Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

spawn drops an own `__proto__` environment entry

Open Beginner friendly
#993 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@nikolay-dementiev is already working on this.

Since Oct 15, 2026.

  • #994 by @nikolay-dementiev — open

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
72/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
nodejs, typescript

Research direction

Start with the assign helper in src/utils.ts, which copies options.env into the target with plain property assignment, so an own __proto__ key hits the prototype setter. Follow how spawn passes that env on to _parseEnv. Run the reproduction from the issue and check whether the child prints true:selected-value. Done when a __proto__ entry survives the copy, using defineProperty or an equivalent, and the reproduction passes.

Written by the indexing model from the issue text.

Description

Environment details

  • OS: macOS (arm64)
  • OS version: 26.5.2
  • node-pty version: 1.1.0 (Node.js 26.3.0)

Issue description

spawn copies options.env with assign (src/utils.ts):

sources.forEach(source => Object.keys(source).forEach(key => target[key] = source[key]));

When the source object has an own __proto__ key (for example one that came from JSON.parse), target["__proto__"] = value invokes the Object.prototype.__proto__ setter instead of creating a property. A string value is ignored, so the variable never reaches _parseEnv and the child starts without it. child_process passes the same object through.

const pty = require("node-pty");
const env = { ...process.env, ...JSON.parse('{"__proto__":"selected-value"}') };
console.log(Object.hasOwn(env, "__proto__")); // true
const child = "console.log(Object.hasOwn(process.env, '__proto__') + ':' + process.env['__proto__'])";
pty.spawn(process.execPath, ["-e", child], { env }).onData((d) => process.stdout.write(d));
// prints: false:[object Object]

With child_process.execFileSync(process.execPath, ["-e", child], { env }) the child prints true:selected-value, and launching through /usr/bin/env __proto__=selected-value node -e ... under node-pty does too, so the operating system and Node accept the name.

Copying with Object.defineProperty(target, key, { value: source[key], enumerable: true, writable: true, configurable: true }), or building the key=value pairs from the source keys directly, keeps the entry.

A downstream process-capture tool hit this in morluto/rea#3338.

Dominant language
TypeScript
Stars
2k
Forks
343
Avg merge
22h 24m
Merged PRs (30d)
6

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from microsoft/node-pty

All issues in microsoft/node-pty

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.