PostToolUse `updatedToolOutput` silently ignored for built-in Bash tool (2.1.163/2.1.177) — regression; prior reports #65403/#67442/#54196 closed as duplicate, never fixed

Open 💬 1 comment Opened Jun 17, 2026 by MeetMartin

Summary

hookSpecificOutput.updatedToolOutput (PostToolUse output rewrite — documented, and shipped for all tools in v2.1.121) is silently ignored for the built-in Bash tool. A PostToolUse hook that returns a correctly-shaped envelope with exit 0 runs (confirmed via side-effects), but the model still receives the original tool output, not the replacement.

Reproduced on 2.1.163 (standalone CLI, minimal repro below) and observed in an interactive 2.1.177 session.

Why this is filed despite prior reports

This exact defect has been reported repeatedly and every report was auto-closed as duplicate by the bot, funneled into secret-redaction feature requests — so there is currently no open, canonical bug for it and it remains unfixed:

  • #54196 (v2.1.121) — closed as duplicate
  • #65403 (Bash, secret leak) — closed as duplicate of #65122
  • #65122 — closed as duplicate
  • #67442 (v2.1.173, Bash + WebFetch) — closed as duplicate of #65403

The open issues it gets merged into (#64326, #62156, #18653, #66044) are framed as new feature requests for output redaction. This is not a feature request: updatedToolOutput is a documented, shipped feature that is broken for built-in tools. Distinguishing the two is the point of this report.

Minimal reproduction

.claude/settings.json:

{
  "hooks": {
    "PostToolUse": [
      { "matcher": "Bash", "hooks": [ { "type": "command", "command": "bash /tmp/uto-min/hook.sh" } ] }
    ]
  }
}

/tmp/uto-min/hook.sh (exit 0, valid envelope per docs):

#!/bin/bash
cat > /dev/null
printf '%s\n' '{"hookSpecificOutput":{"hookEventName":"PostToolUse","updatedToolOutput":"REDACTED_BY_HOOK"}}'

Run:

cd /tmp/uto-min && claude -p \
  "Use the Bash tool to run exactly: echo SECRET_ORIGINAL_VALUE . Then reply with ONLY the exact verbatim stdout string the tool returned to you." \
  --setting-sources project --allowedTools "Bash(echo:*)" --model haiku

Expected

The model receives REDACTED_BY_HOOK (the hook's updatedToolOutput), so it replies REDACTED_BY_HOOK.

Actual

The model replies SECRET_ORIGINAL_VALUE — the original output. The hook ran (its envelope is emitted on stdout, exit 0), but the rewrite was not applied.

Scope notes (from isolating the channels)

Tested side-by-side with sentinel hooks (all hooks confirmed firing via marker files) on the same version:

| Channel | Reaches the model? |
|---|---|
| PreToolUse hookSpecificOutput.additionalContext | ✅ yes (Bash and Edit) |
| PostToolUse hookSpecificOutput.additionalContext | ✅ yes |
| PreToolUse stderr + exit 2 (block reason) | ✅ yes |
| PostToolUse hookSpecificOutput.updatedToolOutput | ❌ no |

So additionalContext works on this version — it is specifically the output-replacement channel that is dropped. Because additionalContext can only append (never shrink/replace), there is no workaround: redaction and output-size reduction both depend on updatedToolOutput.

Worth checking whether it still works for MCP tools (the pre-2.1.121 scope) and regressed only for built-in tools (Bash/WebFetch) — that would match the v2.1.121 extension being the regression surface.

Impact

Any PostToolUse output transform for built-in tools is inert: secret/credential redaction (the recurring leak reports) and tool-output token-compression hooks both silently no-op while appearing to work (the hook reports success; the model still gets the full/unredacted output).

Environment

  • Claude Code 2.1.163 (standalone CLI, repro above); also observed in a 2.1.177 desktop-app session
  • macOS (Darwin 25.5.0), arm64
  • Hooks: project-scope .claude/settings.json, --setting-sources project

🤖 Filed via Claude Code

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗