Skip to content

fix(security): sanitize originalname before forwarding to ElevenLabs#79

Merged
itzzavdhesh merged 1 commit into
itzzavdhesh:mainfrom
anshul23102:fix/issue-69-filename-sanitize
Jun 8, 2026
Merged

fix(security): sanitize originalname before forwarding to ElevenLabs#79
itzzavdhesh merged 1 commit into
itzzavdhesh:mainfrom
anshul23102:fix/issue-69-filename-sanitize

Conversation

@anshul23102

@anshul23102 anshul23102 commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

🚀 Program

NSOC

📝 Description

cloneVoice forwarded audioFile.originalname directly to ElevenLabs as the
multipart filename. originalname is derived from the client
Content-Disposition header and is fully attacker controlled, so path
traversal 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

  • 🐛 Bug fix
  • ✨ New feature
  • 🔍 SEO improvement
  • 🎨 Style / UI improvement
  • ♿ Accessibility improvement
  • 📝 Documentation
  • ⚙️ CI / configuration
  • 🧹 Refactor / cleanup

🧪 How to Test

  1. Start the server with npm run dev --workspace server.
  2. Send a POST /api/voice/clone request whose uploaded file name contains
    path traversal or injection characters, for example ../../etc/passwd or
    a name with embedded slashes and control characters.
  3. Confirm the value forwarded to ElevenLabs is reduced to a safe name made of
    alphanumerics, dot, hyphen, and underscore only, with directory components
    removed and a reference.webm fallback when the result is empty.

📸 Screenshots (if applicable)

Not applicable. This is a server-side sanitization change with no UI surface.

✅ Checklist

  • I am contributing under NSOC
  • My code follows the project's existing style
  • I have tested my changes in a browser
  • I have linked the related issue above
  • My PR title follows Conventional Commits format (e.g. feat: add voice preview)

@vercel

vercel Bot commented Jun 3, 2026

Copy link
Copy Markdown

@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.

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown

DCO Sign-off Verified

Hi @anshul23102, all commits currently include a valid Signed-off-by: line.

Status

Item Result
DCO check Passed
Label applied dco-verified
Review flow Maintainers can continue normal PR review

VoiceForge automation

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds filename sanitization to the cloneVoice handler before forwarding audio to ElevenLabs. A new helper removes path components, restricts character sets, removes leading dots, truncates length, and falls back to a safe default. The handler now applies this sanitization to user-supplied filenames instead of forwarding them raw.

Changes

Filename Sanitization for Voice Cloning

Layer / File(s) Summary
Filename sanitization helper
server/controllers/voiceController.js
New sanitizeUploadFileName helper removes directory traversal sequences, replaces disallowed characters with underscores, strips leading dots, truncates to 100 characters, and defaults to reference.webm if empty.
Apply sanitization in cloneVoice
server/controllers/voiceController.js
cloneVoice now computes a sanitized filename from audioFile.originalname and uses it when appending the audio blob to the ElevenLabs FormData, replacing the previous pass-through of the raw client-supplied name.

Estimated Code Review Effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly Related Issues

  • #69: [BUG] cloneVoice forwards audioFile.originalname to ElevenLabs without sanitizing path traversal characters — This PR directly addresses the filename-injection vulnerability by implementing sanitization before API submission.

Poem

🐰 A path traversal, oh what a fright!
But now filenames are scrubbed clean and tight.
No more ../../../ in our quest,
Just safe, sanitized names—the very best! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main security fix: sanitizing the originalname filename before forwarding it to ElevenLabs.
Linked Issues check ✅ Passed The PR fully implements the requirements from issue #69: sanitizes filenames by removing directory components and null bytes, restricts allowed characters to alphanumerics with dot/hyphen/underscore, handles truncation, and provides a safe fallback.
Out of Scope Changes check ✅ Passed All changes are directly related to issue #69 requirements: the new sanitizeUploadFileName helper and modifications to cloneVoice exclusively address filename sanitization before forwarding to ElevenLabs.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown

PR Ready For Mentor Review

Hi @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

Item Result
Program NSOC
Closing issue #69
Assignment check PR author matches linked issue assignee
Title check Conventional Commits title detected
Description check Enough review context provided
Change size 21 lines changed across 1 file(s)
Review request Review requested: @joyprakashk @rushi-k12

Mentor Review Request

@joyprakashk @rushi-k12, this NSOC PR is ready for your review.

Review checklist

  • Confirm the PR stays within the linked issue scope
  • Review code quality, behavior, and edge cases
  • Check tests or manual verification notes
  • Approve, comment, or request changes through GitHub review

Contributor Note

This 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>
@github-actions github-actions Bot requested a review from rushi-k12 June 4, 2026 16:48

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
server/controllers/voiceController.js (2)

56-56: ⚡ Quick win

Extract 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 value

Consider 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

📥 Commits

Reviewing files that changed from the base of the PR and between 657f0b5 and 25b76b5.

📒 Files selected for processing (1)
  • server/controllers/voiceController.js

@anshul23102

Copy link
Copy Markdown
Contributor Author

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.

@anshul23102

Copy link
Copy Markdown
Contributor Author

@itzzavdhesh, could you please add the following labels to this PR for tracking and GSSoC'26 points allocation?

Suggested Labels:

  • gssoc-approved — Marks this as an approved GSSoC'26 contribution
  • type:security — Security enhancement (path traversal prevention)
  • priority:high — High priority security fix preventing path traversal attacks
  • level:medium — Medium difficulty (input sanitization)

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!

@anshul23102

Copy link
Copy Markdown
Contributor Author

Label Request for NSOC 2026 Contribution

Hi @itzzavdhesh,

Could you please add these labels to track this NSOC 2026 security contribution?

Suggested Labels:

  • gssoc-approved - NSOC 2026 contribution label
  • security-patched - Security fix validation
  • input-sanitization - Category for filename handling
  • nsoc-2026 - Program identifier

PR Status:

  • ✅ Code reviewed and approved
  • ✅ DCO verified
  • ✅ Addressing filename sanitization vulnerability
  • 🔄 2 reviews pending

This PR prevents filename injection attacks when forwarding to ElevenLabs API. Critical security fix for NSOC 2026.

Thanks!

@anshul23102

Copy link
Copy Markdown
Contributor Author

Label Request

This 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:

  • nsoc-approved (recommended for NSoC contributions)
  • type:security (critical security fix for API integration)

The implementation ensures user-controlled filenames cannot be exploited for malicious purposes.

Thank you!

@itzzavdhesh itzzavdhesh added level3 Critical level SSoC26 SSOC Medium medium mentor:joyprakashk SSoC: Mentor-@joyprakashk mentor:rushi-k12 SSoC: Mentor-@rushi-k12 labels Jun 8, 2026
Repository owner deleted a comment from coderabbitai Bot Jun 8, 2026
@itzzavdhesh itzzavdhesh merged commit d5f281d into itzzavdhesh:main Jun 8, 2026
13 of 16 checks passed
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown

🎊 PR Merged Successfully

Hey @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

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] cloneVoice forwards audioFile.originalname to ElevenLabs without sanitizing path traversal characters

2 participants