Repository navigation
FATAL ERROR: v8::ToLocalChecked Empty MaybeLocal #56531
Description
Activity
In general we provide no guarantee about the usability of the process once builtin prototypes like this are modified, so it's not technically a bug, but poor UX at worst. It would be a UX improvement to at least not crash, if it's not too invasive a change to defend against it.
Marking as good first issues, though just for those who are willing to debug the C++ internals.
Reacted by Juan José, Cristian-Alexandru STAICU, Viktor Podzigun and surajtaghash- addedgood first issueIssues that are suitable for first-time contributors.Issues that are suitable for first-time contributors.c++Issues and PRs that require attention from people who are familiar with C++.Issues and PRs that require attention from people who are familiar with C++.child_processIssues and PRs related to the child_process subsystem.Issues and PRs related to the child_process subsystem.
on Jan 10, 2025 Thanks for the clarification! Imo, crashing the runtime like this is always bad. We had a discussion a while back about supporting the execution of untrusted code in Node.js: #40718. While not necessary true for this particular payload shared by @vdata1 because of the privileged child_process API call, but imagine a use case like Cloudflare's Workers (https://developers.cloudflare.com/workers/reference/security-model/) in which mutually untrusted, low-privilege code share the same process. Attackers can crash co-located Isolates with such payloads. What is the team's view on this? Are these assumptions well documented somewhere?
but imagine a use case like Cloudflare's Workers in which mutually untrusted, low-privilege code share the same process.
You are referencing cloudflare's security model, which differs from the Node.js threat model.
Node.js trusts everything else. Examples include:
...
The code it is asked to run, including JavaScript, WASM and native code, even if said code is dynamically loaded, e.g., all dependencies installed from the npm registry. The code run inherits all the privileges of the execution user.Like vm, child_process is just another regular API that should not be accessible to untrusted code. If a Node.js application allows code provided by a potential attacker to run in the process, the security risk is on them, not on Node.js. Using Node.js for an architecture similar to cloudflare's worker is in itself, a design with security flaws, as Node.js was never built with this security model in mind and after >10 years of organic growth, it would have countless loopholes even if one wants to start amending it for this model now, so it's already a lost cause.
Reacted by Cristian-Alexandru STAICU and surajtaghash(github button mistakes)
Wow, that is a very bold claim in Node.js' threat model! "Node.js trusts everything else. Examples include: ... The code it is asked to run." 😄 Sure, I am aware that Cloudflare runs on a dedicated runtime, not on Node.js, that is why I said "a use case like". Nonetheless, many of us thought that running untrusted code inside a worker or something like isolated-vm is probably safe (see the discussion I linked above). However, that is only the case if the runtime is crash-resilient against arbitrary code, which you say the team does not aim to guarantee. I now see that the isolated-vm project is struggling exactly with this type of issues: https://github.com/laverdet/isolated-vm?tab=readme-ov-file#wishlist
Thanks for the updated comment above. If I understand correctly, it is the combination of a privileged/Node.js API with a crash that makes this a low-priority issue, then. If the same effect can be obtained by a modified prototype like above with something like Math.log(), that would be more interesting for you guys; but, then, we would likely need to take such issues to the v8 team directly. 😄
Happens a lot for plugin installations in Visual Studio Code:
Start: Install plugin project-manager Running command 'D:\projects\_ide\software\default\vscode\vscode\1.104.1\bin\code.cmd' with arguments '--new-window' '--user-data-dir=D:\projects\IDEasy\workspaces\main\.vscode\.userdata' '--extensions-dir=D:\projects\IDEasy\plugins\vscode' 'D:\projects\IDEasy\workspaces\main' '--force' '--install-extension' 'alefragnani.project-manager' failed with exit code 134! Installing extensions... Installing extension 'alefragnani.project-manager'... Extension 'alefragnani.project-manager' v12.8.0 was successfully installed. FATAL ERROR: v8::ToLocalChecked Empty MaybeLocal ----- Native stack trace ----- 1: 00007FF7DF3DB4AA llhttp_get_upgrade+41370 2: 00007FF7DF4B6262 node::OnFatalError+290 3: 00007FF7E48E7D8C v8::Function::NewInstance+540 4: 00007FF7E48E82C4 v8::api_internal::ToLocalEmpty+20 5: 00007FF7DF52CC67 uv_loop_fork+448279 6: 00007FF7DF530B76 uv_loop_fork+464422 7: 00007FF7E33C5E74 v8::internal::compiler::CompilationDependencies::FieldTypeDependencyOffTheRecord+2356100 8: 00007FF7B8ECE198 ----- JavaScript stack trace ----- 1: getPackageScopeConfig (node:internal/modules/package_json_reader:149:33) 2: getPackageJSONURL (node:internal/modules/package_json_reader:225:25) 3: packageResolve (node:internal/modules/esm/resolve:779:81) 4: moduleResolve (node:internal/modules/esm/resolve:865:18) 5: defaultResolve (node:internal/modules/esm/resolve:995:11) 6: nextResolve (node:internal/modules/esm/hooks:748:28) 7: resolve (data:text/javascript;base64,CglleHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZShzcGVjaWZpZXIsIGNvbnRleHQsIG5leHRSZXNvbHZlKSB7CgkJaWYgKHNwZWNpZmllciA9PT0gJ2ZzJykgewoJCQlyZXR1cm4gewoJCQkJZm9ybWF0OiAnYnVpbHRpbicsCgkJCQlzaG9ydENpcmN1aXQ6IHRydWUsCgkJCQl1cmw6ICdub2RlOm9yaWdpbmFsLWZzJwoJCQl9OwoJCX0KCgkJLy8gRGVmZXIgdG8gdGhlIG5leHQgaG9vayBpbiB0aGUgY2hhaW4sIHdoaWNoIHdvdWxkIGJlIHRoZQoJCS8vIE5vZGUuanMgZGVmYXVsdCByZXNvbHZlIGlmIHRoaXMgaXMgdGhlIGxhc3QgdXNlci1zcGVjaWZpZWQgbG9hZGVyLgoJCXJldHVybiBuZXh0UmVzb2x2ZShzcGVjaWZpZXIsIGNvbnRleHQpOwoJfQ==:13:10) 8: nextResolve (node:internal/modules/esm/hooks:748:28) 9: resolve (node:internal/modules/esm/hooks:240:30) 10: handleMessage (node:internal/modules/esm/worker:199:24) Running command 'D:\projects\_ide\software\default\vscode\vscode\1.104.1\bin\code.cmd' with arguments '--new-window' '--user-data-dir=D:\projects\IDEasy\workspaces\main\.vscode\.userdata' '--extensions-dir=D:\projects\IDEasy\plugins\vscode' 'D:\projects\IDEasy\workspaces\main' '--force' '--install-extension' 'alefragnani.project-manager' failed with exit code 134! Step 'Install plugin project-manager' ended with failure. Start: Install plugin asciidoctor Running command 'D:\projects\_ide\software\default\vscode\vscode\1.104.1\bin\code.cmd' with arguments '--new-window' '--user-data-dir=D:\projects\IDEasy\workspaces\main\.vscode\.userdata' '--extensions-dir=D:\projects\IDEasy\plugins\vscode' 'D:\projects\IDEasy\workspaces\main' '--force' '--install-extension' 'asciidoctor.asciidoctor-vscode' failed with exit code 134! Installing extensions... Installing extension 'asciidoctor.asciidoctor-vscode'... Extension 'asciidoctor.asciidoctor-vscode' v3.4.5 was successfully installed. FATAL ERROR: v8::ToLocalChecked Empty MaybeLocal ----- Native stack trace ----- 1: 00007FF7DF3DB4AA llhttp_get_upgrade+41370 2: 00007FF7DF4B6262 node::OnFatalError+290 3: 00007FF7E48E7D8C v8::Function::NewInstance+540 4: 00007FF7E48E82C4 v8::api_internal::ToLocalEmpty+20 5: 00007FF7DF52CC67 uv_loop_fork+448279 6: 00007FF7DF530B76 uv_loop_fork+464422 7: 00007FF7E33C5E74 v8::internal::compiler::CompilationDependencies::FieldTypeDependencyOffTheRecord+2356100 8: 00007FF7B8ECE198 ----- JavaScript stack trace ----- 1: getPackageScopeConfig (node:internal/modules/package_json_reader:149:33) 2: getPackageJSONURL (node:internal/modules/package_json_reader:225:25) 3: packageResolve (node:internal/modules/esm/resolve:779:81) 4: moduleResolve (node:internal/modules/esm/resolve:865:18) 5: defaultResolve (node:internal/modules/esm/resolve:995:11) 6: nextResolve (node:internal/modules/esm/hooks:748:28) 7: resolve (data:text/javascript;base64,CglleHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZShzcGVjaWZpZXIsIGNvbnRleHQsIG5leHRSZXNvbHZlKSB7CgkJaWYgKHNwZWNpZmllciA9PT0gJ2ZzJykgewoJCQlyZXR1cm4gewoJCQkJZm9ybWF0OiAnYnVpbHRpbicsCgkJCQlzaG9ydENpcmN1aXQ6IHRydWUsCgkJCQl1cmw6ICdub2RlOm9yaWdpbmFsLWZzJwoJCQl9OwoJCX0KCgkJLy8gRGVmZXIgdG8gdGhlIG5leHQgaG9vayBpbiB0aGUgY2hhaW4sIHdoaWNoIHdvdWxkIGJlIHRoZQoJCS8vIE5vZGUuanMgZGVmYXVsdCByZXNvbHZlIGlmIHRoaXMgaXMgdGhlIGxhc3QgdXNlci1zcGVjaWZpZWQgbG9hZGVyLgoJCXJldHVybiBuZXh0UmVzb2x2ZShzcGVjaWZpZXIsIGNvbnRleHQpOwoJfQ==:13:10) 8: nextResolve (node:internal/modules/esm/hooks:748:28) 9: resolve (node:internal/modules/esm/hooks:240:30) 10: handleMessage (node:internal/modules/esm/worker:199:24) Running command 'D:\projects\_ide\software\default\vscode\vscode\1.104.1\bin\code.cmd' with arguments '--new-window' '--user-data-dir=D:\projects\IDEasy\workspaces\main\.vscode\.userdata' '--extensions-dir=D:\projects\IDEasy\plugins\vscode' 'D:\projects\IDEasy\workspaces\main' '--force' '--install-extension' 'asciidoctor.asciidoctor-vscode' failed with exit code 134! Step 'Install plugin asciidoctor' ended with failure.Also for
pretty-ts-errorsplugin.Reacted by Abdullah AlHamdan, Jupiter and Stefan Heinemannis this issue still open?
I'd like to work on this issue.
Hello! I'm looking for ways to contribute to to nodejs, can i be assigned to work on this?
Opened a fix PR here: https://github.com/nodejs/node/pull/61978\n\nThis adds validation for non-object stdio entries in ProcessWrap::ParseStdioOptions() and includes a regression test for the Array.prototype setter pollution case.
github-actions commented
on Jul 20, 2026 on Jul 20, 2026 – with GitHub ActionsContributorMore actionsThis issue has been marked as stale due to 90 days of inactivity.
It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.- addedstaleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.Issues and PRs marked stale due to inactivity and scheduled for automatic closure.
on Jul 20, 2026 Thanks for the report! I was able to reproduce this. Modifying
Array.prototype[2](orArray.prototypein general) breaks internal C++ assumptions when V8 arrays are constructed or accessed (often seen inchild_processwhen arguments/env arrays are being converted to V8 arrays). TheToLocalChecked()failure happens because V8 throws a JS exception when setting the element, resulting in an emptyMaybeLocal. Node core usually protects against this by usingSetRealNamedPropertyor ensuring prototype pollution doesn't break array initialization. I will try to track down the exact V8 call insrc/node_child_process.ccorsrc/env.ccthat is throwing.- removedstaleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.Issues and PRs marked stale due to inactivity and scheduled for automatic closure.
on Jul 31, 2026 Hi! I’m interested in investigating this issue as my first contribution to Node.js. Before I begin, could a maintainer please confirm whether the issue is still open for contribution and point me toward any relevant files or tests I should review? Thank you!
Reacted by Hesam DanaeeI would like to contribute with this as my first issue.
Hi, I’d like to investigate this issue. I plan to reproduce the crash on the current main branch, trace where an empty MaybeLocal reaches ToLocalChecked, determine whether the affected child-process path can handle the failure without terminating the runtime, and add a regression test for the provided reproduction. Is anyone currently working on this, and would maintainers prefer an initial diagnostic PR or a complete fix?
- added a commit that references this issue
on Aug 25, 2026 - added a commit that references this issue
on Aug 29, 2026 - added a commit that references this issue
on Sep 4, 2026 In more recent version of Node the above example from the issue description is throwing the following error now:
% node test.js node:internal/child_process:396 const err = this._handle.spawn(options); ^ TypeError: Cannot read properties of undefined (reading 'type') at ChildProcess.spawn (node:internal/child_process:396:28) at spawn (node:child_process:796:9) at Object.execFile (node:child_process:349:17) at exec (node:child_process:236:25) at /Users/viktorpodzigun/workspace/test/test.js:8:3 at Object.<anonymous> (/Users/viktorpodzigun/workspace/test/test.js:11:3) at Module._compile (node:internal/modules/cjs/loader:1812:14) at Object..js (node:internal/modules/cjs/loader:1943:10) at Module.load (node:internal/modules/cjs/loader:1533:32) at Module._load (node:internal/modules/cjs/loader:1335:12) Node.js v24.14.0
Bun is also freezing in this case: oven-sh/bun#42723
What should be the proper handling then? Should warning also be written to the console when modifying Array prototype? 🤔
Version
v23.6.0
Platform
Subsystem
No response
What steps will reproduce the bug?
Hi,
I would like to report a bug, it can be reproduced by running the PoC below:
Regards,
AH
How often does it reproduce? Is there a required condition?
It reproduces anytime by simply running the given PoC on the given Node.js version.
What is the expected behavior? Why is that the expected behavior?
It is a crash.
What do you see instead?
FATAL ERROR: v8::ToLocalChecked Empty MaybeLocal
Additional information
No response