Skip to content

fix(agent): re-introduce credential scrubbing on the tinyagents tool seam (tinyhumansai#4453) - #3

Closed
senamakel wants to merge 2 commits into
agent/vendor-tinyagentsfrom
agent/fix-4453
Closed

fix(agent): re-introduce credential scrubbing on the tinyagents tool seam (tinyhumansai#4453)#3
senamakel wants to merge 2 commits into
agent/vendor-tinyagentsfrom
agent/fix-4453

Conversation

@senamakel

Copy link
Copy Markdown
Owner

Summary

Fixes the credential-scrubbing regression from the TinyAgents 1.3 → 1.5 migration (source issue: tinyhumansai#4453).

The legacy engine ran scrub_credentials over every tool output before it entered model context (v0.58.7 engine/tools.rs). On the tinyagents path, execute_openhuman_tool never scrubbed and scrub_credentials had zero production callers, so secrets in tool output (env dumps, config reads, API responses, shell output) reached model context (and thus third-party providers), session_raw transcripts, worker-thread mirrors, and the ToolCallOutcome sink — violating "Never log secrets or full PII."

Fix

  • CredentialScrubMiddleware — a wrap_tool tool middleware installed on the shared assemble_turn_harness seam, so both the parent chat path and the sub-agent path are covered. It is registered as the innermost wrap layer, so it always sees the RAW tool output and always runs BEFORE the after_tool chain (summarization / caps / tokenjuice via ToolOutputMiddleware) and before the transcript push. This ordering holds regardless of after_tool registration order — deliberately robust to the middleware-ordering rework in after_tool middleware order inverted: progressive-disclosure handoff is dead code, outcome capture sees pre-cap content tinyhumansai/openhuman#4464 (the crate runs after_tool in reverse registration order; using wrap_tool sidesteps that entirely). Because every downstream surface (transcript, ToolOutputMiddleware, the ToolCallOutcome sink, session_raw persistence via persist_subagent_transcript, worker-thread mirror) derives from the scrubbed content, one scrub at this seam covers all of them.
  • harness/credentials.rs stays the single source of truth for the patterns, extended beyond the legacy key/value regex to also catch the standalone formats the acceptance criteria name: bare AWS access-key IDs (AKIA…/ASIA…), OpenAI sk-… keys, and space-separated Bearer tokens. The scrub is idempotent.
  • The tool result's error text is scrubbed too (it can echo the raw output and feeds the outcome sink / model-facing error surface).

Verified

  • Unit tests in credentials.rs for the new AWS / OpenAI / Bearer patterns + idempotency (logic reviewed against each input; each raw secret is redacted, marker preserved).
  • e2e tests in tinyagents/tests.rs drive a real turn through run_turn_via_tinyagents_shared with a tool that leaks a fake AKIA…/sk-…/Bearer token and assert redaction at the model-visible transcript, the persisted conversation, and the ToolCallOutcome sink — on both the chat and the sub-agent path.

Could NOT verify locally

  • cargo check/cargo test did not finish within the time budget: this worktree shares one Cargo target dir with several sibling worktree agents, and the build serialized on the shared target lock (20+ concurrent cargo processes). The change compiles against the current APIs as read from the vendored crate (ToolMiddleware/ToolHandler/MiddlewareToolOutcome, run_turn_via_tinyagents_shared, SubagentScope), but CI is the authoritative build/test signal here. Please rely on CI for the green check.

https://claude.ai/code/session_019j5TLsRLHsM3kqAYFyH4hR

senamakel added 2 commits July 3, 2026 20:19
…seam (tinyhumansai#4453)

The legacy engine scrubbed `scrub_credentials` over every tool output before
it entered model context (v0.58.7 `engine/tools.rs`). The tinyagents migration
dropped this: `execute_openhuman_tool` never scrubbed and `scrub_credentials`
had zero production callers, so secrets in tool output (env dumps, config
reads, API responses, shell output) reached model context, `session_raw`
transcripts, worker-thread mirrors, and the `ToolCallOutcome` sink.

Fix:
- Re-introduce scrubbing as `CredentialScrubMiddleware`, a `wrap_tool` tool
  middleware installed on the shared `assemble_turn_harness` seam so BOTH the
  parent chat path and the sub-agent path are covered. It runs as the innermost
  wrap layer, so it always sees the RAW tool output and always runs BEFORE the
  `after_tool` chain (summarization / caps / tokenjuice) and the transcript
  push — independent of `after_tool` registration order (which tinyhumansai#4464 reworks).
  Because every downstream surface (transcript, ToolOutputMiddleware, the
  ToolCallOutcome sink, session_raw persistence, worker-thread mirror) derives
  from the scrubbed content, one scrub at this seam covers all of them.
- Keep `harness/credentials.rs` as the single source of the patterns, and
  extend it beyond the legacy key/value regex to also catch the standalone
  secret formats the acceptance criteria name: bare AWS access-key IDs
  (`AKIA…`/`ASIA…`), OpenAI `sk-…` keys, and space-separated `Bearer` tokens.
  The scrub is idempotent.
- Also scrub the tool result's `error` text (it can echo the raw output and is
  consumed by the outcome sink / model-facing error surface).

Tests:
- Unit tests in `credentials.rs` for the new AWS/OpenAI/Bearer patterns and
  idempotency.
- e2e tests in `tinyagents/tests.rs` drive a real turn through
  `run_turn_via_tinyagents_shared` with a tool that leaks a fake
  `AKIA…`/`sk-…`/`Bearer` token and assert redaction at the model-visible
  transcript, the persisted conversation, and the `ToolCallOutcome` sink — on
  both the chat and the sub-agent path.

Claude-Session: https://claude.ai/code/session_019j5TLsRLHsM3kqAYFyH4hR
… scrub

The adapter-inventory test asserted 2 around-tool wraps; tinyhumansai#4453 adds
CredentialScrubMiddleware as a 3rd (innermost) wrap, so the count is now 3.
Caught by the workflow's static review (the original commit shipped with
build_check=not_run and never ran this test).

Ref: tinyhumansai#4453
Claude-Session: https://claude.ai/code/session_019j5TLsRLHsM3kqAYFyH4hR
@cursor

cursor Bot commented Jul 3, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@senamakel

Copy link
Copy Markdown
Owner Author

Superseded: re-implementing tinyhumansai#4453 fresh on current upstream/main as a PR to tinyhumansai/openhuman (upstream tinyhumansai#4483 changed the middleware area).

@senamakel senamakel closed this Jul 4, 2026
@senamakel
senamakel deleted the agent/fix-4453 branch July 4, 2026 02:25
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.

1 participant