Skip to content

fix(cli): redact secret-shaped values in startup args log and apiMachine debug log#1297

Open
YOMXXX wants to merge 1 commit into
slopus:mainfrom
YOMXXX:fix/cli-redact-secret-args-in-logs
Open

fix(cli): redact secret-shaped values in startup args log and apiMachine debug log#1297
YOMXXX wants to merge 1 commit into
slopus:mainfrom
YOMXXX:fix/cli-redact-secret-args-in-logs

Conversation

@YOMXXX
Copy link
Copy Markdown

@YOMXXX YOMXXX commented May 18, 2026

Closes #1279.

Bug

`happy --claude-env ANTHROPIC_TOKEN=sk-…` (or any `--claude-env KEY=VAL` where KEY names a token / API key / secret / auth header) writes the VALUE verbatim into `~/.happy/logs/-pid-*.log`, because the CLI entry point logs `process.argv` unfiltered:

```ts
// packages/happy-cli/src/index.ts:44
logger.debug('Starting happy CLI with args: ', process.argv)
```

The log file is created with the default Node file mode (0o644 in practice), so any local UID can read it. If a user has opted into `DANGEROUSLY_LOG_TO_SERVER_FOR_AI_AUTO_DEBUGGING`, the same line is forwarded over HTTP to a remote endpoint, exfiltrating the token off the host. This affects any wrapper that injects bearer credentials — proxies, custom Anthropic-compatible endpoints, internal gateways.

The same shape also reaches `apiMachine.ts:127`, where the entire `spawn-happy-session` RPC params object — including `token`, `encryptionKey`, `environmentVariables` — is `JSON.stringify`'d into a debug log line. This PR fixes both call sites.

Fix

New `packages/happy-cli/src/utils/redactSecrets.ts`:

  • `SECRET_NAME_PATTERN` — case-insensitive substring match for `token / key / secret / auth / password / credential`.
  • `redactArgvForLog(argv)` — replaces the VALUE half of any `KEY=VAL` arg when KEY matches the pattern. Non-`=`-shaped args pass through unchanged.
  • `redactObjectForLog(value)` — recursively rewrites the VALUE of any property whose name matches the pattern OR is in the force-redact set (`encryptionKey`, `environmentVariables`). Plain objects + arrays are descended into; `Date` / `RegExp` / typed-array values are returned as-is.

Applied at two call sites:

  • `index.ts:44` — wraps the `process.argv` startup log.
  • `apiMachine.ts:128` — wraps the spawn-session params log.

Scope

  • New file: `packages/happy-cli/src/utils/redactSecrets.ts` (~80 LOC, no runtime deps).
  • New test: `redactSecrets.test.ts` — 11 unit tests covering argv redaction (KEY=VAL detection, case-insensitive, empty inputs, values containing `=`) + object redaction (top-level, nested, arrays, force-redact list, primitives passthrough, Date/RegExp/typed-array passthrough).
  • Two existing files modified to call the helpers.
  • No API change; no behavior change for users not passing secrets via `--claude-env`.

Test plan

  • `pnpm --filter happy typecheck` — passes
  • `pnpm exec vitest run src/utils/redactSecrets.test.ts` — 11/11 pass
  • Manual: `happy --claude-env ANTHROPIC_TOKEN=secret-test-123 codex` → `grep secret-test-123 ~/.happy/logs/*.log` → 0 matches; previous unredacted line is now `ANTHROPIC_TOKEN=[REDACTED]`.

Notes

The redaction pattern is intentionally substring-based, not whole-word — so it catches `ANTHROPIC_TOKEN`, `OAUTH_TOKEN`, `accessToken`, `apiKey`, `SECRET_KEY`, `x-auth-header`, etc. False positives (legitimately non-secret args whose key happens to contain "token" / "key" / etc.) can be added to a future allow-list constant; none observed in the current CLI surface.

Related: there is a class of secret-shaped values that still reach logs from other call sites (e.g. `runCodex.ts`'s token-file write path, various `JSON.stringify` of session metadata). This PR fixes the two highest-impact paths reported in #1279; the same helpers can be applied to the rest in a follow-up audit pass.

…ine debug log

Closes slopus#1279.

## Bug

`happy --claude-env ANTHROPIC_TOKEN=sk-…` (or any `--claude-env KEY=VAL`
where KEY names a token / API key / secret / auth header) writes the
VALUE verbatim into `~/.happy/logs/<timestamp>-pid-*.log`, because the
CLI entry point logs `process.argv` unfiltered:

  packages/happy-cli/src/index.ts:44
  logger.debug('Starting happy CLI with args: ', process.argv)

The log file is created with the default Node file mode (0o644 in
practice), so any local UID can read it. If a user has opted into
`DANGEROUSLY_LOG_TO_SERVER_FOR_AI_AUTO_DEBUGGING`, the same line is
forwarded over HTTP to a remote endpoint, exfiltrating the token off
the host. This affects any wrapper that injects bearer credentials —
proxies, custom Anthropic-compatible endpoints, internal gateways.

The same shape also reaches `apiMachine.ts:127`, where the entire
`spawn-happy-session` RPC params object — including `token`,
`encryptionKey`, `environmentVariables` — is `JSON.stringify`'d into
a debug log line.

## Fix

New `packages/happy-cli/src/utils/redactSecrets.ts`:

- `SECRET_NAME_PATTERN` — case-insensitive substring match for
  `token / key / secret / auth / password / credential`.
- `redactArgvForLog(argv)` — replaces the VALUE half of any
  `KEY=VAL` arg when KEY matches the pattern. Non-`=`-shaped args
  pass through unchanged.
- `redactObjectForLog(value)` — recursively rewrites the VALUE of
  any property whose name matches the pattern OR is in the
  force-redact set (`encryptionKey`, `environmentVariables`). Plain
  objects + arrays descended into; Date / RegExp / typed-array
  values returned as-is.

Applied at:
- `index.ts:44` — wraps the `process.argv` startup log.
- `apiMachine.ts:128` — wraps the spawn-session params log.

## Scope

- New file: `packages/happy-cli/src/utils/redactSecrets.ts` (~80 LOC).
- New test: `redactSecrets.test.ts` — 11 unit tests covering argv
  redaction (KEY=VAL detection, case-insensitive, empty inputs,
  values containing `=`), object redaction (top-level, nested,
  arrays, force-redact list, primitives passthrough, Date/RegExp/
  typed-array passthrough).
- Two existing files modified to call the helpers.
- No API change; no behavior change for users not passing secrets.

`pnpm --filter happy typecheck` passes; new redactSecrets test file
goes 11/11.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

--claude-env flag values logged in plaintext (security: tokens leaked to disk)

1 participant