
The popular NPM package “pac-resolver” has fixed a serious remote code execution (RCE) bug.
The pac-resolver package receives over 3 million weekly downloads, extending this vulnerability to Node.js applications that rely on the open source dependency. Pac-resolver bills itself as a module that accepts JavaScript proxy configuration files and generates a function for your app to map certain domains to use a proxy.
Proxy or not
This week, developer Tim Perry revealed a very serious flaw in pac resolver that could allow threat actors on the local network to execute arbitrary code within your Node.js process when it tries to make an HTTP request.
While adding proxy support to his HTTP toolkit, Perry started checking the pac resolver code and ran into the security flaw. Tracked as CVE-2021-23406, the vulnerability is related to how Proxy Auto-Config (PAC) files are handled by the module. PAC files consist of JavaScript code that specifies a proxy configuration – which network requests should go over a proxy and which should go directly. For example, in a PAC file, network administrators can explicitly specify a network proxy through which all traffic should be routed and list domains that are exempt from the requirement:
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 above example, network requests to “example.com” bypass the proxy, while the rest of the traffic is instructed to go through a proxy server.
Originally introduced as part of Netscape Navigator 2.0 in 1996, the PAC standard remains relevant and is widely used today. For example, Web Proxy Auto-Discovery Protocol (WAPD) uses DNS and/or DHCP services to locate PAC files on a network and import the proxy configuration into an application. However, as proxy configurations grow, the JavaScript code in a PAC file can become increasingly complex and is ideally designed to run in a virtualized environment (VM).
Few lines of JavaScript can bypass VM, lead to RCE
And that’s where the problem starts.
For example, a related NPM package called Pac-Proxy-Agent, which was created by the same author and has over 2 million weekly downloads, provides PAC file support for Node.js applications. Pac-Proxy-Agent does this by including the URL to a PAC file, fetching the file, and then acting as a Node.js HTTP agent that handles outgoing requests for your application. But Pac-Proxy-Agent fails to sandbox PAC files properly because it uses the vulnerable pac-resolver module, which further relies on “degenerator” to build the PAC function.
Degenerator is yet another package from the same author that helps convert arbitrary code into a sandbox function using Node.js’ “VM” module. But the VM module was never designed to be used as a security mechanism, something explicitly described in Node.js docs. Therefore, the output of the generator – when used by a chain of packages such as pac-resolver, Pac-Proxy-Agent, and proxy-agent – poses a security risk.
Referring to a disclaimer in Node docs stating “vm module is not a security mechanism. Don’t use it to run untrusted code,” Perry said in a blog post, “This is an easy mistake to make – it’s small text (honestly, it should be the headline on that page and next to each method).” Perry further claims that MongoDB also “did the exact same thing in 2019, with even worse consequences.” However, the CVE Perry links to a third-party tool called mongo-express. MongoDB confirmed to Ars that they have no affiliation with the package in question.
Perry went on to explain that “this is causing a major problem. While VM tries to create an isolated environment in a separate context, there is a long list of easy ways to access the original context and get out of the sandbox completely. . the ‘sandbox’ to basically do whatever it wants on your system.”
With that, Perry shared a proof-of-concept exploit code showing how an attacker can break out of the VM:

“That’s it – this is all it takes to break out of the VM module sandbox. If you can get a vulnerable target to use this PAC file as their proxy configuration, then you can run arbitrary code on their machine,” he explained.
The vulnerability seriously affects those using 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 OS proxy configuration in Node.js on WPAD enabled systems or
- Using proxy configuration (
env
vars, configuration files, remote configuration endpoints, command-line arguments) from an untrusted source
A remote attacker in any of these scenarios could configure a malicious PAC URL and execute arbitrary code on a computer whenever an HTTP request is made using the proxy configuration.
The fix for pac-resolver in version 5.0.0 is to simply increase the degenerator version to 3.0.1. The core solution went to the generator itself and implements a stronger sandbox mechanism through the vm2 module to “prevent privilege escalation of untrusted code”.
Perry thanked Snyk for supporting the developer through the coordinated vulnerability disclosure process.
Affected developers should upgrade to pac-resolver version 5.0.0 or later to address this serious vulnerability in their applications.