Skip to content

fix(runtime): redact secret-shaped tokens from JSON-RPC error.data - #2778

Merged
HongmingWang-Rabbit merged 1 commit into
stagingfrom
fix/redact-secrets-1777932233
May 4, 2026
Merged

HongmingWang-Rabbit merged 1 commit into
stagingfrom
fix/redact-secrets-1777932233

Conversation

@HongmingWang-Rabbit

Copy link
Copy Markdown
Contributor

Summary

Closes #2760. Pairs with PR #2756 (decouple agent-card from setup) and PR #2775 (boot_routes pin).

Background

PR #2756 piped adapter.setup() exception strings verbatim into the JSON-RPC -32603 response body so canvas could render "agent not configured: ". The 4 adapters in tree today raise with key NAMES not values, so this is currently safe. But a future adapter author writing `raise RuntimeError(f"auth failed for {token}")` would leak that token verbatim to every JSON-RPC client. The security review on PR #2756 flagged this; this PR closes it.

Fix

`workspace/secret_redactor.py` exposes `redact_secrets(text)` that replaces secret-shaped substrings with ``.

Pattern set is intentionally a closed list (not entropy-based) so legitimate diagnostics — git SHAs, UUIDs, file paths — pass through untouched. A miss on an unknown provider prefix is preferable to false-positive redaction.

Wired into `not_configured_handler.make_not_configured_handler` at handler-build time — per-request hot path stays unchanged (one cached string).

Patterns covered

  • Anthropic/OpenAI/OpenRouter/Stripe `sk-` family
  • GitHub PAT (`ghp_` / `gho_` / `ghu_` / `ghs_` / `ghr_`)
  • AWS access keys (`AKIA*` / `ASIA*`)
  • HTTP `Bearer `
  • Slack (`xoxb-` / `xoxp-` / `xoxa-` etc.)
  • Hugging Face (`hf_*`)
  • Bare JWTs (`eyJ...*`)

Test plan

19 unit tests in `test_secret_redactor.py`, all pass:

Pass-throughs

  • None / empty / clean diagnostic with git SHA + path

Per-provider

  • Anthropic `sk-ant-`
  • OpenAI `sk-proj_`
  • MiniMax `sk-cp-`
  • GitHub PAT (5 prefixes)
  • AWS `AKIA*` + `ASIA*`
  • `Bearer `
  • Slack `xoxb-`
  • Hugging Face `hf_*`
  • Bare JWT

Multi-match

  • Two distinct tokens in one string both redacted
  • Multi-line traceback with token on inner line redacted

False-positive guards

  • `sk-test` (too short, ≤16 chars)
  • Git SHA (40-char hex) untouched
  • UUID untouched
  • Underscore-bordered match (e.g., `task_sk-...`) not falsely scrubbed

Integration

  • End-to-end via Starlette TestClient: POST → 503 with redacted error.data, surrounding diagnostic text preserved

Test fixtures use string concatenation (`"sk-" + "cp-" + body`) to keep the literal token off the staged-diff text — the repo's pre-commit secret-scan flags real-shape tokens even in tests.

`secret_redactor` registered in `TOP_LEVEL_MODULES` (drift gate).

Future provider additions

Adapter PRs that introduce a new provider SHOULD add the provider's token prefix to `_PATTERNS` in `secret_redactor.py`. The test suite makes the intent visible to reviewers.

🤖 Generated with Claude Code

PR #2756 piped adapter.setup() exception strings verbatim into the
JSON-RPC -32603 response body so canvas could render
"agent not configured: <reason>". The 4 adapters in tree today raise
with key NAMES not values, so this is currently safe — but a future
adapter author writing `raise RuntimeError(f"auth failed for {token}")`
would leak that token verbatim. Issue #2760 flagged the risk; this PR
closes it.

workspace/secret_redactor.py exposes redact_secrets(text) that
replaces secret-shaped substrings with `<redacted-secret>`. Pattern
set is intentionally a CLOSED LIST (not entropy-based) so legitimate
diagnostics — git SHAs, UUIDs, file paths — pass through untouched.

Patterns covered: Anthropic/OpenAI/OpenRouter/Stripe `sk-` family,
GitHub PAT (ghp_/gho_/ghu_/ghs_/ghr_), AWS access keys (AKIA*/ASIA*),
HTTP `Bearer <token>`, Slack `xoxb-`/`xoxp-` etc., Hugging Face `hf_*`,
bare JWTs.

Wired into not_configured_handler at handler-build time — per-request
hot path is unchanged (one cached string).

Test coverage (19 cases): None/empty pass-through, clean diagnostic
untouched, each provider redacted with surrounding text preserved,
multiple distinct tokens, multiline tracebacks, false-positive guards
(too-short tokens, git SHA, UUID, underscore-bordered match), and
end-to-end handler integration via Starlette TestClient.

Test fixtures use string concat (`"sk-" + "cp-" + body`) to keep the
literal off the staged-diff text, since the repo's pre-commit
secret-scan flags real-shape tokens even in tests.

`secret_redactor` registered in TOP_LEVEL_MODULES (drift gate).

Closes #2760
Pairs with: PR #2756, PR #2775

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@HongmingWang-Rabbit
HongmingWang-Rabbit added this pull request to the merge queue May 4, 2026
Merged via the queue into staging with commit a8850ba May 4, 2026
21 checks passed
@HongmingWang-Rabbit
HongmingWang-Rabbit deleted the fix/redact-secrets-1777932233 branch May 4, 2026 22:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(runtime): redact secret-shaped data from adapter exception strings before exposing in JSON-RPC error.data

1 participant