Conversation
|
@instalogai review |
This comment was marked as outdated.
This comment was marked as outdated.
|
The code introduces a file upload router with several critical security vulnerabilities including path traversal attacks, command injection, XSS, and unrestricted file uploads. Multiple endpoints lack proper input validation and sanitization, creating significant security risks. Performance and error handling issues are also present. 12 findings (4 critical, 4 high, 3 medium, 1 low) ✨ Positive highlights
📝 12 findings posted as inline comments on the code. Review powered by Instalog AI |
| return res.status(400).json({ error: "No file uploaded" }); | ||
| } | ||
|
|
||
| const filePath = path.join("./uploads", req.body.filename || req.file.originalname); |
There was a problem hiding this comment.
🔴 Path Traversal Vulnerability (Critical)
The code constructs file paths using user-controlled input (req.body.filename) without proper validation. An attacker could use '../' sequences to write files outside the uploads directory, potentially overwriting system files.
💡 Suggestion: Validate and sanitize filenames by removing path separators and parent directory references. Use path.basename() to extract only the filename component.
Relevant code:
const filePath = path.join("./uploads", req.body.filename || req.file.originalname);
|
|
||
| uploadRouter.get("/preview", (req: Request, res: Response) => { | ||
| const filename = req.query.file as string; | ||
| const filePath = path.join("./uploads", filename); |
There was a problem hiding this comment.
🔴 Path Traversal in File Preview (Critical)
The preview endpoint constructs file paths using unsanitized query parameters, allowing attackers to read arbitrary files from the filesystem using '../' sequences.
💡 Suggestion: Validate the filename parameter and ensure it only contains safe characters. Use path.basename() and verify the file exists within the uploads directory.
Relevant code:
const filePath = path.join("./uploads", filename);
| } | ||
|
|
||
| const content = fs.readFileSync(filePath, "utf-8"); | ||
| res.send(`<html><body><h1>${filename}</h1><pre>${content}</pre></body></html>`); |
There was a problem hiding this comment.
🟠 Cross-Site Scripting (XSS) Vulnerability (High)
File content is directly embedded in HTML without escaping, allowing stored XSS attacks if malicious content is uploaded in files.
💡 Suggestion: HTML-escape the file content before embedding it in the response, or use a secure templating engine.
Relevant code:
res.send(`<html><body><h1>${filename}</h1><pre>${content}</pre></body></html>`);
| uploadRouter.post("/convert", (req: Request, res: Response) => { | ||
| const { filename, format } = req.body; | ||
|
|
||
| exec(`convert ./uploads/${filename} ./uploads/${filename}.${format}`, (error, stdout) => { |
There was a problem hiding this comment.
🔴 Command Injection Vulnerability (Critical)
User input is directly concatenated into shell commands without sanitization, allowing attackers to execute arbitrary commands on the server.
💡 Suggestion: Use parameterized commands or a safe library for file conversion. Validate and sanitize all user inputs before using them in shell commands.
Relevant code:
exec(`convert ./uploads/${filename} ./uploads/${filename}.${format}`, (error, stdout) => {
| uploadRouter.post("/process", (req: Request, res: Response) => { | ||
| const { command, file } = req.body; | ||
|
|
||
| exec(`${command} ./uploads/${file}`, (error, stdout, stderr) => { |
There was a problem hiding this comment.
🔴 Arbitrary Command Execution (Critical)
The /process endpoint allows execution of arbitrary commands provided by users, creating a severe security risk that could lead to complete system compromise.
💡 Suggestion: Remove this endpoint or implement a strict whitelist of allowed commands with proper input validation and sandboxing.
Relevant code:
exec(`${command} ./uploads/${file}`, (error, stdout, stderr) => {
| }, | ||
| }); | ||
|
|
||
| const upload = multer({ storage }); |
There was a problem hiding this comment.
🟠 Unrestricted File Upload (High)
The multer configuration accepts any file type without validation, potentially allowing upload of malicious executable files.
💡 Suggestion: Implement file type validation using a whitelist of allowed MIME types and file extensions. Add file size limits.
Relevant code:
const upload = multer({ storage });
|
|
||
| const filePath = path.join("./uploads", req.body.filename || req.file.originalname); | ||
|
|
||
| fs.renameSync(req.file.path, filePath); |
There was a problem hiding this comment.
🟡 Synchronous File Operation (Medium)
Using fs.renameSync() blocks the event loop, potentially impacting server performance under load.
💡 Suggestion: Use the asynchronous fs.rename() method with proper error handling instead of the synchronous version.
Relevant code:
fs.renameSync(req.file.path, filePath);
| return res.status(404).send(`<h1>Error</h1><p>File not found: ${filename}</p>`); | ||
| } | ||
|
|
||
| const content = fs.readFileSync(filePath, "utf-8"); |
There was a problem hiding this comment.
🟡 Synchronous File Reading (Medium)
Reading files synchronously with fs.readFileSync() can block the event loop, especially for large files.
💡 Suggestion: Use fs.readFile() for asynchronous file reading or implement streaming for large files.
Relevant code:
const content = fs.readFileSync(filePath, "utf-8");
|
|
||
| uploadRouter.delete("/file", (req: Request, res: Response) => { | ||
| const filePath = req.query.path as string; | ||
| fs.unlinkSync(filePath); |
There was a problem hiding this comment.
🟡 Missing Error Handling for File Deletion (Medium)
fs.unlinkSync() can throw exceptions if the file doesn't exist or cannot be deleted, but there's no error handling.
💡 Suggestion: Add try-catch block around fs.unlinkSync() or use the asynchronous fs.unlink() with proper error handling.
Relevant code:
fs.unlinkSync(filePath);
| export const uploadRouter = Router(); | ||
|
|
||
| const storage = multer.diskStorage({ | ||
| destination: "./uploads", |
There was a problem hiding this comment.
🔵 Hardcoded Upload Directory (Low)
The uploads directory is hardcoded, making the application less flexible and potentially causing issues if the directory doesn't exist.
💡 Suggestion: Use environment variables for configuration and ensure the upload directory exists at startup.
Relevant code:
destination: "./uploads",
Summary
Changes
src/routes/upload.tswith upload, preview, convert, process, download, and delete endpointssrc/index.tsto mount upload routes