flawopen.com/path-traversal/Javascript
How naive path.join allows directory traversal in Express/Node.js, and how to enforce directory boundary checks with path.resolve and path.sep.
Bayangkan pembaca kartu kunci hotel yang hanya boleh membuka kamar di lantai dua. Jika seorang tamu mengetik '../../master-safe' pada tombol pintu, kunci yang rentan keluar ke lorong dan membuka brankas utama milik manajer.
Web Application SecurityCWE-918.CWE-918Defense-in-DepthTitik akhir menerima nama file atau pengenal sumber daya dari parameter permintaan HTTP.
Penyerang menyisipkan urutan traversal seperti '../', '..%2f' atau jalur mutlak ke parameter file.
Backend menggabungkan nama file tanpa kanonisasi jalur dan tanpa memastikan target tetap dalam folder aman.
Sistem membaca dan mengalirkan file sensitif (misal: /etc/passwd atau rahasia konfigurasi) ke klien.
// VULNERABLE: path.join allows directory breakout
const express = require('express');
const path = require('path');
const fs = require('fs');
const app = express();
const PUBLIC_DIR = path.join(__dirname, 'public');
app.get('/download', (req, res) => {
// Attacker input: "../../etc/passwd"
const targetFile = path.join(PUBLIC_DIR, req.query.file);
// Directly pipes arbitrary system file to response!
res.sendFile(targetFile);
});
// HARDENED: Canonicalize path and assert prefix with directory separator
const express = require('express');
const path = require('path');
const fs = require('fs');
const app = express();
const PUBLIC_DIR = path.resolve(__dirname, 'public');
app.get('/download', (req, res) => {
const userInput = req.query.file;
if (!userInput || typeof userInput !== 'string') {
return res.status(400).send('Invalid file parameter');
}
// 1. Resolve to absolute path
const safePath = path.resolve(PUBLIC_DIR, userInput);
// 2. Strict boundary check: must start with base folder + separator
if (!safePath.startsWith(PUBLIC_DIR + path.sep)) {
return res.status(403).send('Forbidden: Path Traversal detected');
}
// 3. Verify file exists and is a regular file
fs.stat(safePath, (err, stats) => {
if (err || !stats.isFile()) return res.status(404).send('File not found');
res.sendFile(safePath);
});
});
path.resolve().express.static() with dotfiles: 'ignore' for static file serving.