Popular NPM package “pac-resolver” has fixed a severe remote code execution (RCE) flaw.
To proxy or not to proxy
This week, developer Tim Perry disclosed a high-severity flaw in pac-resolver that can enable threat actors on the local network to run arbitrary code within your Node.js process whenever it attempts to make an HTTP request.
function FindProxyForURL(url, host) // Send all *.example requests directly with no proxy: if (dnsDomainIs(host, '.example.com')) return 'DIRECT'; // Send every other request via this proxy: return 'PROXY proxy.example.com:8080';
In the example above, network requests to “example.com” will bypass the proxy, whereas the rest of the traffic is instructed to go through a proxy server.
And that’s where the problem begins.
For example, a related NPM package called Pac-Proxy-Agent, which is made by the same author and has over 2 million weekly downloads, provides PAC file support to Node.js applications. Pac-Proxy-Agent does so by taking in the URL to a PAC file, retrieving the file, and then acting as a Node.js HTTP agent handling outgoing requests for your application. But Pac-Proxy-Agent fails to sandbox PAC files correctly because it uses the vulnerable pac-resolver module, which further relies on “degenerator” to build the PAC function.
Degenerator is yet another package by the same author that helps transform arbitrary code into a sandboxed function using Node.js’ “VM” module. But the VM module was never designed to be used as a security mechanism, something that is explicitly spelled out in Node.js docs. Therefore, the output from degenerator—when used by a chain of packages like pac-resolver, Pac-Proxy-Agent, and proxy-agent—poses a security risk.
Referring to a disclaimer in Node docs saying, “vm module is not a security mechanism. Do not use it to run untrusted code,” Perry said in a blog post, “This is an easy mistake to make—it’s small text (frankly, it should be the headline on that page and next to every method).” Perry further alleges that MongoDB also did “the exact same thing too in 2019, with even worse consequences.” However, the CVE Perrry links to involves a third-party tool named mongo-express. MongoDB confirmed to Ars that they have no affiliation with the package in question.
Perry explained further that “this creates a big problem. While VM does try to create an isolated environment in a separate context, there’s a long list of easy ways to access the original context and break out of the sandbox entirely… allowing code inside the ‘sandbox’ to basically do anything it likes on your system.”
With that, Perry shared a proof-of-concept exploit code demonstrating how an attacker can break out of the VM:
“That’s it—this is all that’s required to break out of the VM module sandbox. If you can make a vulnerable target use this PAC file as their proxy configuration, then you can run arbitrary code on their machine,” he explained.
The vulnerability seriously impacts those who use pac-resolver versions prior to 5.0.0, even transitively in their Node.js application, and:
- Explicitly use PAC files for proxy configuration or
- Read and use the operating system proxy configuration in Node.js on systems with WPAD enabled or
- Use proxy configuration (
envvars, config files, remote config endpoints, command-line arguments) from an untrusted source
A remote attacker can, in any of these scenarios, configure a malicious PAC URL and run arbitrary code on a computer any time an HTTP request is made using the proxy configuration.
The fix for pac-resolver in version 5.0.0 consists of simply bumping up the degenerator version to 3.0.1. The core fix went into degenerator itself and implements a stronger sandboxing mechanism via the vm2 module to “prevent privilege escalation of untrusted code.”
Perry thanked Snyk for supporting the developer throughout the coordinated vulnerability disclosure process.
Affected developers should upgrade to pac-resolver version 5.0.0 or above to fix this severe vulnerability in their applications.