fix(config): redact sensitive CLI argv values in config-audit.jsonl#70468
fix(config): redact sensitive CLI argv values in config-audit.jsonl#70468Ziy1-Tan wants to merge 1 commit intoopenclaw:mainfrom
Conversation
Greptile SummaryThis PR fixes a real security issue:
Confidence Score: 4/5Hold for the argv join/split correctness fix before merging. The security goal is sound and the approach is directionally correct, but the join-then-split round-trip produces a structurally wrong argv array whenever any argument contains a space. This is a present defect on the changed code path (wrong data written to the audit log), not a hypothetical, warranting a 4 rather than a 5. src/config/io.audit.ts — the resolveConfigAuditProcessInfo redaction logic needs the per-element approach. Prompt To Fix All With AIThis is a comment left during a code review.
Path: src/config/io.audit.ts
Line: 180-189
Comment:
**`join(" ").split(" ")` corrupts argv entries that contain spaces**
Joining the argv array with a space delimiter and then splitting the redacted result back on spaces destroys the original token boundaries. Any argument that itself contains a space — e.g. `process.argv[1]` pointing to a path like `/home/user/my project/openclaw.js`, or a flag value like `--message "hello world"` — gets silently split into multiple elements in the written audit record.
A path-safe approach is to redact each element independently:
```ts
const rawArgv = process.argv.slice(0, 8);
const redactedArgv = rawArgv.map((arg) =>
redactSensitiveText(arg, {
mode: "tools",
patterns: [...getDefaultRedactPatterns(), ...AUDIT_ARGV_EXTRA_PATTERNS],
}),
);
return {
pid: process.pid,
ppid: process.ppid,
cwd: process.cwd(),
argv: redactedArgv,
execArgv: process.execArgv.slice(0, 8),
};
```
This still matches multi-word patterns (e.g. `--token value`) because each element is compared against patterns that also match the `=`-delimited form, and space-separated values land in adjacent elements which the existing `\s+` variant covers when the flag and value happen to be in the same element.
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: src/config/io.audit.test.ts
Line: 222-226
Comment:
**`AUDIT_ARGV_EXTRA_PATTERNS` duplicated instead of exported**
The test file manually mirrors the `AUDIT_ARGV_EXTRA_PATTERNS` constant from `io.audit.ts` with a comment saying "Mirror the pattern constant from io.audit.ts to exercise it directly in tests." If the production constant is updated (new flag names, tweaked regex), the test copy will silently diverge and the tests will no longer validate the actual patterns in use.
Consider exporting `AUDIT_ARGV_EXTRA_PATTERNS` from `io.audit.ts` and importing it here, so the tests always exercise the real constant rather than a copy.
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "fix(config): redact sensitive CLI argv v..." | Re-trigger Greptile |
f404be5 to
2ca6a1c
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f404be5b77
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
2ca6a1c to
e313ec1
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e313ec1fb4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
config-audit.jsonl records process argv as part of tamper-detection audit entries. Commands containing secret-bearing flags (--token, --bot-token, --gateway-token, --password, etc.) would persist those values in plaintext on disk. Changes: - Add AUDIT_ARGV_EXTRA_PATTERNS in io.audit.ts: extends the default CLI flag redaction pattern with missing flag names (bot-token, gateway-token, app-token, access-token, custom-api-key) and adds `=` as a separator for --flag=value format. - In resolveConfigAuditProcessInfo(), join argv to a single string, apply redactSensitiveText with the extended patterns, and store as a single-element array. This avoids join/split boundary corruption while reusing the existing redaction infrastructure; flag names are preserved in the output for diagnostics. - Export resolveConfigAuditProcessInfo() and replace the three inline process.argv.slice(0, 8) blocks in io.ts (x2) and io.observe-recovery.ts with ...resolveConfigAuditProcessInfo(). - Add unit tests covering each flag type, both --flag value and --flag=value formats, non-secret pass-through. Fixes openclaw#60826
e313ec1 to
7892635
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 78926356f8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| argv: [ | ||
| redactSensitiveText(process.argv.slice(0, 8).join(" "), { |
There was a problem hiding this comment.
Keep argv tokenized after redaction
resolveConfigAuditProcessInfo() now wraps the redacted command string in a single-element array, so every config.write/config.observe audit record loses original argv token boundaries (argv[0] becomes the full command line). This is a behavior regression from the previous process.argv.slice(0, 8) shape and can break tooling or incident triage logic that reads positional args (for example command/subcommand detection from argv[1]/argv[2]). Redaction should preserve the array contract instead of collapsing all args into one entry.
Useful? React with 👍 / 👎.
Summary
config-audit.jsonlrecordsprocess.argvas part of tamper-detection audit entries. Any command containing secret-bearing flags (e.g.--token,--bot-token,--gateway-token) would persist those values in plaintext on disk permanently.Fixes #60826. Related prior attempt: #60871 (closed due to author PR queue limit, not a technical rejection).
Changes
src/config/io.audit.ts: ImportredactSensitiveText/getDefaultRedactPatternsfromlogging/redact. AddAUDIT_ARGV_EXTRA_PATTERNSconstant that extends the default CLI flag pattern with missing flag names (bot-token,gateway-token,app-token,access-token,custom-api-key) and=as a separator (to cover--flag=valueformat). Apply redaction viajoin(" ") → redactSensitiveText → split(" ")inresolveConfigAuditProcessInfo(). Export the function.src/config/io.ts: ImportresolveConfigAuditProcessInfo. Replace two inlinepid/ppid/cwd/argv/execArgvblocks (lines ~662 and ~796) with...resolveConfigAuditProcessInfo().src/config/io.observe-recovery.ts: ImportresolveConfigAuditProcessInfo. Replace one inline block with...resolveConfigAuditProcessInfo().src/config/io.audit.test.ts: Add tests for redaction of--token,--token=value,--bot-token,--gateway-token,--password=value,--app-token,--access-token,--custom-api-key; non-secret flag pass-through; empty argv.Design
Reuses existing
redactSensitiveTextinfrastructure (same pattern used insrc/gateway/ws-log.ts). TheprocessInfooverride path inresolveConfigAuditProcessInfois intentionally left unredacted — callers that supply their ownprocessInfo(e.g. tests) receive it back as-is.typecheck prodfailure in CI is pre-existing onmainand unrelated to this change.Test plan
pnpm test src/config/io.audit.test.ts— 17 tests pass (13 existing + 10 new)pnpm test src/config/io.observe-recovery.test.ts— existing tests unaffectedprocess.argv.sliceoutsideresolveConfigAuditProcessInfoAI-assisted
This PR was AI-assisted (Claude). Code reviewed and understood by the author. Testing: fully tested.
Post-Deploy Monitoring & Validation
No runtime behavior change. The audit log is best-effort and write-only from the perspective of the tamper-detection logic. No metrics or dashboards to watch. Validation: confirm
config-audit.jsonlentries no longer contain plaintext token values after runningopenclaw gateway install --token=<value>under anomaly conditions.