Releases: EmZod/Speak-Turbo
Releases · EmZod/Speak-Turbo
v1.0.7: Output path allowlist for -o flag
What's New
Output path allowlist — the -o flag now only writes to safe directories by default.
Security
-owrites restricted to/tmp,$PWD,~/.speakturbo/by default--allow-dirflag for one-off directory overrides~/.speakturbo/configfor permanent directory allowlisting- Clear error messages with exact fix commands when a path is blocked
- Symlink escape and path traversal attacks blocked via
realpathresolution - Rust CLI:
resolve_path()helper correctly handles non-existent paths (walks ancestor tree) - Rust CLI: allowlist entries canonicalized (critical for macOS
/tmp→/private/tmp) - Both Python and Rust CLIs produce identical error messages
Testing
- 14 new behavioral tests (23 total, all passing)
- Covers: default-allowed paths, blocked paths, error message quality, escape hatches (
--allow-dir+ config file), symlink escape, path traversal, no-output edge case
Usage
# Default — works as before
speakturbo "Hello" -o /tmp/output.wav
# Blocked path — clear error with fix instructions
speakturbo "Hello" -o /custom/path/audio.wav
# Error: Output path is outside allowed directories.
# To allow: speakturbo "Hello" -o /custom/path/audio.wav --allow-dir /custom/path
# Permanent override
mkdir -p ~/.speakturbo && echo "/custom/path" >> ~/.speakturbo/configFiles Changed
speakturbo/cli.py— allowlist logic +--allow-dirflagspeakturbo-cli/src/main.rs— allowlist logic +--allow-dirflagspeakturbo-cli/Cargo.toml— addeddirs = "5"dependencyspeakturbo/tests/test_cli.py— 14 new behavioral testsSKILL.md— Output Path Security sectionAGENTS.md— design decision #7
v1.0.4 — Security Hardening
What's Changed
Dead code removed
- Deleted
daemon.py(242 lines) andraw_server.py(95 lines) — legacy prototypes that were never used in production daemon_streaming.pyis now the sole, unambiguous server implementation
Test suite fixed
- Tests now target the actual production daemon (
GET /ttson port 7125) instead of the deleted legacy daemon (POST /ttson port 7123) - Added DNS rebinding protection tests
- WAV header validation uses
struct.unpack_from(works with streaming WAV) - All ruff lint checks pass
Install script cleaned up
- Removed
git clonefallback — builds from local source only - Pinned dependency versions with upper bounds
- Removed unused OS/ARCH detection code
- Added error trap
Developer docs updated
AGENTS.mdnow documents the single-daemon design explicitly- Key files table updated, port change instructions cover all 3 locations
No production code changes
daemon_streaming.py, cli.py, main.rs are completely untouched.
v1.0.2 - Security Fix: DNS Rebinding Protection
Security Fix
This release adds protection against DNS rebinding attacks on the localhost daemon.
Changes
- Added Host header validation middleware to daemon
- Blocks requests with non-localhost Host headers (returns 403 Forbidden)
- Protects against malicious websites attempting to access the local TTS service
Details
The speakturbo daemon runs on 127.0.0.1:7125. Without Host header validation, a malicious website could potentially use DNS rebinding to send requests to the daemon. This fix ensures only requests with Host: 127.0.0.1 or Host: localhost are accepted.
No Breaking Changes
All existing functionality works exactly as before. Normal usage via CLI or curl is unaffected.
Upgrade
git pull origin main
# Restart daemon
pkill -f daemon_streaming
speakturbo "test"