CVE-2026-92951
vm2 before 3.11.7 Module Allowlist Bypass via Custom Resolver
vm2 before 3.11.7 contains an incorrect authorization vulnerability in the external package allowlist check that uses non-exact substring matching instead of full package-name boundary validation. Attackers can bypass the allowlist by requiring a colliding package name that contains an allowlisted package substring, causing vm2 to load and execute unauthorized host packages in the host context.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
9.4
vm2 before 3.11.7 Module Allowlist Bypass via Custom Resolver
vm2 before 3.11.7 contains an incorrect authorization vulnerability in the external package allowlist check that uses non-exact substring matching instead of full package-name boundary validation. Attackers can bypass the allowlist by requiring a colliding package name that contains an allowlisted package substring, causing vm2 to load and execute unauthorized host packages in the host context.
- Record
CVE-2026-92951- CVSS 4.0
- 9.4 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H - CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-706
- Updated
- 2026-11-02
EUVDEUVD-2026-81600
9.4
vm2 before 3.11.7 contains an incorrect authorization vulnerability in the external package allowlist check that uses non-exact substring matching instead of full package-name boundary validation. Attackers can bypass the allowlist by requiring a colliding package name that contains an allowlisted package substring, causing vm2 to load and execute unauthorized host packages in the host context.
- Record
EUVD-2026-81600- CVSS 4.0
- 9.4 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-6fvh-fgmg-3x7v
9.4
Duplicate Advisory: vm2 Custom Module Resolver Can Bypass the External Package Allowlist by Loading a Colliding Host Package
Duplicate Advisory
This advisory has been withdrawn because it is a duplicate of GHSA-c48m-32m9-vx93. This link is maintained to preserve external references.
Original Description
vm2 before 3.11.7 contains an incorrect authorization vulnerability in the external package allowlist check that uses non-exact substring matching instead of full package-name boundary validation. Attackers can bypass the allowlist by requiring a colliding package name that contains an allowlisted package substring, causing vm2 to load and execute unauthorized host packages in the host context.
- Record
GHSA-6fvh-fgmg-3x7v- CVSS 4.0
- 9.4 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/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
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-706
- Updated
- 2026-11-02
GitHub AdvisoriesGHSA-c48m-32m9-vx93
9.9
vm2 Custom Module Resolver Can Bypass the External Package Allowlist by Loading a Colliding Host Package
Summary
vm2 is a sandbox library for isolating and executing untrusted JavaScript code inside a Node.js process. It can restrict access to built-in modules and external packages.
When NodeVM enables an external allowlist together with a custom resolve callback, vm2 checks the requested package name with a non-exact match. For example, if the allowlist only permits left-pad, an attacker can still bypass the check with a colliding package name such as evil-left-pad, because it contains the allowlisted name.
If the colliding package already exists in a host path resolvable by the custom resolver, or if the target application's custom resolver / dependency-management workflow downloads the package and places it in a resolvable path, vm2 loads and executes that package in the host context. This lets sandboxed code bypass the module allowlist and may further lead to host code execution.
Details
NodeVM supports require.external to configure which external npm packages sandboxed code may load. It also supports a custom resolver through require.resolve. This combination is commonly used in business plugin systems, user-script platforms, or sandbox execution environments: the application allows only a small set of trusted dependencies while using a custom resolver that points to the application's own package directory.
The vulnerability is in the allowlist pre-check logic before the custom resolver is called. vm2 generates a regular expression from the external allowlist and uses it to check the original package name supplied by sandboxed code. However, the regular expression is not anchored to the full package-name boundary, so it performs a substring match on the original package name.
For example, with the following configuration:
new NodeVM({
require: {
external: ['left-pad'],
resolve: id => require.resolve(id, { paths: [customRoot] }),
context: 'host',
builtin: []
}
})
The intended policy is that sandboxed code can only load left-pad. However, because vm2 uses a non-exact match similar to /left\-pad/ for the requested package name, names such as evil-left-pad and left-pad-backdoor also pass the allowlist pre-check.
After evil-left-pad passes the check, vm2 calls the custom resolver configured by the application. If the resolver can find that colliding package in a host-resolvable path, vm2 adds the returned path to the loadable list and, in context: 'host' mode, loads the package with the host require(). At that point, the package's top-level code executes in the host context instead of being constrained by sandbox restrictions such as NodeVM's builtin: [].
In local verification, the PoC only allows external: ['left-pad'] and sets builtin: [], so sandboxed code cannot directly load child_process. However, after the sandboxed code executes require('evil-left-pad'), vm2 still loads the colliding package from a host path. The colliding package's top-level code successfully invokes the host child_process module and prints HOST_EXEC.
This issue does not mean that vm2 automatically downloads malicious packages from npm at runtime. The attack requires the colliding package to already be in a path resolvable by the custom resolver, or for the target application's own dependency resolution / download workflow to place that package in such a path. This precondition limits the affected scenarios, but it does not change the core vulnerability: the external allowlist is not enforced against complete package-name boundaries, allowing sandboxed code to load a host package that the application did not authorize.
PoC
An independent PoC is attached in the poc directory. The PoC installs vm2 3.11.5, creates a temporary host package directory, and writes an unauthorized evil-left-pad package into it.
Run the following from the poc directory:
npm install
node poc.js
When the vulnerability is present, the output is similar…
- Record
GHSA-c48m-32m9-vx93- CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-706, CWE-829, CWE-863
- Updated
- 2026-11-02
NVD
9.4
vm2 before 3.11.7 contains an incorrect authorization vulnerability in the external package allowlist check that uses non-exact substring matching instead of full package-name boundary validation. Attackers can bypass the allowlist by requiring a colliding package name that contains an allowlisted package substring, causing vm2 to load and execute unauthorized host packages in the host context.
- Record
CVE-2026-92951- CVSS 4.0
- 9.4 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/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
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-706
- Updated
- 2026-11-02
OSV
9.4
vm2 before 3.11.7 Module Allowlist Bypass via Custom Resolver
vm2 before 3.11.7 contains an incorrect authorization vulnerability in the external package allowlist check that uses non-exact substring matching instead of full package-name boundary validation. Attackers can bypass the allowlist by requiring a colliding package name that contains an allowlisted package substring, causing vm2 to load and execute unauthorized host packages in the host context.
- Record
CVE-2026-92951- CVSS 4.0
- 9.4 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H - Weakness
- CWE-706
- Updated
- 2026-11-02
Show 5 moreShow less
OSVGHSA-6fvh-fgmg-3x7v
9.4
Duplicate Advisory: vm2 Custom Module Resolver Can Bypass the External Package Allowlist by Loading a Colliding Host Package
Duplicate Advisory
This advisory has been withdrawn because it is a duplicate of GHSA-c48m-32m9-vx93. This link is maintained to preserve external references.
Original Description
vm2 before 3.11.7 contains an incorrect authorization vulnerability in the external package allowlist check that uses non-exact substring matching instead of full package-name boundary validation. Attackers can bypass the allowlist by requiring a colliding package name that contains an allowlisted package substring, causing vm2 to load and execute unauthorized host packages in the host context.
- Record
GHSA-6fvh-fgmg-3x7v- CVSS 4.0
- 9.4 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/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
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-706
- Updated
- 2026-11-02
OSVGHSA-c48m-32m9-vx93
9.9
vm2 Custom Module Resolver Can Bypass the External Package Allowlist by Loading a Colliding Host Package
Summary
vm2 is a sandbox library for isolating and executing untrusted JavaScript code inside a Node.js process. It can restrict access to built-in modules and external packages.
When NodeVM enables an external allowlist together with a custom resolve callback, vm2 checks the requested package name with a non-exact match. For example, if the allowlist only permits left-pad, an attacker can still bypass the check with a colliding package name such as evil-left-pad, because it contains the allowlisted name.
If the colliding package already exists in a host path resolvable by the custom resolver, or if the target application's custom resolver / dependency-management workflow downloads the package and places it in a resolvable path, vm2 loads and executes that package in the host context. This lets sandboxed code bypass the module allowlist and may further lead to host code execution.
Details
NodeVM supports require.external to configure which external npm packages sandboxed code may load. It also supports a custom resolver through require.resolve. This combination is commonly used in business plugin systems, user-script platforms, or sandbox execution environments: the application allows only a small set of trusted dependencies while using a custom resolver that points to the application's own package directory.
The vulnerability is in the allowlist pre-check logic before the custom resolver is called. vm2 generates a regular expression from the external allowlist and uses it to check the original package name supplied by sandboxed code. However, the regular expression is not anchored to the full package-name boundary, so it performs a substring match on the original package name.
For example, with the following configuration:
new NodeVM({
require: {
external: ['left-pad'],
resolve: id => require.resolve(id, { paths: [customRoot] }),
context: 'host',
builtin: []
}
})
The intended policy is that sandboxed code can only load left-pad. However, because vm2 uses a non-exact match similar to /left\-pad/ for the requested package name, names such as evil-left-pad and left-pad-backdoor also pass the allowlist pre-check.
After evil-left-pad passes the check, vm2 calls the custom resolver configured by the application. If the resolver can find that colliding package in a host-resolvable path, vm2 adds the returned path to the loadable list and, in context: 'host' mode, loads the package with the host require(). At that point, the package's top-level code executes in the host context instead of being constrained by sandbox restrictions such as NodeVM's builtin: [].
In local verification, the PoC only allows external: ['left-pad'] and sets builtin: [], so sandboxed code cannot directly load child_process. However, after the sandboxed code executes require('evil-left-pad'), vm2 still loads the colliding package from a host path. The colliding package's top-level code successfully invokes the host child_process module and prints HOST_EXEC.
This issue does not mean that vm2 automatically downloads malicious packages from npm at runtime. The attack requires the colliding package to already be in a path resolvable by the custom resolver, or for the target application's own dependency resolution / download workflow to place that package in such a path. This precondition limits the affected scenarios, but it does not change the core vulnerability: the external allowlist is not enforced against complete package-name boundaries, allowing sandboxed code to load a host package that the application did not authorize.
PoC
An independent PoC is attached in the poc directory. The PoC installs vm2 3.11.5, creates a temporary host package directory, and writes an unauthorized evil-left-pad package into it.
Run the following from the poc directory:
npm install
node poc.js
When the vulnerability is present, the output is similar…
- Record
GHSA-c48m-32m9-vx93- CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-706, CWE-829, CWE-863
- 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
OSVROOT-APP-NPM-CVE-2026-92951 No score
CVE-2026-92951 in vm2 - Patched by Root
Root has patched CVE-2026-92951 in the vm2 package for Root:npm. Multiple fixed versions available.
- Record
ROOT-APP-NPM-CVE-2026-92951- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
vm2npm |
through 3.11.6 | 3.11.7 |
vm2TuxCare: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 |
vm2TuxCare: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 |
vm2npm |
before 3.11.7 | 3.11.7 |
vm2Root:npm |
before 3.10.5-aikido.8 | 3.10.5-aikido.83.11.6-aikido.1 |
@rootio/vm2Root:npm |
before 3.10.5-root.io.8 | 3.10.5-root.io.83.11.6-root.io.1 |
History
| Recorded | Changed | Sources |
|---|---|---|
| affected, facts | ||
| affected | ||
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-92951 is a critical vulnerability (CVSS 9.4) 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.47%, the 40th percentile. Fixed in vm2 3.11.7.
References
github.com/patriksimek/vm2/security/advisories/GHSA-c48m-32m9-vx93
vulncheck.com/advisories/vm2-before-3.11.7-module-allowlist-bypass-via-custom-resolver
nvd.nist.gov/vuln/detail/CVE-2026-92951
github.com/advisories/GHSA-6fvh-fgmg-3x7v
github.com/patriksimek/vm2/commit/ab4ee7d803e8c80155e9eb3672226bddbca4aa9c
github.com/patriksimek/vm2/releases/tag/v3.11.7
github.com/advisories/GHSA-c48m-32m9-vx93
github.com/CVEProject/cvelistV5/tree/main/cves/2026/92xxx/CVE-2026-92951.json
github.com/patriksimek/vm2
Left out here: the rest of 2 source descriptions. The JSON record has them.