The vulnerability, identified as GHSA-v27g-jcqj-v8rw, is an information disclosure flaw in vm2 where sandboxed code can obtain absolute file paths from the host machine. This is caused by insufficient sanitization in the CallSite wrapper class, which is meant to provide a safe version of V8's native stack frame objects.
There are two primary ways to exploit this:
- Path A (Default
error.stack): By default, if Error.prepareStackTrace is not set, V8 uses a native formatter that includes full file paths in the error.stack string. The initial state of vm2's sandbox allowed this native formatter to be used, leaking host paths.
- Path B (Custom
prepareStackTrace): An attacker can define a custom Error.prepareStackTrace function. This function receives an array of CallSite objects. The vulnerability lies in the fact that methods on vm2's wrapped CallSite objects, such as getFileName(), getLineNumber(), and getEvalOrigin(), would return unsanitized data for stack frames originating from the host.
The analysis of the patches between the vulnerable version (3.10.5) and the fixed version (3.11.0) confirms this. The commit e5d8635f6cc3516b0fb0cd346f9ca33303fa953c fixes Path B by modifying the applyCallSiteGetters function in lib/setup-sandbox.js. It introduces logic to detect if a stack frame belongs to the host and, if so, redacts the output of all CallSite getters by returning null. The subsequent commit, 0a394d33fac1364d64fd790b0f0ddeaa4067afa1, further hardens this by unconditionally redacting getEvalOrigin() and fixing Path A by ensuring a safe, sandboxed prepareStackTrace function is set by default.
The identified vulnerable functions are applyCallSiteGetters, which contained the flawed logic, and the CallSite getters (getFileName, getEvalOrigin) that the attacker's code would call to retrieve the sensitive information.