User controlled paths
User input directly controls file paths in fs operations
A critical vulnerability where attackers can write files to arbitrary locations on the file system by controlling file paths in Node.js file operations. This can lead to overwriting critical system files, configuration files, or placing malicious files in web-accessible directories, potentially resulting in remote code execution, privilege escalation, or complete system compromise.
const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();
app.use(express.json());
app.post('/write-file', (req, res) => {
const { filename, content } = req.body;
// DANGEROUS: No path validation
const filePath = './data/' + filename;
fs.writeFile(filePath, content, (err) => {
if (err) {
res.status(500).send('Error writing file');
} else {
res.send('File written successfully');
}
});
});
const express = require('express');
const fs = require('fs').promises;
const path = require('path');
const app = express();
app.use(express.json());
function validatePath(userInput, baseDir) {
if (!userInput || typeof userInput !== 'string') {
throw new Error('Invalid filename');
}
// Remove null bytes and check for traversal
const cleaned = userInput.replace(/\x00/g, '').trim();
if (cleaned.includes('..') || cleaned.includes('\\')) {
throw new Error('Path traversal detected');
}
// Extract basename only (removes path components)
const basename = path.basename(cleaned);
// Resolve full path
const fullPath = path.resolve(baseDir, basename);
// Ensure path is within base directory
const relativePath = path.relative(baseDir, fullPath);
if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {
throw new Error('Path outside base directory');
}
return fullPath;
}
const DATA_DIR = path.resolve('./data');
app.post('/write-file', async (req, res) => {
try {
const { filename, content } = req.body;
if (!filename || !content) {
return res.status(400).json({ error: 'Missing parameters' });
}
// Validate and resolve path
const safePath = validatePath(filename, DATA_DIR);
// Write file with restricted permissions
await fs.writeFile(safePath, content, { mode: 0o644 });
res.json({
message: 'File written successfully',
filename: path.basename(safePath)
});
} catch (error) {
console.error('File write error:', error.message);
res.status(400).json({ error: error.message });
}
});
app.listen(3000);The vulnerable code allows users to control file paths directly through string concatenation, enabling path traversal attacks to write files anywhere on the filesystem. The secure version implements comprehensive path validation using path.resolve() and path.relative() to ensure all file operations stay within the intended base directory. It uses path.basename() to extract only the filename (removing path components), validates that resolved paths don't escape the base directory, and removes dangerous characters like null bytes. This prevents attackers from writing files outside the designated directory.
User input directly controls file paths in fs operations
Sourcery automatically identifies arbitrary file write vulnerability from unvalidated user-controlled file paths and many other security issues in your codebase.