spawn drops an own `__proto__` environment entry
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
- Domain
- operating-systems
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
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from microsoft/node-pty
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
ConPTY/TSFN exit callback aborts the process during environment teardown — fixable with NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS (same root cause as #904)Possibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
microsoft/node-pty#951 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 1 day
All issues in microsoft/node-pty
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
QuantumNous/new-api#7839 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
Maintainers usually reply within 1 day
-
bug p2 triaged
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
getpaseo/paseo#7071 · 1 comment ·
Maintainers usually reply within 1 day
-
test: make the #3408 Claude OAuth token fixture obviously fake so secret scanners stop flagging itOpen
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
code-yeongyu/senpi#3436 ·
Maintainers usually reply within 1 day
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Difficulty 1/5 Under an hour Newbie friendliness 78/100
lingdojo/kana-dojo#32505 · 1 comment · 5 reactions ·
Maintainers usually reply within 1 day