#8339: fix(tts): validate ElevenLabs base URL against allowlist
stale
Cluster:
Voice Call and TTS Improvements
## Summary
Add validation to ElevenLabs TTS base URL configuration to prevent SSRF and data exfiltration attacks.
## The Problem
The TTS system accepts a configurable `baseUrl` for the ElevenLabs API without validation. If an attacker modifies the config (via prompt injection, config patch, or environment variable), all LLM response text would be sent to an attacker-controlled server. This could leak credentials, PII, and sensitive information from agent responses.
- CWE-918: Server-Side Request Forgery (SSRF)
- CWE-200: Exposure of Sensitive Information
## Changes
- `src/tts/tts.ts`: Add `validateElevenLabsBaseUrl()` function with:
- Allowlist of official ElevenLabs API hosts
- HTTPS protocol requirement
- Rejection of embedded credentials
- Applied during config resolution
- `src/tts/tts.test.ts`: Add comprehensive tests for URL validation
## Test Plan
- [x] `pnpm build && pnpm test` passes
- [x] New test `describe('validateElevenLabsBaseUrl')` validates the fix
- [x] Verified official URLs like `https://api.elevenlabs.io` are accepted
- [x] Verified attacker URLs are rejected with clear error messages
## Related
- [CWE-918](https://cwe.mitre.org/data/definitions/918.html) - Server-Side Request Forgery
- [CWE-200](https://cwe.mitre.org/data/definitions/200.html) - Exposure of Sensitive Information
- Internal audit ref: VULN-220
---
*Built with [bitsec-ai](https://github.com/bitsec-ai). AI-assisted: Yes. Testing: fully tested (test written before fix). Code reviewed and understood.*
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR adds `validateElevenLabsBaseUrl()` and an allowlist (`api.elevenlabs.io` / `api.elevenlabs.com`) to ensure ElevenLabs TTS requests can’t be redirected to attacker-controlled hosts. The validation enforces HTTPS, disallows embedded credentials, and is applied during `resolveTtsConfig`, with a new test suite covering accepted/rejected URLs.
In the broader TTS flow, this constrains the `config.elevenlabs.baseUrl` that is later used by `elevenLabsTTS()` to build the request URL, reducing SSRF/data-exfil risk from malicious configuration overrides.
<h3>Confidence Score: 4/5</h3>
- This PR is largely safe to merge and improves security, with a small risk of misconfiguration causing broken ElevenLabs endpoints.
- The allowlist/HTTPS/credential checks are straightforward and well-tested, but the current validation/normalization allows base URLs with paths (e.g. ending in `/v1`), which can lead to doubled path segments when requests are constructed (`.../v1/v1/...`).
- src/tts/tts.ts (baseUrl normalization/validation semantics)
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#8103: fix(tts): sanitize API keys from error messages
by yubrew · 2026-02-03
82.2%
#8317: fix(tts): add dynamic timeout and retry logic for ElevenLabs TTS
by camtang26 · 2026-02-03
79.1%
#8228: fix(link-understanding): block private IPs and internal hostnames i...
by yubrew · 2026-02-03
78.2%
#9736: feat(tts): add baseUrl option to OpenAI TTS config (#9709)
by divol89 · 2026-02-05
76.8%
#22186: feat(talk): add baseUrl support for custom TTS servers
by bautrey · 2026-02-20
76.2%
#19768: fix(security): OC-85 validate TTS provider directives against known...
by aether-ai-agent · 2026-02-18
75.8%
#8922: feat(voice-call): Add ElevenLabs WebSocket streaming TTS
by mikiships · 2026-02-04
75.6%
#8124: fix(browser): add path validation for file upload and download
by yubrew · 2026-02-03
75.6%
#21110: fix(tts): deliver audio via structured mediaUrl instead of MEDIA: t...
by hydro13 · 2026-02-19
75.2%
#8305: fix(browser): add SSRF protection to browser navigation
by yubrew · 2026-02-03
73.9%