Repository navigation
fix(inference): validate local TTS output paths - #406
Merged
Merged
Conversation
Auto-committed-on: dragonfly
The speech tests now build LocalAiService from the local runtime config derived from the app config, matching the updated constructor signature. Auto-committed-on: dragonfly
…/service/speech.rs,crates/openh Auto-committed-on: dragonfly
Rustfmt-style line wrapping was applied to the TTS path validation error construction and to several test invocations. No behaviour changed; the reformatting only adjusts how long expressions are broken across lines. Auto-committed-on: dragonfly
The TTS output path validator now rejects a final path component that is a symlink, closing a gap where a symlink inside an allowed root could redirect writes outside it. Root resolution was reworked to reuse the security policy's path validation instead of a bespoke canonicalization helper. Auto-committed-on: dragonfly
The TTS output path validator probed each allowed root by validating a synthetic child file, which failed when the root directory did not exist yet. Roots are now resolved by canonicalizing the nearest existing ancestor and re-appending the missing suffix, and the workspace directory is registered as a trusted root so workspace-only configurations accept outputs written there. Auto-committed-on: dragonfly
The validator now rejects paths outside the workspace or local-ai models directory before resolving them, and refuses roots that canonicalize into protected locations. Canonicalization also distinguishes missing paths from other filesystem errors instead of treating every failure as a missing suffix. Auto-committed-on: dragonfly
The test now builds a Config with a workspace directory under /etc instead of relying on the enabled_config helper, so the always-forbidden path assertion is exercised against a workspace that actually overlaps the blocked prefix. Auto-committed-on: dragonfly
This was referenced Oct 18, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
The local AI TTS host adapter now rejects empty or whitespace-only text before resolving Piper and validates requested output paths before creating directories or starting Piper. Outputs are confined to the workspace or the configured local-AI models directory; traversal, protected paths, and symlink escapes (including a symlink at the final output filename) are rejected.
The path check uses OpenHuman's security policy and preserves its always-forbidden path floor. Tests cover the allowed roots with autonomy enabled, outside-root paths, traversal, parent and final-component symlinks, and
/etcremaining forbidden even when configured as an allowed workspace root.Refs #245
Part of tinyhumansai#8092
Validation
cargo test --manifest-path Cargo.toml -p openhuman --lib inference::host_runtime::service::speech::tests— passed (7 tests) at758186ea681f8b5ec2fa0b19a5660f04642e0e0f.cargo fmt --manifest-path Cargo.toml -p openhuman --check— passed.git diff --check— passed.piper binary not foundinstead of rejecting blank text or an outside-root output path.pnpm rust:layout— reports a pre-existing stale audited allowance fortokio::fs::write(&target, body)incrates/openhuman-core/src/agent/harness/artifact_offload/mod.rs; the speech changes do not touch that code.pnpm debug rust inferenceare pending serialized execution due to host memory pressure.