Skip to content

feat: add file upload and processing#2

Open
Zfinix wants to merge 1 commit intomainfrom
feat/file-upload
Open

feat: add file upload and processing#2
Zfinix wants to merge 1 commit intomainfrom
feat/file-upload

Conversation

@Zfinix
Copy link
Contributor

@Zfinix Zfinix commented Feb 20, 2026

Summary

  • Add file upload endpoint with multer
  • Add file preview, conversion, and processing utilities
  • Add file download and deletion endpoints

Changes

  • New src/routes/upload.ts with upload, preview, convert, process, download, and delete endpoints
  • Updated src/index.ts to mount upload routes

@Zfinix
Copy link
Contributor Author

Zfinix commented Feb 20, 2026

@instalogai review

@Instalog-dev Instalog-dev deleted a comment from instalog-ai bot Feb 21, 2026
@instalog-ai

This comment was marked as outdated.

@instalog-ai
Copy link

instalog-ai bot commented Feb 21, 2026

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
  • Good use of TypeScript for type safety
  • Proper separation of concerns with a dedicated router module
  • Consistent error response format in JSON
  • Appropriate HTTP status codes for error responses

📝 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);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 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);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 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>`);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 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) => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 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) => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 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 });
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 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);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 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",

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant