Every CVE Search/ Get API key

CVE-2026-92945

vm2 before 3.11.7 Module Allowlist Bypass via Prefix Matching

2.3 LowFix available

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.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
High
Privileges needed
Low
User interaction
None

What an attacker can affect

Confidentiality
Low
Integrity
Low
Availability
None

Exploit likelihood

0.28%Up 0.1 points since Sep 18, 2026
90%50%10%1%

What each source reports

CVE List Score used 2.3

vm2 before 3.11.7 Module Allowlist Bypass via Prefix Matching

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.

Record
CVE-2026-92945
CVSS 4.0
2.3 LowCVSS:4.0/AV:N/AC:H/AT:P/PR:L/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N
CVSS 3.1
4.2 MediumCVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:N
Weakness
CWE-22
Updated
2026-11-02
EUVDEUVD-2026-81594 2.3

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.

Record
EUVD-2026-81594
CVSS 4.0
2.3 LowCVSS:4.0/AV:N/AC:H/AT:P/PR:L/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-7q3f-wx44-378m 4.2

vm2: External module allowlist uses a raw prefix test, so a prefix-sharing sibling package is treated as allowlisted

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:

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:

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.

Record
GHSA-7q3f-wx44-378m
CVSS 3.1
4.2 MediumCVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:N
Weakness
CWE-22, CWE-863
Updated
2026-11-02
GitHub AdvisoriesGHSA-8mvv-mcc3-xwhh 2.3

Duplicate Advisory: External module allowlist uses a raw prefix test, so a prefix-sharing sibling package is treated as allowlisted

Duplicate Advisory

This advisory has been withdrawn because it is a duplicate of GHSA-7q3f-wx44-378m. This link is maintained to preserve external references.

Original Description

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.

Record
GHSA-8mvv-mcc3-xwhh
CVSS 4.0
2.3 LowCVSS: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:X
CVSS 3.1
4.2 MediumCVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:N
Weakness
CWE-22
Updated
2026-11-02
NVD 2.3

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.

Record
CVE-2026-92945
CVSS 4.0
2.3 LowCVSS: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:X
CVSS 3.1
4.2 MediumCVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:N
Weakness
CWE-22
Updated
2026-11-02
OSV 2.3

vm2 before 3.11.7 Module Allowlist Bypass via Prefix Matching

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.

Record
CVE-2026-92945
CVSS 4.0
2.3 LowCVSS:4.0/AV:N/AC:H/AT:P/PR:L/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N
Weakness
CWE-22
Updated
2026-11-02
Show 4 moreShow less
OSVGHSA-7q3f-wx44-378m 4.2

vm2: External module allowlist uses a raw prefix test, so a prefix-sharing sibling package is treated as allowlisted

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:

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:

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.

Record
GHSA-7q3f-wx44-378m
CVSS 3.1
4.2 MediumCVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:N
Weakness
CWE-22, CWE-863
Updated
2026-11-02
OSVGHSA-8mvv-mcc3-xwhh 2.3

Duplicate Advisory: External module allowlist uses a raw prefix test, so a prefix-sharing sibling package is treated as allowlisted

Duplicate Advisory

This advisory has been withdrawn because it is a duplicate of GHSA-7q3f-wx44-378m. This link is maintained to preserve external references.

Original Description

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.

Record
GHSA-8mvv-mcc3-xwhh
CVSS 4.0
2.3 LowCVSS: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:X
CVSS 3.1
4.2 MediumCVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:N
Weakness
CWE-22
Updated
2026-11-02
OSVCLSA-2026-1790888247 No score

TuxCare security update for vm2 (15 CVEs)

TuxCare rebuilt vm2 to address 15 CVEs. Fixed in 3.11.5-tuxcare.3.

Record
CLSA-2026-1790888247
Updated
2026-11-02
OSVCLSA-2026-1790937673 No score

TuxCare security update for vm2 (7 CVEs)

TuxCare rebuilt vm2 to address 7 CVEs. Fixed in 3.10.0-tuxcare.2.

Record
CLSA-2026-1790937673
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
vm2
npm
through 3.11.6
3.11.7
vm2
TuxCare:npm
From an advisory covering 13 CVEs
3.11.5-tuxcare.0 up to 3.11.5-tuxcare.3, plus listed versions
3.11.53.11.5-tuxcare.13.11.5-tuxcare.2
3.11.5-tuxcare.3
vm2
TuxCare:npm
From an advisory covering 6 CVEs
3.10.0-tuxcare.0 up to 3.10.0-tuxcare.2, plus listed versions
3.10.03.10.0-tuxcare.1
3.10.0-tuxcare.2
vm2
npm
before 3.11.7
3.11.7

History

History
RecordedChangedSources
affected, facts
affected
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-92945 is a low vulnerability (CVSS 2.3) in Patriksimek Vm2, published September 17, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.28%, the 20th percentile. Fixed in vm2 3.11.7.

References

MoveEnter Open