PostToolUse cannot safely redact tool output before transcript rendering
Summary
PostToolUse hooks currently do not provide a safe way to redact or replace tool output before it appears in the Codex CLI transcript.
I tested this while building a local tool-boundary/privacy middleware that masks secrets in shell/MCP/browser outputs before they reach the model or the visible transcript. Two behaviors make that impossible today:
- Returning a replacement payload such as
hookSpecificOutput.updatedToolOutputis rejected as invalid PostToolUse JSON. - Returning a valid blocking payload still renders the raw tool output in the TUI transcript before showing the masked hook feedback.
This means PostToolUse can warn/block after the fact, but it cannot currently guarantee that sensitive tool output never appears in the transcript/logs/UI.
Environment
- Codex CLI:
0.142.5 - OS: Windows 11 / PowerShell, launched under tmux for reproducible capture
- Hooks enabled with
--dangerously-bypass-hook-trust - Values below are fake test tokens, not real credentials
Reproduction A: replacement output is rejected
Configure a PostToolUse command hook that returns:
{
hookSpecificOutput: {
hookEventName: PostToolUse,
updatedToolOutput: MASKED_BY_POSTTOOL_HOOK
}
}
Ask Codex to run a shell command that prints a fake secret, for example:
Write-Output 'OPENAI_API_KEY=sk-POSTTOOLPROBE1234567890'
Actual
Codex reports:
PostToolUse hook (failed)
error: hook returned invalid post-tool-use JSON output
The model/transcript continues to see the original raw tool output.
Expected
Codex should either:
- support a documented replacement schema for
PostToolUseoutput, applied before the tool result is rendered/stored/passed to the model, or - clearly document that
PostToolUsecannot redact tool results and provide another pre-transcript interception point.
Reproduction B: blocking still renders raw output first
Configure a PostToolUse command hook that always returns a valid block payload:
{
decision: block,
reason: OPENAI_API_KEY=<<OPENAI_API_KEY_BLOCK_PROBE>>
}
Ask Codex to run:
Write-Output 'OPENAI_API_KEY=sk-postblockprobeABCDEFGHIJKLMNOP'
Actual TUI transcript
The raw output is shown before the hook block feedback:
• Ran Write-Output 'OPENAI_API_KEY=sk-postblockprobeABCDEFGHIJKLMNOP'
└ OPENAI_API_KEY=sk-postblockprobeABCDEFGHIJKLMNOP
• PostToolUse hook (blocked)
feedback: OPENAI_API_KEY=<<OPENAI_API_KEY_BLOCK_PROBE>>
The model's final answer saw the blocked/masked feedback, but the raw value had already appeared in the visible transcript.
Expected
If a PostToolUse hook blocks or redacts output, Codex should not render or persist the raw tool result in the user-visible transcript before applying the hook decision.
At minimum, a blocking PostToolUse result should suppress the raw output display and show only the hook-provided masked reason.
Why this matters
For privacy/security middleware, the relevant invariant is:
raw sensitive tool output must not reach the model, transcript, local session log, or visible UI before the masking layer runs.
This affects more than shell commands. It also matters for MCP/browser/connector tools that can return API keys, passwords, access tokens, recovery phrases, or private page contents. Without a pre-transcript replacement/suppression mechanism, integrations have to either block high-risk tools in PreToolUse or proxy all external tools outside Codex, which hurts UX and makes built-in tools difficult to protect.
Requested behavior
Please add and document one of these:
- A supported
PostToolUsereplacement contract, e.g. a stableupdatedToolOutput-style payload that is applied before transcript/model/log persistence. - A
PostToolUseblock behavior that suppresses raw output rendering and persistence. - A new pre-render/pre-model hook point for tool results that can replace or redact output before Codex stores or displays it.
Related broad hook parity tracker: #21753. This issue is specifically about the security/UX impact of raw output rendering before PostToolUse redaction/blocking.