JAVASCRIPT
Secure File Upload Handling in Node.js
Implement secure file upload mechanisms to prevent malicious file execution and protect against common vulnerabilities like arbitrary code execution.
const express = require('express');
const multer = require('multer');
const path = require('path');
const fs = require('fs');
const app = express();
// Create the 'uploads' directory if it doesn't exist
const uploadDir = path.join(__dirname, 'uploads');
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir);
}
// Configure Multer for secure file storage
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, uploadDir); // Store files in a dedicated 'uploads' directory
},
filename: function (req, file, cb) {
// Sanitize filename and append a unique timestamp to prevent overwrites and guessing
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
const sanitizedFileName = file.originalname.replace(/[^a-zA-Z0-9.]/g, '_'); // Allow only alphanumeric and dot
const fileExtension = path.extname(sanitizedFileName).toLowerCase();
// Restrict file extensions to a whitelist
const allowedExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.pdf'];
if (!allowedExtensions.includes(fileExtension)) {
return cb(new Error('Invalid file type. Only images and PDFs are allowed.'), false);
}
cb(null, sanitizedFileName.replace(fileExtension, '') + '-' + uniqueSuffix + fileExtension);
}
});
// Configure Multer with file size and storage limits
const upload = multer({
storage: storage,
limits: { fileSize: 5 * 1024 * 1024 }, // 5 MB file size limit
fileFilter: function (req, file, cb) {
const allowedMimeTypes = ['image/jpeg', 'image/png', 'image/gif', 'application/pdf'];
if (allowedMimeTypes.includes(file.mimetype)) {
cb(null, true);
} else {
cb(new Error('Invalid MIME type. Only images and PDFs are allowed.'), false);
}
}
});
// Route for file upload
app.post('/upload', upload.single('myFile'), (req, res) => {
if (!req.file) {
return res.status(400).send('No file uploaded or file type not allowed.');
}
res.send(`File uploaded successfully: ${req.file.filename}`);
}, (error, req, res, next) => { // Multer error handler
res.status(400).send({ error: error.message });
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
How it works: Securely handling file uploads is vital to prevent attackers from uploading malicious scripts or executables. This Node.js (Express) snippet uses the `multer` middleware to manage file uploads safely. It enforces strict measures by: 1) Defining a dedicated upload directory (though in this example, it's relative to `__dirname`, best practice for production is to store outside publicly accessible folders). 2) Renaming files with unique suffixes and sanitizing original filenames to prevent path traversal and overwrites. 3) Whitelisting allowed file extensions and MIME types to prevent executable files. 4) Setting a maximum file size limit to guard against denial-of-service attacks. Robust error handling is also included for failed uploads.