#7400: media: allow temp-dir MEDIA paths for tool outputs
Cluster:
Voice Call and TTS Improvements
## Problem
MEDIA paths from internal tools like `tts` are rejected by `isValidMedia()` because they use absolute paths under the OS temp directory (e.g., `/tmp/tts-abc123/voice.opus`).
This causes TTS voice responses to be sent as plain text markup instead of voice messages, since the media file path fails validation.
### Reproduction
1. Configure TTS with `messages.tts.auto: "tagged"`
2. Send a message requesting voice output (e.g., "tell me a joke, voice")
3. TTS tool generates a file in the temp directory and returns `MEDIA:<temp-path>`
4. Media validation rejects the absolute path → voice file never attached
5. User receives `[[tts]]` markup as plain text
*Note: A local hotfix patching `dist/` was applied to verify the fix; this PR targets the source.*
## Solution
Allow absolute paths that safely resolve under temp directories:
- Support both `os.tmpdir()` AND `/tmp` on POSIX (macOS returns `/var/folders/...` but tools often use `/tmp`)
- Normalize paths with `path.resolve()`
- Use `path.relative()` to safely determine containment
- Reject temp dir roots themselves (must be a file inside)
- Preserves existing security: URLs, relative `./` paths, and traversal blocking
### Security considerations
- **No new attack surface**: Only paths resolving strictly inside temp directories are allowed
- **Traversal-safe**: `path.resolve()` normalizes `..` before comparison
- **Cross-platform**: Uses `path.relative()` and `path.isAbsolute()` for Windows compatibility
- **Prefix attack protection**: `path.relative()` correctly handles `/tmp-evil/` vs `/tmp`
## Changes
- `src/media/parse.ts`: Add `getTempRoots()` and `isSafeTempPath()` helpers, update `isValidMedia()` to allow temp paths
- `src/media/parse.test.ts`: Add OS-portable test cases for temp path acceptance and traversal rejection
## Testing
- [x] `pnpm vitest run src/media/parse.test.ts` — all 16 tests pass
- [x] `pnpm build` — compiles successfully
- [x] New tests: temp path acceptance (os.tmpdir and /tmp on POSIX)
- [x] New tests: traversal attack rejection
- [x] Manual: TTS voice messages now work correctly (verified with local patch)
## AI Disclosure
This PR was developed with AI assistance (Claude). The code has been reviewed and tested locally.
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR extends media token validation to support absolute `MEDIA:` file paths that resolve under OS temp directories (via `os.tmpdir()` and `/tmp` on POSIX), allowing internal tools like TTS to attach generated audio files instead of leaving `[[tts]]` markup in the message. It adds helper functions (`getTempRoots`, `isSafeTempPath`) and new Vitest coverage for accepted temp paths and rejected traversal/prefix attacks.
Overall, the change fits into the existing `splitMediaFromOutput` pipeline by relaxing `isValidMedia()` only for a tightly-scoped class of absolute paths while keeping URL handling and `./` relative path requirements unchanged.
<h3>Confidence Score: 4/5</h3>
- This PR looks safe to merge with low risk; it narrowly expands accepted MEDIA paths to temp directories and includes targeted tests.
- Change is localized to media path validation and uses `path.resolve` + `path.relative` containment checks plus tests for traversal and prefix edge cases. Main remaining concern is platform-specific path/case semantics (especially Windows/case-insensitive volumes) that could cause incorrect accept/reject behavior.
- src/media/parse.ts (temp path containment logic on Windows/case-insensitive filesystems)
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#21110: fix(tts): deliver audio via structured mediaUrl instead of MEDIA: t...
by hydro13 · 2026-02-19
82.2%
#22401: fix: resolve relative media paths against workspace and fix /tmp on...
by derrickburns · 2026-02-21
79.1%
#18811: fix(media): require file extension for ambiguous MEDIA: path detection
by aldoeliacim · 2026-02-17
78.6%
#19868: fix: prevent media token regex from matching markdown bold text
by sanketgautam · 2026-02-18
78.4%
#9817: fix(media): resolve relative paths before reading local files (#8759)
by lailoo · 2026-02-05
77.9%
#18890: fix(media): parse tool-result MEDIA directives with shared parser
by teededung · 2026-02-17
77.1%
#14794: fix: parse inline MEDIA: tokens in agent replies
by explainanalyze · 2026-02-12
77.0%
#21513: Agents: track TTS media in duplicate filter state
by DevvGwardo · 2026-02-20
76.9%
#22178: test(web): allow fixture roots in media local file tests
by Kansodata · 2026-02-20
76.2%
#22356: test(web): fix media test fixture local root handling
by AIflow-Labs · 2026-02-21
75.6%