helperPath replace produces 'app.asar.unpacked.unpacked/…' when caller is itself in app.asar.unpacked → posix_spawnp ENOENT
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 76/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- electron, node.js, typescript
- Domain
- operating-systems, tooling
Research direction
Start in src/unixTerminal.ts at the helperPath replacements and reproduce the reported path transformation with a caller already under app.asar.unpacked. Ensure an already-unpacked helper path is not rewritten again, then verify the resulting spawn-helper path exists and launches in the described Electron or Node.js setup.
Written by the indexing model from the issue text.
Description
Summary
src/unixTerminal.ts#L19-L20 resolves helperPath, then runs:
helperPath = helperPath.replace('app.asar', 'app.asar.unpacked');
helperPath = helperPath.replace('node_modules.asar', 'node_modules.asar.unpacked');
String.prototype.replace with a string argument replaces the first occurrence. When the resolved helperPath already contains app.asar.unpacked/… (because the caller of node-pty lives inside app.asar.unpacked too, not inside app.asar), the substring app.asar matches the prefix of app.asar.unpacked and the replace produces a path like …/app.asar.unpacked.unpacked/node_modules/node-pty/build/Release/spawn-helper, which doesn't exist on disk.
posix_spawn then fails with ENOENT and node-pty throws the generic posix_spawnp failed., which is widely misdiagnosed as a code-signing / hardened-runtime / sandbox problem.
Reproduction
// simulate what unixTerminal.js does when the caller is itself unpacked
let helperPath = '/path/to/MyApp.app/Contents/Resources/app.asar.unpacked/node_modules/node-pty/build/Release/spawn-helper';
helperPath = helperPath.replace('app.asar', 'app.asar.unpacked');
console.log(helperPath);
// → /path/to/MyApp.app/Contents/Resources/app.asar.unpacked.unpacked/node_modules/node-pty/build/Release/spawn-helper
// ^^^^^^^^^^^^^^^^^^^ bogus
This affects packaged Electron apps that:
- Run node-pty from a separate child process spawned with
ELECTRON_RUN_AS_NODE=1(which strips Electron's asar shim and uses plain Node module resolution), AND - Have that child binary itself living in
app.asar.unpacked.
In that combination __dirname resolves to the real app.asar.unpacked/… filesystem path rather than the asar-shimmed app.asar/… path, so the replace runs against a string that already contains app.asar.unpacked. VS Code, Theia, etc. don't hit this because they call node-pty from the Electron main/renderer process where the asar shim is in play and __dirname reports app.asar/….
Suggested fix
Guard each replace so it doesn't fire when the unpacked path is already present:
if (helperPath.indexOf('app.asar.unpacked') === -1) {
helperPath = helperPath.replace('app.asar', 'app.asar.unpacked');
}
if (helperPath.indexOf('node_modules.asar.unpacked') === -1) {
helperPath = helperPath.replace('node_modules.asar', 'node_modules.asar.unpacked');
}
Or anchor the replace with a path-separator regex, e.g. .replace(/app\.asar([\\/])/, 'app.asar.unpacked$1').
Bonus: misleading error
src/unix/pty.cc#L373 reports posix_spawnp failed. without the underlying errno. Surfacing strerror(err) (this case would say No such file or directory) would have made this trivially diagnosable instead of sending people down the code-signing rabbit hole. Happy to send a separate PR for that.
Environment
- node-pty 1.1.0
- macOS arm64, Electron 32 (also reproduces with system Node ≥18 when require'ing node-pty from a path inside
app.asar.unpacked)
- Dominant language
- TypeScript
- Stars
- 2k
- Forks
- 337
- Avg merge
- 21h 58m
- Merged PRs (30d)
- 3
Contributor 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
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
All issues in microsoft/node-pty
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
copse-dev/agent-pane#2953 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Eynzof/Hermes-CN-Desktop#610 ·
-
bug clawsweeper:linked-pr-open clawsweeper:needs-live-repro clawsweeper:no-new-fix-pr impact:message-loss issue-rating: 🐚 platinum hermit P2 regression
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
calcite-components needs triage refactor
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Esri/calcite-design-system#15203 ·