JAVASCRIPT
Secure File Upload Validation in Node.js
Implement robust server-side validation for file uploads, checking file types, sizes, and storing them securely to prevent common vulnerabilities.
// Install required packages: npm install express multer path uuid
const express = require('express');
const multer = require('multer');
const path = require('path');
const { v4: uuidv4 } = require('uuid'); // For unique file names
const fs = require('fs');
const app = express();
const PORT = 3000;
// Ensure upload directory exists
const uploadDir = path.join(__dirname, 'uploads');
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir);
}
// Configure Multer storage
const storage = multer.diskStorage({
destination: (req, file, cb) => {
// Store files outside the public web root for security
cb(null, uploadDir);
},
filename: (req, file, cb) => {
// Generate a unique filename to prevent overwriting and path traversal
const uniqueSuffix = uuidv4();
const fileExtension = path.extname(file.originalname);
cb(null, `${uniqueSuffix}${fileExtension}`);
}
});
// Configure Multer upload middleware
const upload = multer({
storage: storage,
limits: {
fileSize: 5 * 1024 * 1024 // Limit file size to 5MB
},
fileFilter: (req, file, cb) => {
// Validate file types - IMPORTANT for security
const allowedMimeTypes = ['image/jpeg', 'image/png', 'application/pdf'];
if (allowedMimeTypes.includes(file.mimetype)) {
cb(null, true); // Accept file
} else {
cb(new Error('Invalid file type. Only JPEG, PNG, and PDF are allowed.'), false); // Reject file
}
}
});
// Route for file upload
app.post('/upload', upload.single('myFile'), (req, res) => {
if (req.file) {
res.status(200).json({
message: 'File uploaded successfully!',
filename: req.file.filename,
path: `/uploads/${req.file.filename}` // Do NOT return full server path
});
} else {
res.status(400).json({ message: 'File upload failed or no file provided.' });
}
}, (error, req, res, next) => { // Multer error handler
if (error instanceof multer.MulterError) {
if (error.code === 'LIMIT_FILE_SIZE') {
return res.status(400).json({ message: 'File size too large. Max 5MB allowed.' });
}
}
// Handle other errors, including custom fileFilter errors
res.status(400).json({ message: error.message });
});
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});
How it works: This Node.js snippet demonstrates how to securely handle file uploads using the `multer` middleware. Key security practices include: 1) **MIME type validation** via `fileFilter` to ensure only expected file types (e.g., images, PDFs) are accepted, preventing malicious script uploads. 2) **File size limits** (`limits.fileSize`) to prevent denial-of-service attacks. 3) **Unique file naming** (`uuidv4`) to avoid overwriting existing files and prevent directory traversal. 4) **Storing files outside the public web root** to prevent direct execution by web servers. Error handling for Multer-specific issues like file size limits is also included.