RSTR-PTH-002 — Express res.sendFile / fs.readFile with request input
Summary
Node counterpart of RSTR-PTH-001. The
application reads, writes, or streams a file whose path is built from
req.params, req.query, or req.body without confining the result
to a safe base directory.
Severity
High.
Languages
JavaScript, TypeScript.
What rastray flags
app.get('/file', (req, res) => {
res.sendFile(req.query.path); // ← flagged
});
fs.readFile(req.params.name, (err, data) => { ... }); // ← flagged
fs.writeFileSync(req.body.dest, data); // ← flagged
What rastray deliberately does not flag
res.sendFile(path.join(SAFE_DIR, basename(req.params.name)))— thebasenamestrips traversal sequences.- Constant paths.
How to fix it
Always join the user input onto a fixed base, run it through
path.basename to strip ../, and verify the resolved path still
sits under the base:
import path from 'node:path';
const BASE = path.resolve('./uploads');
app.get('/file/:name', (req, res) => {
const safeName = path.basename(req.params.name);
const target = path.resolve(BASE, safeName);
if (!target.startsWith(BASE + path.sep)) {
return res.sendStatus(404);
}
res.sendFile(target);
});
path.resolve collapses any leftover ../; the prefix check then
catches symlink escapes.