File paths built from user input allow ../ sequences to escape the intended directory.
When file paths are built from user input using string concatenation, attackers use `../` sequences to escape the intended directory. Linux doesn’t prevent `..` in filenames — it’s a path traversal, not a filesystem bug. Even when the app checks for `..`, encoding tricks (`%2e%2e%2f`), null bytes (`%00`), and double-encoded sequences can bypass naive filters.
// VULNERABLE
app.get('/download', (req, res) => {
const file = req.query.file;
const stream = fs.createReadStream('./uploads/' + file);
// Attacker: ?file=../../../etc/passwd
});
// FIXED — use realpath and containment check
const uploadsDir = path.resolve('./uploads');
app.get('/download', (req, res) => {
const file = path.resolve(path.join(uploadsDir, req.query.file));
if (!file.startsWith(uploadsDir)) {
return res.status(403).send('Forbidden');
}
res.sendFile(file);
});
pool.query(`SELECT * FROM users WHERE id = ${req.params.id}`)