If you’re a developer or sysadmin using Node.js, you need to be aware of CVE-2023-23918, a critical privilege escalation vulnerability that affects several versions of Node.js. This article breaks down what happened, who’s affected, how the bug works, and (most importantly) how to protect yourself.
< 14.21.3
The vulnerability lets attackers bypass Node’s new experimental “Permissions” feature, which was designed to restrict what code is allowed to do—like reading files or using certain modules.
It’s especially dangerous if you were running Node.js with --experimental-permissions. The feature *should* have blocked access to unauthorized modules, but anyone could sneak in by using an old API call: process.mainModule.require().
Original References
- Node.js Security Release Summary (Official Node.js)
- Node.js Permissions API Documentation
- NVD Entry for CVE-2023-23918
You enabled experimental permissions with --experimental-permissions.
If you don’t use --experimental-permissions, you aren’t directly affected by this specific bug.
How the Exploit Works
--experimental-permissions responds to a policy file or command line switches to limit access to the file system, child processes, and specific built-in modules.
But a crafty attacker could trick Node.js using an overlooked API
// Suppose lodash is NOT allowed according to permissions policy
const moduleRequire = process.mainModule.require;
const lodash = moduleRequire('lodash'); // ← This bypasses policy!
console.log(lodash.VERSION);
Even if your permissions.json or command line arguments denied loading lodash, with this trick, the code is able to load it anyway!
Why does this happen?
Node.js has multiple internal ways to load modules. The require() function you use in most files was locked down by the permissions feature, but process.mainModule.require() was not! This blind spot allowed bypassing all those rules.
Here’s a minimal and clear proof-of-concept
// This will bypass permission checks in affected Node.js versions
const forbiddenModule = process.mainModule.require('fs');
// Should not be accessible if permissions are respected
forbiddenModule.writeFileSync('/tmp/pwned', 'You got hacked!');
>= 14.21.3
Visit the Node.js Downloads page for the latest releases.
Conclusion
CVE-2023-23918 is a real-world reminder that no tool is perfect—even shiny new features can have holes. Now that you know how attackers could bypass Node.js permissions with a simple trick, make sure to update and keep your projects safe.
For more details, read the Node.js Security Release.
Timeline
Published on: 02/23/2023 20:15:00 UTC
Last modified on: 03/16/2023 16:15:00 UTC