CVE-2026-92945

mediumpriority · track · 0OT risk · elevatedEPSS 0.003 · 20 %ileDERUUS
grimoire priorityP3 · Track
Exploitable?
—
no known exploitation
Likely / severe?
0.28% (20th) EPSS
CVSS 4.2 · medium
Is it mine?
4 products
Check your exposure
Who says so?
3 sources
fstec_bdu · cert_bund · osv

EPSS · scored 2026-10-27

vm2 before 3.11.7 contains a module allowlist bypass vulnerability in isPathAllowedForModule that uses raw string prefix matching instead of boundary-anchored comparison. Attackers can reach non-allowlisted packages sharing a prefix with allowlisted modules by performing relative requires from allowlisted packages when transitive loading is disabled.

01

cvss

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

4.2
010

base score 0–10 · higher = more severe · hover a vector to decode⚠ sources disagree · low–medium · 0.6–4.2

v3.14.2mediumAV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:Nsecondary · FSTEC (BDU) RU
v3.14.2mediumCVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:Nsecondary · disclosure@vulncheck.comexploitability 1.6 · impact 2.5
v3.14.2mediumCVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:Nsecondary · OSV
v4.02.3lowCVSS:4.0/AV:N/AC:H/AT:P/PR:L/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N/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.00.6lowCVSS:4.0/AV:N/AC:H/AT:P/PR:L/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N/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.

Trackcoordinatorcisa_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-7q3f-wx44-378mvm2: External module allowlist uses a raw prefix test, so a prefix-sharing sibling package is treated as allowlisted2026-10-01ghsa · osvUS

    ## Summary `isPathAllowedForModule` decides whether a resolved path belongs to an allowlisted external module using a raw string prefix test. `node_modules/foo2` starts with `node_modules/foo`, so a package whose name merely shares a prefix with an allowlisted one is treated as being inside it, and a relative require from the allowlisted package reaches it even with transitive loading disabled. ## Where it is `lib/resolver-compat.js`, lines 122 to 132, quoted from HEAD `7a1f5100b96f48d34e0fe104ab37c0acc5944f92`: ```js isPathAllowedForModule(path, mod) { if (!super.isPathAllowed(path)) return false; if (mod) { if (mod.allowTransitive) return true; if (path.startsWith(mod.path)) { const rem = path.slice(mod.path.length); if (!/(?:^|[\\/])node_modules(?:$|[\\/])/.test(rem)) return true; } } return this.externals.some(regex => regex.test(path)); } ``` With `mod.path` of `.../node_modules/foo` and a resolved path of `.../node_modules/foo2/index.js`, `startsWith` is true and `rem` is `2/index.js`, which contains no `node_modules` segment, so the function returns true. The `node_modules` test in `rem` is what stops a genuine transitive dependency from slipping through. It does not stop a sibling, because a sibling's remainder never contains that segment. ## Impact Code running in `NodeVM` under an external module allowlist with `transitive: false` can reach a package that was not allowlisted, provided an allowlisted package performs a relative require to a prefix-sharing sibling. Two preconditions are worth stating plainly rather than leaving implicit. The deployment must already have such a package layout, and an allowlisted package must have a reachable code path that does the relative require. This is not something the attacker creates; it is something they find. That narrows it considerably, and it is why I have not scored it higher. ## Reachability `NodeVM.run` at `lib/nodevm.js:506` executes the script. `require` comes from `createRequireForModule` at `lib/setup-node-sandbox.js:168-172` and reaches the resolver callback at `lib/nodevm.js:380-384`. `LegacyResolver.resolveFull` at `lib/resolver-compat.js:145-160` sets `currMod` for direct requires, the relative specifier resolves through `DefaultResolver.resolveFull` and `tryFile` at `lib/resolver.js:327-330`, and the authorization decision lands on the function above. ## Suggested fix Require a separator after the prefix, so a sibling cannot match: ```js if (path === mod.path || path.startsWith(mod.path + path.sep)) { ``` That is the same anchoring the `rem` regex already applies to `node_modules`, applied one level earlier.

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