Skip to content

fix(dashboard): redact audio provider errors before HTTP replies - #37890

Open
coygeek wants to merge 1 commit into
NousResearch:mainfrom
coygeek:fix/dashboard-audio-endpoints-relay-unredacted-provider-errors
Open

fix(dashboard): redact audio provider errors before HTTP replies#37890
coygeek wants to merge 1 commit into
NousResearch:mainfrom
coygeek:fix/dashboard-audio-endpoints-relay-unredacted-provider-errors

Conversation

@coygeek

@coygeek coygeek commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Summary

An authenticated dashboard caller, or a caller on a non-loopback dashboard bind allowed by the operator, can trigger STT/TTS provider failures and receive unredacted provider error text in the JSON response body. If the upstream provider error includes the submitted API key or bearer material, Hermes sends that operator credential outside the agent process.

  • Local venv proof showed the transcription HTTP detail field preserved the synthetic credential-bearing provider error.
  • Local venv proof showed the TTS HTTP detail field preserved the synthetic credential-bearing provider error.
  • web_server.py puts result.get("error") directly into HTTPException.detail.
  • The same endpoint file does not apply agent.redact.redact_sensitive_text to these audio error paths.
  • The protected resource is the operator's STT/TTS or LLM provider credential.

Sanitize every provider-derived audio error string with agent.redact.redact_sensitive_text(..., force=True) before constructing dashboard HTTPException.detail, including both success-dict failures and outer exception paths.

Linked context

Closes #37889

Real behavior proof (required for external PRs)

Affected component (issue scope)

  • hermes-agent/hermes_cli/web_server.py:1130-1195
  • hermes-agent/hermes_cli/web_server.py:1265-1295
  • hermes-agent/tools/transcription_tools.py:1310-1311,1367-1368,1410-1412,1519,1605
  • hermes-agent/tools/tts_tool.py:2142-2146
  • hermes-agent/agent/redact.py:326-427

Files changed in this PR

  • hermes_cli/web_server.py
  • tests/hermes_cli/test_web_server.py

Behavior reproduced or verified

  1. Use Hermes Agent latest upstream main at source receipt commit 2f0ee664670bb308c44ef969628a998c7e13cb86.
  2. Patch tools.transcription_tools.transcribe_audio to return a failure dict whose error text contains a credential-shaped bearer token, then call transcribe_audio_upload() with a valid base64 audio payload.
  3. Observe HTTP status 400 with detail equal to the unredacted provider error.
  4. Patch tools.tts_tool.text_to_speech_tool to return a failure JSON object whose error text contains a credential-shaped API key, then call speak_text().
  5. Observe HTTP status 400 with unredacted detail; expected result is redacted provider-error text before any dashboard response.

Expected fixed behavior

Sanitize every provider-derived audio error string with agent.redact.redact_sensitive_text(..., force=True) before constructing dashboard HTTPException.detail, including both success-dict failures and outer exception paths.

Tests and validation

  • scripts/run_tests.sh -j 1 tests/hermes_cli/test_web_server.py -k 'redacts_provider' -q — 4 passed, 0 failed.
  • scripts/run_tests.sh -j 1 tests/hermes_cli/test_web_server.py -q — 467 passed, 0 failed.
  • Coverage includes provider failure dictionaries and provider-raised exceptions for both transcription and TTS.

Current branch status

  • Rebased onto upstream main at 477c08b44766ace8b890faa72bf82ecbcf2b3ba8.
  • Review feedback covering the two outer exception paths is implemented in a341d6a7575967ae58c3c183f240b1228dc2d309.

Environment

Hermes latest-main source receipt: 2f0ee664670bb308c44ef969628a998c7e13cb86, detached local checkout. Reproduction used the upstream .venv and provider-free mocks, so no real secrets, provider transcripts, unrelated private paths, or private execution artifacts are included. Public route status: public issue plus linked review-ready PR through public_security_full_disclosure; redaction checked.
Source freshness receipt: source_ready for upstream-main at 2f0ee664670bb308c44ef969628a998c7e13cb86 via /tmp/hermes-source-receipt.json; affected paths exist in the prepared latest-main checkout.

Risk checklist

  • Security/auth/secrets impact: Yes; this is a full-public security route.
  • Approval gate: Confirm current-turn approval evidence before live publication.
  • Public disclosure safety: Redaction and public-body validation run before GitHub mutation.
  • Regression risk: Scoped to the linked fix branch and covered by the tests above.
  • Issue-body contract: Unchanged; the linked issue carries the canonical security disclosure.

@alt-glitch alt-glitch added type/security Security vulnerability or hardening comp/cli CLI entry point, hermes_cli/, setup wizard tool/tts Text-to-speech and transcription P2 Medium — degraded but workaround exists labels Jun 3, 2026
@alt-glitch alt-glitch added comp/dashboard Web dashboard / control panel UI (dashboard/, landing) sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data and removed comp/cli CLI entry point, hermes_cli/, setup wizard labels Jun 26, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing the direct provider-error relay. The result-dictionary changes target a real current-main disclosure path, but the patch is incomplete for its stated security boundary.

Problems

  • hermes_cli/web_server.py:3725 still returns raw text from an exception as Transcription failed: {exc}; hermes_cli/web_server.py:3866 does the same for TTS. The PR diff only redacts the later result.get("error") branches, so provider errors that escape as exceptions remain client-visible.

Suggested changes

  • Apply the same redact_sensitive_text(..., force=True) helper to both outer exception details.
  • Add endpoint tests that mock each provider call to raise a credential-shaped exception and verify the HTTP 500 detail is redacted.

Automated hermes-sweeper review.

Comment thread hermes_cli/web_server.py Outdated
@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users labels Jul 14, 2026
Redact provider-derived STT and TTS failure details before returning dashboard HTTP errors so synthetic credential-bearing provider messages cannot be relayed to clients.

Add regression coverage for both audio transcription and speak endpoints using mocked provider failures.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/dashboard Web dashboard / control panel UI (dashboard/, landing) P2 Medium — degraded but workaround exists sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data tool/tts Text-to-speech and transcription type/security Security vulnerability or hardening

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(dashboard): redact audio provider errors before HTTP replies

3 participants