Deny the test builtin family, a host-process launcher
fix(GHSA-qhwx-74w5-xhxq): deny the test builtin family, a host-process launcher
Deny the test builtin family, a host-process launcher415339-fix-deny-the-test-builtin-family-a-cve-2026-92948fixdeny test builtin family host process
Committed by patriksimek-bot
commit message
fix(GHSA-qhwx-74w5-xhxq): deny the test builtin family, a host-process launcher
`node:test`'s documented `run({ files, execArgv })` API starts a SEPARATE host
Node process for process-isolated test execution and forwards `execArgv` to it
verbatim, so `execArgv: ['--eval=<js>']` executes attacker JavaScript in an
unsandboxed host process. `test` was absent from `DANGEROUS_BUILTINS`, and on
Node 18+ `require('module').builtinModules` lists `node:test` and
`node:test/reporters` with the `node:` prefix, so both `builtin: ['node:test']`
and `builtin: ['*']` admitted the real host module — host RCE from a NodeVM
with no `fs`, `child_process`, `module`, or `process` of its own.
Chokepoint: `lib/builtin.js` adds `test` to `DANGEROUS_BUILTINS`. Because
`BUILTIN_MODULES` is built by filtering `nmod.builtinModules` through
`isDangerousBuiltin`, the whole family leaves the source list, so it is gone
from `'*'` expansion and from the explicit-allowlist branch alike, and
`addDefaultBuiltin` refuses it again on the low-level registration path.
Subpath coverage (`node:test/reporters`) falls out of the existing
family-prefix match with no special case. `isDangerousBuiltin` additionally
strips repeated `node:` prefixes so the doubled `node:node:test` spelling
cannot survive as an unnormalized denylist miss. This restores the Category 21
invariant that no host-passthrough process-spawning primitive is reachable
under any builtin configuration.
`isDangerousBuiltin` (the hard, non-configurable denylist) is a distinct
chokepoint from `isBuiltinDenied` (user-supplied negative deny tokens,
GHSA-8686-vhfx-7r3j / GHSA-6rh5-qq4q-97xh); this change does not touch the
latter's shared semantics.
Tests: test/ghsa/GHSA-qhwx-74w5-xhxq/repro.js — explicit-allow denial across
all four spellings, wildcard denial, a spawn oracle asserting no host process
wrote its marker file, and a no-over-block check that a benign builtin still
loads.
Docs: docs/ATTACKS.md Category 21 extended (description bullet, canonical
example, mitigation point 7, detection rules) plus a "How The Bridge Defends"
row. No version bump.Editor assessment
This commit patches CVE-2026-92948. The body explains the node:test execArgv host-process launch, why both the explicit and wildcard builtin paths admitted the real module, how adding test to DANGEROUS_BUILTINS removes the family including subpaths, and what the spawn-oracle repro asserts. The only formal issue is the GHSA-id scope, which is an advisory identifier rather than a codebase area; that CCv1 violation is what keeps an otherwise strong message at 3. The denial applies to every spelling and to the wildcard path; stating that breadth in the body would show the fix is complete.