fix(security): sanitize originalname before forwarding to ElevenLabs#79
Conversation
|
@anshul23102 is attempting to deploy a commit to the itzzavdhesh's projects Team on Vercel. A member of the Team first needs to authorize it. |
DCO Sign-off VerifiedHi @anshul23102, all commits currently include a valid Status
VoiceForge automation |
📝 WalkthroughWalkthroughThis PR adds filename sanitization to the ChangesFilename Sanitization for Voice Cloning
Estimated Code Review Effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly Related Issues
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
PR Ready For Mentor ReviewHi @anshul23102, thank you for opening this PR with the required structure. Your PR passed the automated checks and has moved into the NSOC mentor review queue. Validation Summary
Mentor Review Request@joyprakashk @rushi-k12, this NSOC PR is ready for your review. Review checklist
Contributor NoteThis does not mean the PR is approved yet. Please wait for mentor feedback before expecting merge. If changes are requested, update the same branch and keep the PR focused on the linked issue. VoiceForge automation |
cloneVoice forwarded audioFile.originalname directly to ElevenLabs as the multipart filename. originalname is taken from the client Content-Disposition header and is fully attacker controlled, allowing path traversal sequences and header injection characters to pass through unmodified. Add sanitizeUploadFileName, which strips any directory components and reduces the name to alphanumerics plus dot, hyphen, and underscore. Null bytes and path separators are removed, leading dots are trimmed, and the result is capped at 200 characters with a safe default fallback. Closes itzzavdhesh#69 Signed-off-by: anshul23102 <anshul23102@iiitd.ac.in>
b59ba58 to
25b76b5
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (2)
server/controllers/voiceController.js (2)
56-56: ⚡ Quick winExtract magic number to a named constant.
The 200-character limit is hardcoded. Consider extracting it to a named constant at the top of the file (e.g.,
UPLOAD_FILENAME_MAX_LENGTH) for clarity and maintainability.♻️ Proposed refactor
At the top of the file, add:
const PENDING_STREAM_TTL_MS = parseInt(process.env.PENDING_STREAM_TTL_MS, 10) || 60000; + +// Cap sanitized upload filenames to prevent excessively long filenames from +// being forwarded to ElevenLabs. +const UPLOAD_FILENAME_MAX_LENGTH = 200;Then update the slice call:
const cleaned = withoutPath .replace(/[^a-zA-Z0-9._-]/g, "_") .replace(/^\.+/, "") - .slice(0, 200); + .slice(0, UPLOAD_FILENAME_MAX_LENGTH);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@server/controllers/voiceController.js` at line 56, Extract the hardcoded 200 into a named constant (e.g., UPLOAD_FILENAME_MAX_LENGTH) at the top of the file and use that constant in the slice call instead of the literal; replace the .slice(0, 200) occurrence in the voiceController (where filenames are generated/truncated) with .slice(0, UPLOAD_FILENAME_MAX_LENGTH) so the max length is clear and configurable.
54-54: 💤 Low valueConsider collapsing consecutive underscores.
When multiple unsafe characters appear consecutively (e.g.,
"my!!!file.webm"), they become multiple underscores ("my___file.webm"). You could collapse them for cleaner output.♻️ Optional enhancement
const cleaned = withoutPath .replace(/[^a-zA-Z0-9._-]/g, "_") + .replace(/_+/g, "_") .replace(/^\.+/, "") .slice(0, 200);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@server/controllers/voiceController.js` at line 54, Update the sanitization call that currently uses .replace(/[^a-zA-Z0-9._-]/g, "_") so consecutive unsafe chars collapse into a single underscore; either change the regex to .replace(/[^a-zA-Z0-9._-]+/g, "_") or chain an additional .replace(/_+/g, "_") after the existing replace (and optionally trim leading/trailing underscores). Locate and update the replace expression in voiceController.js where the filename sanitization occurs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@server/controllers/voiceController.js`:
- Line 56: Extract the hardcoded 200 into a named constant (e.g.,
UPLOAD_FILENAME_MAX_LENGTH) at the top of the file and use that constant in the
slice call instead of the literal; replace the .slice(0, 200) occurrence in the
voiceController (where filenames are generated/truncated) with .slice(0,
UPLOAD_FILENAME_MAX_LENGTH) so the max length is clear and configurable.
- Line 54: Update the sanitization call that currently uses
.replace(/[^a-zA-Z0-9._-]/g, "_") so consecutive unsafe chars collapse into a
single underscore; either change the regex to .replace(/[^a-zA-Z0-9._-]+/g, "_")
or chain an additional .replace(/_+/g, "_") after the existing replace (and
optionally trim leading/trailing underscores). Locate and update the replace
expression in voiceController.js where the filename sanitization occurs.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: a93ff679-f313-4c32-9b1e-c12b12526f45
📒 Files selected for processing (1)
server/controllers/voiceController.js
|
Could a maintainer please add the 'nsoc26' label to this PR? This contribution is part of the NSOC 2026 program and addresses the filename sanitization security vulnerability in the voice clone feature. |
|
@itzzavdhesh, could you please add the following labels to this PR for tracking and GSSoC'26 points allocation? Suggested Labels:
This contribution is filed under GSSoC 2026. The fix sanitizes the audioFile.originalname before forwarding to ElevenLabs API, preventing path traversal and injection attacks. Thank you! |
Label Request for NSOC 2026 ContributionHi @itzzavdhesh, Could you please add these labels to track this NSOC 2026 security contribution? Suggested Labels:
PR Status:
This PR prevents filename injection attacks when forwarding to ElevenLabs API. Critical security fix for NSOC 2026. Thanks! |
Label RequestThis PR addresses filename sanitization to prevent path traversal attacks when forwarding to ElevenLabs API. This is part of the NSoC 2026 program. Could you please add the following labels for proper tracking:
The implementation ensures user-controlled filenames cannot be exploited for malicious purposes. Thank you! |
🎊 PR Merged SuccessfullyHey @anshul23102! 👋 Congratulations and thank you for your contribution to VoiceForge! Note 🔗 Linked issue(s): #69 · ✅ Marked as merged and complete Maintainers may still handle final cleanup, release notes, or follow-up tracking after the merge. 🤖 VoiceForge Automation · Updates automatically on edits |
🚀 Program
NSOC
📝 Description
cloneVoiceforwardedaudioFile.originalnamedirectly to ElevenLabs as themultipart filename.
originalnameis derived from the clientContent-Dispositionheader and is fully attacker controlled, so pathtraversal sequences and header injection characters could pass through
unmodified. This sanitizes the filename before it leaves the server by
stripping directory components and reducing it to a safe character set.
🔗 Related Issue
Closes #69
🔄 Type of Change
🧪 How to Test
npm run dev --workspace server.POST /api/voice/clonerequest whose uploaded file name containspath traversal or injection characters, for example
../../etc/passwdora name with embedded slashes and control characters.
alphanumerics, dot, hyphen, and underscore only, with directory components
removed and a
reference.webmfallback when the result is empty.📸 Screenshots (if applicable)
Not applicable. This is a server-side sanitization change with no UI surface.
✅ Checklist
feat: add voice preview)