Untrusted script executed in Node vm without memory limit or restricted host surface
User-controlled orderLinesData is evaluated through notevil inside a Node vm context that has only a wall-clock timeout — no memory budget and no isolation of host globals, so the runtime is unsuitable as a sandbox for untrusted code.
The sandbox at lines 21–24 instantiates a Node vm context and runs safeEval(orderLinesData):
const sandbox = { safeEval, orderLinesData }
vm.createContext(sandbox)
vm.runInContext('safeEval(orderLinesData)', sandbox, { timeout: 2000 })
Reviewing against the required-mitigations checklist:
- Time budget: present (
timeout: 2000). - Memory budget: absent. The vm module does not expose one; only
isolated-vmdoes. A large allocation in the evaluated script will consume the host's heap. - No host references: the sandbox is created without a frozen prototype chain; the
vmmodule shares the host realm's intrinsics. Code running inside can walk up viathis.constructor.constructor('return process')()and similar tricks — a well-known vm escape that Node maintainers explicitly call out as expected behavior. - API-surface restriction: the sandbox additionally exposes
safeEval(notevil), which itself has had multiple bypass CVEs.
The correct mitigation is isolated-vm with memoryLimit, compileScript, and script.run(ctx, { timeout }), plus an explicit context that exposes only the values the use case needs.
Submit POST /b2b/v2/orders with a notevil-bypass payload (or trivially Array(2**30).fill(0) to OOM the host) in orderLinesData. The Node vm timeout fires for infinite loops but does not stop allocation-based attacks or in-flight escape payloads that complete within 2 seconds.
Memory-exhaustion DoS of the entire Node process (one request can crash the server), plus the RCE potential described in the companion rce finding. Affects any caller able to reach the B2B order endpoint.
The code at lines 21-23 literally matches the finding: vm.createContext(sandbox) followed by vm.runInContext('safeEval(orderLinesData)', sandbox, { timeout: 2000 }) with user-controlled body.orderLinesData. Node's vm module is not a security boundary (documented by Node maintainers), has no memory limit option, and the wall-clock timeout does not stop allocation-based DoS — a payload like Array(2**30).fill(0) would exhaust the host heap. Additionally, safeEval (notevil) is exposed in the sandbox and has known bypass CVEs, and the scope explicitly says to treat findings as if production. The exploit chain is reachable via the B2B order endpoint without further auth gating beyond the challenge-enabled flag.
The sink is reached by sending a POST to the B2B order endpoint with an orderLinesData body field — pure network input, no auth check is visible in the handler that gates vm.runInContext, and no victim interaction is needed. Worst-plausible exploitation is a notevil-bypass / vm-escape payload (this.constructor.constructor('return process')()) that escapes the Node vm realm into the host process, which crosses the sandbox's security authority into the host runtime (Scope:C) and yields full RCE — hence C/I/A all High. Even without an escape, the missing memory budget allows a single request (e.g. Array(2**30).fill(0)) to OOM-crash the entire Node process, independently justifying A:H. The conditional isChallengeEnabled gate is configuration, not authentication, so PR remains N for the worst code-visible state.
- CWE-913
- CWE-1336
- https://nodejs.org/api/vm.html#vm-executing-javascript