Address PR #75095 review:
- Add a suffix-based heuristic so any `--<...>-(token|secret|password|
passwd|api[-_]?key|api[-_]?secret|webhook|credential|bearer|pat)` is
treated as a secret flag in addition to the explicit list. This
catches `--custom-api-key`, `--alibaba-model-studio-api-key`,
plugin-defined `cliFlag` values, and similar flags that ship in
OpenClaw + bundled plugins today and were previously falling through
to the per-element token-shape fallback (which can miss arbitrary
provider keys with no recognizable prefix).
- Expand the explicit list with adjacent secret flags surfaced by
Copilot (`--app-token`, `--remote-token`, `--push-token`,
`--bearer-token`, `--id-token`, `--identity-token`,
`--session-token`, `--service-token`, `--pat`,
`--personal-access-token`, `--oauth-token`, `--webhook-token`).
- Stop masking the next arg when a secret flag is followed by another
option (`--token --port 8080` should not mask `--port`). Treat that
as a missing value and keep the following arg intact.
- Cap caller-supplied processInfo argv/execArgv at 8 entries via a new
capArgv helper so a future caller can't bypass the snapshot length
bound and persist arbitrarily large argv to the audit log.
4 new tests cover: heuristic flag detection (`--custom-api-key`,
`--alibaba-model-studio-api-key`, `--app-token`,
`--frobnicate-credential`), no-mask when secret flag is followed by
another option, no-mask when secret flag is the final arg without a
value, and the slice(0, 8) cap with a long argv that smuggles a
sensitive value past index 8 into a confirmed-not-present assertion.
`config-audit.jsonl` is the persistent record of config writes/observes
under `~/.openclaw/logs/`. It captures `process.argv.slice(0, 8)` raw at
four sites (write-audit, async observe, sync observe, observe-recovery
record builder), so any token passed as a CLI flag (gateway tokens, bot
tokens, hook tokens, exec'd `op read`/op-style tokens) lands at rest in
a mode-0600 file indefinitely. The mechanism designed to detect config
tampering becomes the credential-leak vector itself.
Centralize the snapshot and redact at the boundary:
- New `snapshotConfigAuditProcessInfo()` in src/config/io.audit.ts wraps
the `process.*` reads and routes argv/execArgv through a new
`redactConfigAuditArgv()` helper.
- redactConfigAuditArgv has three layers per element:
1. `--flag=value` for known secret flag names → mask the value half.
2. value following a bare `--flag` → emit `***`.
3. fall through to redactToolPayloadText (force-on tools mode using
the shared logging.redactPatterns defaults) for the remaining
standalone token shapes — sk-/ghp_/xox*/gsk_/AIza*/npm_, Telegram
bot tokens, PEM blocks, Bearer headers, URL query secrets,
`KEY=VALUE` env-style assignments.
- `resolveConfigAuditProcessInfo` (write-base path) now also redacts a
caller-supplied processInfo, so test/non-default callers can't bypass.
- The three other inline `process.argv.slice(0, 8)` sites in io.ts
(sync + async observe) and io.observe-recovery.ts now spread
`...snapshotConfigAuditProcessInfo()` instead.
Five new tests cover: secret-flag value redaction (space-separated and
=-form), shared-pattern fallback for standalone token shapes, untouched
non-secret args, and end-to-end via createConfigWriteAuditRecordBase
with a crafted processInfo.
Fixes#60826
Preserve the existing wrapped OpenAI Codex stream so PI OAuth bearer injection reaches ChatGPT/Codex Responses, and scope native Codex payload sanitization to the ChatGPT backend.\n\nThanks @keshavbotagent.