highCVSS 7.1Vulnerability

CVE-2026-92959

### Summary When `allowAsync` is set to `false`, vm2 is expected to reject attempts to run asynchronous code. Direct use of `Promise.prototype.then` is blocked, but Promise static methods still assimilate attacker-controlled thenables. `Promise.resolve(thenable)`, `Promise.all([thenable])`, `Promise.race([thenable])`, `Promise.any([thenable])`, and `Promise.allSettled([thenable])` can invoke the thenable's `then` method in a microtask after `VM.run()` or `NodeVM.run()` has already returned. This bypasses the documented async-execution restriction and runs outside the configured `timeout`, allowing sandboxed code to continue executing after the host believes execution is complete. ### Details The documented VM option says `allowAsync: false` should cause attempts to run async code to throw a `VMError`; README.md:139-145 also recommends using it with `timeout`. The implementation enforces part of this policy by replacing `localPromise.prototype.then` with an `AsyncErrorHandler` when async is disabled: - `lib/setup-sandbox.js:1629-1637` defines `AsyncErrorHandler`, whose `apply` and `construct` traps throw `VMError: Async not available`. - `lib/setup-sandbox.js:1743-1752` installs that handler on `localPromise.prototype.then` when `allowAsync` is false. However, Promise static methods are still exposed and rebound to `localPromise`: - `lib/setup-sandbox.js:1816-1819` wraps `Promise.all`. - `lib/setup-sandbox.js:1821-1824` wraps `Promise.race`. - `lib/setup-sandbox.js:1826-1830` wraps `Promise.allSettled`. - `lib/setup-sandbox.js:1833-1837` wraps `Promise.any`. - `lib/setup-sandbox.js:1840-1843` wraps `Promise.resolve`. Those wrappers prevent species attacks by forcing `localPromise` as the constructor, but they do not reject or neutralize thenables when `allowAsync` is false. Native Promise resolution then performs `PromiseResolveThenableJob` and calls the attacker-controlled `then` method asynchronously. That job does not go through the patched `localPromise.p

Properties

severity
high
summary
vm2: `allowAsync: false` can be bypassed through Promise thenable assimilation in VM and NodeVM
epss_score
0.00449
cvss_score
7.1
retrieved_at
2026-10-05T22:59:58+00:00
ghsa_published
2026-10-05T22:47:34Z
source_url
https://github.com/advisories/GHSA-f8gf-w286-fmq2
ghsa_updated
2026-10-05T22:47:35Z
ghsa_id
GHSA-f8gf-w286-fmq2
last_source
FIRST EPSS
cve_id
CVE-2026-92959
cvss_vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:H
signal_observed_at
2026-10-05T22:52:21+00:00
is_ghsa_only
false
epss_percentile
0.36785

Related Entities (5)

ENRICHED_BY (1)

→[Source]FIRST EPSS

VULNERABLE_TO (1)

←[Software]npm/vm2

AFFECTS (1)

→[Software]npm/vm2

HAS_WEAKNESS (1)

→[Weakness]Protection Mechanism Failure

REPORTED_BY (1)

→[Source]GitHub Advisory Database

Explore deeper with Ninja Signal's threat intelligence graph

CVE-2026-92959 (CVSS 7.1) — Ninja Signal Threat Intelligence | Ninja Signal