Redact exec tool result payloads#81185
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 20, 2026, 2:58 PM ET / 18:58 UTC. Summary PR surface: Source +294, Tests +633, Other -1. Total +926 across 19 files. Reproducibility: yes. from source and supplied live proof: emitting a fake secret-shaped assignment through exec or process output reaches the returned tool-result boundary, and the branch’s canary run shows that boundary masked after the change. Review metrics: 2 noteworthy metrics.
Stored data model Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review detailsBest possible solution: Have an exec/runtime security owner explicitly adopt the redacted-by-default contract, retain the structured marker and visible warning, then rebase and land the exact reviewed merge result after the upstream scan is rerun. Do we have a high-confidence way to reproduce the issue? Yes from source and supplied live proof: emitting a fake secret-shaped assignment through exec or process output reaches the returned tool-result boundary, and the branch’s canary run shows that boundary masked after the change. Is this the best way to solve the issue? Unclear pending maintainer policy approval: the shared formatter boundary is the narrowest maintainable implementation, but redacted-by-default versus a supported raw-output recovery path is a product/security contract choice. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against ba3711bb825d. Label changesLabel justifications:
Evidence reviewedPR surface: Source +294, Tests +633, Other -1. Total +926 across 19 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (19 earlier review cycles; latest 8 shown)
|
|
Added real behavior proof to the PR body using an obvious fake canary ( @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
a67fbbe to
da701a0
Compare
|
Updated the PR body with the required real behavior proof field labels and added process-list coverage plus the node-host testing note. The Real behavior proof check is now passing. @clawsweeper re-review |
|
Rebased onto current main to resolve the stale-base Also addressed the ClawSweeper [P1] finding: applied @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Maintainer/security review request: #81185 is ready for maintainer look after confirming #71211 is still present in v2026.6.6. ClawSweeper now has this at The remaining merge decision is whether maintainers accept the returned exec/process/node-host raw-output compatibility tradeoff to close the P1 tool-result secret exposure. |
|
@clawsweeper re-review Branch rebased onto current main for daily watcher. Current head: 6d64410. Previous red CI was check-prod-types on old head 945c0a9, failing in extensions/telegram/src/rich-message.ts outside this PR diff; fresh CI is queued after rebase. |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
|
@steipete quick maintainer/security decision request on this one since it has been sitting since May 12 and now has the June 18 ClawSweeper diamond-lobster review, sufficient proof, and green checks. The remaining question appears to be maintainer/security acceptance of redacted exec/process/node-host tool-result output as the default contract. Is that acceptable to merge, or should I split out an explicit raw-output reveal path before this lands? |
|
Pushed follow-up head: Addresses the ClawSweeper P1 active-reference gap from the June 20 review:
Local lightweight validation on a clean checkout of I attempted the two focused Vitest files locally, but stopped the Pi run after it stayed in bundler/plugin timing churn for over a minute. GitHub CI is running on the pushed head. @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
Pushed follow-up head: This fixes the exact embedded-agent CI failures from Final-head runtime proof for the ClawSweeper P1 proof request: {
"proof": "PR 81185 active process runtime/compaction context redaction",
"head": "ff43a0bfe7603a5a55e0fdbf075b4d56eb942df4",
"fakeSecretOutput": "OPENAI_API_KEY=sk-proj-redaction-canary-1234567890",
"results": [
{
"label": "compaction",
"activeProcessSessions": [
{
"sessionId": "sess-active-secret",
"status": "running",
"startedAt": 1782017342173,
"runtimeMs": 1,
"cwd": "/tmp",
"command": "node worker.js --token ***",
"name": "node worker.js",
"tail": "last output OPENAI_API_KEY=***",
"truncated": false
}
],
"containsRawFakeSecret": false,
"commandRedacted": true,
"tailRedacted": true
},
{
"label": "afterTurn",
"activeProcessSessions": [
{
"sessionId": "sess-session-secret",
"status": "running",
"startedAt": 1782017342219,
"runtimeMs": 1,
"cwd": "/tmp",
"command": "node worker.js --token ***",
"name": "node worker.js",
"tail": "last output OPENAI_API_KEY=***",
"truncated": false
}
],
"containsRawFakeSecret": false,
"commandRedacted": true,
"tailRedacted": true
}
]
}Local checks on a clean worktree: Focused Vitest for the two embedded-agent files was attempted locally but did not finish in a bounded Pi-local window due repeated bundler plugin timing churn. Exact-head GitHub CI is running after this push. @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
Hi! Small heads-up: ClawSweeper had a short-lived label/comment sync bug that may have affected this PR. Your latest ClawSweeper review comment appears to be for the current PR head and says this is ready for maintainer review, but the ready/proof/rating labels were later removed by stale local review state. The ClawSweeper fix has merged, but this PR needs a fresh author-triggered review so the labels and comment are reconciled again. Could you please post a new comment asking ClawSweeper to re-review? Use the bot mention followed by Thanks, and sorry for the noise. |
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
Hey @steipete / @openclaw/openclaw-secops — quick nudge on #81185. I know everyone’s got a lot moving, so I’m trying not to keep poking this unnecessarily. This one has been open since May, checks are green, and ClawSweeper has it at proof: sufficient / ready for maintainer look. I think the remaining blocker is not more code from me, but a maintainer/security call on the policy tradeoff:
My preferred path is to merge the default-redaction fix as-is, then track an explicit raw-output reveal control separately if maintainers want that escape hatch. But if you’d rather require that reveal path in this PR before merge, I can add it. I’ll keep the branch clean and mergeable while this is waiting, but I’m trying to avoid unnecessary churn unless CI breaks or maintainers ask for a change. Could someone make the merge/no-merge call or point me at the right owner for that decision? |
|
Rebased onto current main and patched the remaining node-host warning redaction gap. Node-host warnings are now passed through Validation:
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@clawsweeper re-review Addressed the P1 redaction-marker finding at head 6b6f96e:
Proof (local, at this head): |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review Repost: re-review requested for head 6b6f96e (redaction-marker P1 addressed; proof in previous comment). |
|
@clawsweeper re-review Head a79c902: merged origin/main (conflict was our test-only 'testing' seam vs #106956 seam removal — resolved by dropping the seam and importing builders directly from bash-tools.exec-result-format.ts; EXEC_REDACTION_WARNING is no longer exported, tests derive it via prependRedactionWarning). Proof re-run locally: git diff --check, oxfmt, oxlint, tsgo core, deadcode-exports clean for our files, and 296 focused tests + contracts/send-keys shards pass. Prior CI failures (OpenClawKit dead-code intersect, extension-runtime-dependencies lobster contract) were base drift fixed on current main. |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Exact-head CI infrastructure note for 69e5972: Scan changed paths (precise) failed before any scan ran because the Opengrep installer could not fetch available versions from GitHub; the SARIF upload then had no file. The completed code matrix is green. Contributor credentials cannot rerun this upstream workflow (GitHub requires repository admin), so a maintainer rerun is requested. This is not a scan finding. |
|
@clawsweeper re-review Refreshed non-force through current main at f766cc0. Exact-head CI is complete with zero failures or pending checks. Local refresh proof passed 317/317 focused exec/process redaction tests, core and core-test typechecks, touched-file format/lint, max-lines ratchet, conflict scan, and diff hygiene. |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review Refreshed exact head |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Receipt correction: the exact current head is |
|
ClawSweeper status: review started. I am starting a fresh review of this pull request: Redact exec tool result payloads This is item 1/1 in the current shard. Shard 0/1. This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking. Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted. |
2026-07-20 refresh
Summary
details.aggregatedbefore returning results to the agentReal behavior proof
Behavior or issue addressed: Exec and background process tool results could return secret-shaped stdout/stderr/session text back to the agent. This patch redacts those returned tool-result surfaces before they leave the exec/process/node-host formatters.
Real environment tested: Real local OpenClaw checkout on branch
fix/exec-tool-result-redactionatda701a0bbf6c, using an isolated temporaryOPENCLAW_HOME. The proof used an obvious fake canary value, not a real credential.Exact steps or command run after this patch: Ran a local runtime proof that exercised
createExecToolandcreateProcessToolwith a fakeREDACTION_CANARY_SECRETvalue, then inspected the returned tool-resultcontent[0].textand structureddetails.aggregatedvalues for foreground exec, process poll, process log, and process list tail/details surfaces.Evidence after fix: Copied live output from the local runtime proof:
{ "foregroundExec": { "status": "completed", "text": "REDACTION_CANARY_SECRET=clawsw…7890", "detailsAggregated": "REDACTION_CANARY_SECRET=clawsw…7890", "rawCanaryValuePresent": false, "redactedMarkerPresent": true }, "processPoll": { "status": "completed", "text": "REDACTION_CANARY_SECRET=clawsw…7890\n\n\nProcess exited with code 0.", "detailsAggregated": "REDACTION_CANARY_SECRET=clawsw…7890\n", "rawCanaryValuePresent": false, "redactedMarkerPresent": true }, "processLog": { "status": "completed", "text": "REDACTION_CANARY_SECRET=clawsw…7890", "detailsAggregated": "", "rawCanaryValuePresent": false, "redactedMarkerPresent": true }, "processList": { "status": "completed", "textTail": "REDACTION_CANARY_SECRET=clawsw…7890", "rawCanaryValuePresent": false, "redactedMarkerPresent": true } }Supplemental focused regression coverage also exercises node-host exec stdout redaction by passing a fake node
system.runpayload throughexecuteNodeHostCommandand asserting both returned text anddetails.aggregatedredact the raw canary.Observed result after fix: The raw fake canary value was absent from returned foreground exec, process poll, process log, and process list output. Redacted markers were present in the returned text/details where output was expected. The node-host formatter path is covered by the focused regression test for the same returned tool-result boundary.
What was not tested: Live node-host exec against a physical connected node was unavailable in this isolated proof environment; the node-host formatter was validated with the focused regression test that feeds a fake gateway node response through the production formatter path.
Tests
corepack pnpm exec oxfmt --write --threads=1 src/agents/bash-tools.exec.ts src/agents/bash-tools.exec-host-node-phases.ts src/agents/bash-tools.process.ts src/agents/bash-tools.exec-foreground-failures.test.ts src/agents/bash-tools.exec-host-node.test.ts src/agents/bash-tools.process.poll-timeout.test.tsgit diff --checkcorepack pnpm tsgo:corecorepack pnpm tsgo:core:testcorepack pnpm exec vitest run --config test/vitest/vitest.agents-core.config.ts src/agents/bash-tools.exec-foreground-failures.test.ts -t 'redacts secret-shaped stdout'corepack pnpm exec vitest run --config test/vitest/vitest.agents-core.config.ts src/agents/bash-tools.process.poll-timeout.test.ts -t 'redacts secret-shaped output'corepack pnpm exec vitest run --config test/vitest/vitest.agents-core.config.ts src/agents/bash-tools.exec-host-node.test.ts -t 'redacts secret-shaped node stdout'Notes: a full local run of the three targeted files is currently blocked in my environment by an unrelated invalid local
~/.openclaw/openclaw.jsonmodel alias (openai-codex/gpt-5.3-codex) during the pre-existing foreground timeout test. The new redaction regression tests pass individually under the agents-core Vitest config.Fixes #71211
Follow-up after review
bc79136bb7to redact background execdetails.tailbefore returning running-session tool results.details.tail, process list command/tail details, and node-host stderr/error redaction in addition to stdout.Additional local verification after follow-up:
corepack pnpm tsgo:corecorepack pnpm tsgo:core:testcorepack pnpm exec vitest run --config test/vitest/vitest.agents-core.config.ts src/agents/bash-tools.exec-foreground-failures.test.ts -t 'redacts secret-shaped'corepack pnpm exec vitest run --config test/vitest/vitest.agents-core.config.ts src/agents/bash-tools.process.poll-timeout.test.ts -t 'redacts secret-shaped'corepack pnpm exec vitest run --config test/vitest/vitest.agents-core.config.ts src/agents/bash-tools.exec-host-node.test.ts -t 'redacts secret-shaped node'git diff --checkNote: the full local three-file Vitest run still hits the pre-existing environment-sensitive approval path in
exec foreground failures > returns a failed text result when the default timeout is exceeded, where local host exec approval interceptssleep 5before the timeout assertion.Review feedback update - 2026-05-21
openclaw agent --jsonfallback behavior is back to the existing contract.runExecProcessregression coverage, so the previous single-line skip branches are gone.8793847f206cca93c49abe33e4f49b9b55a0c4dc.Additional verification on final head:
node scripts/run-vitest.mjs src/agents/bash-tools.exec-foreground-failures.test.ts -t 'redacts secret-shaped'\n-node scripts/run-vitest.mjs src/agents/bash-tools.exec-runtime.test.ts -t 'redacts secret-shaped stdout in update text and details tail'\n-node scripts/run-vitest.mjs src/commands/agent-via-gateway.test.ts -t 'JSON'\n-node scripts/run-vitest.mjs src/agents/bash-tools.process.poll-timeout.test.ts -t 'redacts secret-shaped'\n-node scripts/run-vitest.mjs src/agents/bash-tools.exec-host-node.test.ts -t 'redacts secret-shaped node'\n-pnpm exec oxlint src/agents/bash-tools.exec-foreground-failures.test.ts src/agents/bash-tools.exec-runtime.test.ts src/commands/agent-via-gateway.ts src/commands/agent-via-gateway.test.ts src/cli/program/register.agent.ts src/cli/program/register.agent.test.ts\n-git diff --check && git diff --cached --check\n\nChanged-file gate note:node scripts/crabbox-wrapper.mjs run --shell -- "pnpm check:changed"did not reach pnpm because localcrabboxfailed its binary sanity check. Directpnpm check:changedalso could not run in this local checkout becauseorigin/main...HEADhas no merge base on the grafted/shallow branch. The focused tests, lint, and diff checks above passed on the final head.Process control redaction update - 2026-05-21
write,submit,paste) pluskill,remove,poll,log,list, andsend-keys.process writeandprocess send-keyscommand-deriveddetails.namevalues.24ac21f4280e9e403722c271d12fda0a4c68535d4.Additional verification on final head:
node scripts/run-vitest.mjs src/agents/bash-tools.process.poll-timeout.test.ts -t 'redacts secret-shaped'\n-node scripts/run-vitest.mjs src/agents/bash-tools.process-send-keys.test.ts -t 'redacts secret-shaped'\n-node scripts/run-vitest.mjs src/agents/bash-tools.exec-foreground-failures.test.ts -t 'redacts secret-shaped'\n-node scripts/run-vitest.mjs src/agents/bash-tools.exec-runtime.test.ts -t 'redacts secret-shaped stdout in update text and details tail'\n-node scripts/run-vitest.mjs src/agents/bash-tools.exec-host-node.test.ts -t 'redacts secret-shaped node'\n-pnpm exec oxlint src/agents/bash-tools.process.ts src/agents/bash-tools.process-send-keys.ts src/agents/bash-tools.process.poll-timeout.test.ts src/agents/bash-tools.process-send-keys.test.ts\n-git diff --check && git diff --cached --check