fix(gateway): redact fast-path console logs#76306
Conversation
|
Codex review: needs maintainer review before merge. Summary Reproducibility: yes. Current-main source shows the Gateway foreground fast path parses before console capture and verbose mode bypasses prefix suppression, and the PR body includes copied before/after live Gateway output. Real behavior proof Next step before merge Security Review detailsBest possible solution: Land the scoped console-capture ordering and sensitive-prefix suppression fix after required CI is green or failures are confirmed unrelated, keeping the change limited to logging redaction. Do we have a high-confidence way to reproduce the issue? Yes. Current-main source shows the Gateway foreground fast path parses before console capture and verbose mode bypasses prefix suppression, and the PR body includes copied before/after live Gateway output. Is this the best way to solve the issue? Yes. Installing capture at the fast-path boundary and checking sensitive prefixes before verbose passthrough is the narrowest maintainable fix without changing WhatsApp protocol behavior, dependencies, auth, config, or networking. Acceptance criteria:
What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against 4e09538f4424. |
afde59d to
2d7b200
Compare
2d7b200 to
f864f8e
Compare
|
Landed via rebase onto Verification:
Thanks @rubencu! |
Summary
pnpm gateway:watch:raw/ foregroundopenclaw gatewaycould print WhatsApp/libsignal session objects from dependencyconsole.*calls before OpenClaw installed console capture.program.parseAsync(...), and known libsignal session-dump prefixes are suppressed before verbose-mode passthrough.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
Real behavior proof (required for external PRs)
console.info("Closing session:", session)output reach the terminal before console capture/redaction was installed.scripts/run-node.mjs, isolatedHOMEandOPENCLAW_HOME, live Gateway on loopback with token auth and/healthzprobe.node /tmp/openclaw-pr76306-gateway-proof.mjs /Users/rubencu/workplace/openclaw-redact-gateway-console pr-head expect-suppressed{ "label": "pr-head", "cwd": "/Users/rubencu/workplace/openclaw-redact-gateway-console", "port": 37437, "health": "{\"ok\":true,\"status\":\"live\"}", "expected": "expect-suppressed", "leakedPrefix": false, "leakedSecret": false, "leakExcerpt": "", "exit": { "code": 130, "signal": null }, "outputTail": "2026-05-09T22:36:08.181-04:00 [gateway] ready\n2026-05-09T22:36:08.187-04:00 [heartbeat] started\n2026-05-09T22:36:11.236-04:00 [shutdown] completed cleanly in 16ms" }{"ok":true,"status":"live"}, then the injected libsignal-shaped dependency console output was absent from terminal capture (leakedPrefix=false,leakedSecret=false).Additional live WhatsApp gateway:watch proof on PR head:
{ "command": "node scripts/watch-node.mjs gateway --force --verbose", "config": "normal local OpenClaw config with WhatsApp account; raw output monitored with numbers redacted", "health": { "ok": true, "status": "live" }, "whatsappEvidence": "sessionKey=agent:main:whatsapp:direct:[number] entered processing, then outbound WhatsApp echo was skipped after reply delivery", "sensitivePrefix": 0, "sensitiveField": 0, "checkedPrefixes": ["Closing session:", "Opening session:", "Removing old closed session:", "Session already closed", "Session already open"], "checkedFields": ["currentRatchet", "ephemeralKeyPair", "privKey", "rootKey", "baseKey", "remoteIdentityKey"] }Observed result: the PR-head gateway:watch process loaded WhatsApp, listened for personal inbound messages, processed a live WhatsApp direct message, sent a reply, skipped the outbound echo, and did not emit any known libsignal session-dump prefix or key-field line in terminal output or the active file log.
{ "label": "main-rerun", "cwd": "/tmp/openclaw-pr76306-main-live", "base": "origin/main@8e8f7915b2573b355d514bd8bebf6a502913c2ab", "health": "{\"ok\":true,\"status\":\"live\"}", "expected": "expect-leak", "leakedPrefix": true, "leakedSecret": true, "leakExcerpt": "Closing session: {\n currentRatchet: {\n rootKey: '<FAKE_SECRET>',\n ephemeralKeyPair: { privKey: '<FAKE_SECRET>' }\n },\n indexInfo: {\n baseKey: '<FAKE_SECRET>',\n closed: -1\n },\n privKey: '<FAKE_SECRET>'\n}\n2026-05-09T22:34:32.940-04:00 [gateway] ready" }Root Cause (if applicable)
runCli(...)returns from the Gateway foreground fast path aftertryRunGatewayRunFastPath(...), while the normal CLIenableConsoleCapture()call lives later in the non-fast-path startup path.node_modules/libsignal/src/session_record.jslogsClosing session:,Opening session:, andRemoving old closed session:with session objects.Regression Test Plan (if applicable)
src/cli/run-main.exit.test.ts,src/logging/console-capture.test.tsenableConsoleCapture()beforeprogram.parseAsync(...), and libsignal session-dump prefixes are suppressed even when verbose mode is enabled.User-visible / Behavior Changes
Raw Gateway watch/foreground logs no longer print known WhatsApp/libsignal session-object dumps. Normal Gateway and WhatsApp behavior is unchanged.
Diagram (if applicable)
Security Impact (required)
Yes/No) NoYes/No) YesYes/No) NoYes/No) NoYes/No) NoYes, explain risk + mitigation: this reduces exposure of WhatsApp/libsignal session key material in raw Gateway terminal logs. It does not add access to secrets; it prevents known sensitive dependency console dumps from being emitted.Repro + Verification
Environment
HOMEandOPENCLAW_HOME; loopback Gateway token auth; no real WhatsApp secretsSteps
origin/main@8e8f7915b2573b355d514bd8bebf6a502913c2aband remove contributorCHANGELOG.mddrift.2d7b20064aa9b90c75287d9a16836b2f3f9f6f14.gateway:watchwith the normal local WhatsApp config, send a live WhatsApp direct message, and monitor terminal/file-log counters for known libsignal dump prefixes and key-field names.Expected
Actual
/healthzreturned{"ok":true,"status":"live"}and terminal capture includedClosing session:plus non-real session secret fields./healthzreturned{"ok":true,"status":"live"}and terminal capture reportedleakedPrefix=false,leakedSecret=false.gateway:watchloaded WhatsApp, processedagent:main:whatsapp:direct:[number], sent an outbound reply, skipped the echo, and terminal/file-log counters stayed atsensitivePrefix=0,sensitiveField=0.Evidence
Human Verification (required)
What you personally verified (not just CI), and how:
pnpm docs:listpnpm installafter rebase to refresh current dependency treenode /tmp/openclaw-pr76306-gateway-proof.mjs /tmp/openclaw-pr76306-main-live main-rerun expect-leaknode /tmp/openclaw-pr76306-gateway-proof.mjs /Users/rubencu/workplace/openclaw-redact-gateway-console pr-head expect-suppressednode scripts/watch-node.mjs gateway --force --verbosewith normal local WhatsApp config; processed a live WhatsApp direct-message turn; terminal/file-log counters stayedsensitivePrefix=0,sensitiveField=0pnpm test src/cli/run-main.exit.test.ts src/logging/console-capture.test.tspnpm exec oxfmt --check --threads=1 src/cli/run-main.ts src/cli/run-main.exit.test.ts src/logging/console.ts src/logging/console-capture.test.tsgit diff --checkpnpm changed:lanes --jsoncodex review --base origin/mainCHANGELOG.mdhas no PR diff.pnpm check/pnpm testbroad suites locally; changed lanes are core prod + core tests, and broad validation is left to PR CI.Review Conversations
Compatibility / Migration
Yes/No) YesYes/No) NoYes/No) NoRisks and Mitigations
node_modules/libsignal/src/session_record.js; a future dependency wording change can add a narrow prefix follow-up.