Что ломается
Обработчик просто склеивает путь к любому файлу, который пришёл в query-параметре. Проверки на выход за пределы каталога нет — поэтому можно читать системные файлы.
app.get('/api/reports', (req, res) => {
const { file } = req.query;
if (!file) {
return res.status(400).json({ error: 'нужен параметр file' });
}
const targetPath = path.join(REPORTS_DIR, file);
try {
// ❌ путь не проверяется — можно дойти до /etc/passwd
const content = fs.readFileSync(targetPath, 'utf8');
return res.json({ file, content });
} catch (err) {
if (err.code === 'ENOENT') {
return res.status(404).json({ error: 'файл не найден' });
}
return res.status(500).json({ error: 'ошибка чтения файла' });
}
});