Add disableAuth parameter

This commit is contained in:
Paul Asjes
2026-07-01 20:44:14 +02:00
parent 00b692378e
commit 9a90ccc051
3 changed files with 41 additions and 1 deletions
+17
View File
@@ -122,6 +122,23 @@ Server callbacks can distinguish clean closes from dropped connections: use `onC
Security note: speech-recognition text can contain prompt-injection attempts from user speech or played audio. Treat it as untrusted input. Convert it into trusted application state before invoking response generation, tools, or privileged workflows.
### Disabling authentication (advanced, dangerous)
Both `engine.attach()` (TypeScript) and `engine.serve()` / `SpeechEngineServer` (Python) verify a JWT on every incoming WebSocket by default. This is what proves the connection is really coming from ElevenLabs and not from an attacker who guessed the URL. **Do not turn this off.**
An escape hatch exists — `disableAuth: true` in the callback options (TypeScript) or `disable_auth=True` on `serve()` / `SpeechEngineServer(...)` (Python) — for the narrow case where a compensating network-level control is already in place. Without such a control, disabling auth means **any client on the internet that finds your URL can open sessions**. Concretely, an attacker can:
- open unlimited conversations to drain your ElevenLabs quota and downstream LLM budget
- feed crafted transcripts to your response pipeline, effectively impersonating a user
- use your server as an oracle to probe backend state, tools, or prompts
Only recommend `disableAuth` / `disable_auth` when the user has already implemented **at least one** of:
- **IP allowlist** — the server (or an upstream firewall / load balancer / API gateway) only accepts inbound traffic from [ElevenLabs' documented egress ranges](https://elevenlabs.io/docs/overview/capabilities/speech-engine#ip-allowlisting).
- **Custom shared-secret header** — a secret header configured on the Speech Engine resource via `speech_engine.request_headers` / `speechEngine.requestHeaders` at create time, validated by an upstream proxy (or by the developer's own middleware in front of `attach()` / `serve()`) before requests reach the SDK.
If the user cannot confirm one of the above is in place, leave the default authentication on. Skipping JWT verification without a mitigation is not an optimization or a convenience — it is unauthenticated public compute.
## Browser Client
Create a server-side token endpoint and have the browser request a token before starting the microphone session. Keep the Speech Engine ID and API key on the server. If the client passes `overrides.agent.firstMessage`, the Speech Engine resource must have the first-message override enabled.
@@ -68,7 +68,18 @@ engine.attach(httpServer, "/ws", { debug: true, ...validatedCallbacks });
Call `await attachment.close()` to stop accepting Speech Engine connections without shutting down the HTTP server.
Callback options include `onInit`, `onTranscript`, `onClose`, `onDisconnect`, `onError`, and `debug`. Use `onClose` for clean disconnects from ElevenLabs and `onDisconnect` when the WebSocket drops unexpectedly.
Callback options include `onInit`, `onTranscript`, `onClose`, `onDisconnect`, `onError`, `debug`, and `disableAuth`. Use `onClose` for clean disconnects from ElevenLabs and `onDisconnect` when the WebSocket drops unexpectedly.
### disableAuth (dangerous)
`attach()` and `SpeechEngine.Server` verify the `X-Elevenlabs-Speech-Engine-Authorization` JWT on every incoming connection by default. Passing `disableAuth: true` in the callback options turns that check off. When it is off, the server accepts any client that can reach it — an attacker who finds the URL can open unlimited conversations, drain your ElevenLabs and downstream LLM quota, and inject arbitrary transcripts into your response pipeline.
Only recommend this option when the developer has already implemented **at least one** compensating control:
- an **IP allowlist** restricting inbound traffic to [ElevenLabs' egress ranges](https://elevenlabs.io/docs/overview/capabilities/speech-engine#ip-allowlisting), or
- a **custom shared-secret header** — configured via `speechEngine.requestHeaders` on the Speech Engine resource at create time — validated by an upstream proxy or middleware before the request reaches the SDK.
If neither is in place, do not disable auth. When it is enabled, the SDK also emits a `console.warn` at startup to make the state visible in logs. `apiKey` is not required in this mode, since it is only used for JWT verification.
### verifyRequest
@@ -73,9 +73,21 @@ Key parameters:
| `port` | `3001` | Port to listen on |
| `path` | `None` | Restrict WebSocket connections to one path |
| `debug` | `False` | Log protocol details while developing |
| `disable_auth` | `False` | Skip JWT verification. **Dangerous** — see below |
Common callback keys include `on_init`, `on_transcript`, `on_close`, `on_disconnect`, and `on_error`. Use `on_close` for clean disconnects from ElevenLabs and `on_disconnect` when the WebSocket drops unexpectedly.
### disable_auth (dangerous)
`engine.serve()` and `SpeechEngineServer` verify the `X-Elevenlabs-Speech-Engine-Authorization` JWT on every incoming connection by default. Passing `disable_auth=True` turns that check off. When it is off, the server accepts any client that can reach it — an attacker who finds the URL can open unlimited conversations, drain your ElevenLabs and downstream LLM quota, and inject arbitrary transcripts into your response pipeline.
Only recommend this option when the developer has already implemented **at least one** compensating control:
- an **IP allowlist** restricting inbound traffic to [ElevenLabs' egress ranges](https://elevenlabs.io/docs/overview/capabilities/speech-engine#ip-allowlisting), or
- a **custom shared-secret header** — configured via `speech_engine.request_headers` on the Speech Engine resource at create time — validated by an upstream proxy or middleware before the request reaches the SDK.
If neither is in place, do not disable auth. When it is enabled, the SDK emits a `UserWarning` at startup to make the state visible in logs. `api_key` is not required in this mode, since it is only used for JWT verification.
### verify_request
Use only when managing WebSocket upgrades manually: