Skip to content

sec (7/9): redact declared scanner env values from error text#31

Open
jesse-merhi wants to merge 1 commit into
sec/06-isolated-cwdfrom
sec/07-redact-env-errors
Open

sec (7/9): redact declared scanner env values from error text#31
jesse-merhi wants to merge 1 commit into
sec/06-isolated-cwdfrom
sec/07-redact-env-errors

Conversation

@jesse-merhi

Copy link
Copy Markdown
Member

What this changes

Part 7 of 9 in the BYOS security-hardening stack. Stacked on sec (6/9) (#30). This is the last of the additive guardrails; parts 8 and 9 change existing behavior and get their own writeups.

A user-defined scanner declares the env vars it needs — and it declares them because they carry secrets (an API token, say). When the scanner command fails, ClawScan builds an error string from the command's stderr and stores it in the run artifact as ScannerResult.Error. If the scanner echoed its token into stderr (many tools print the failing request, headers included), that secret would be written into the artifact.

ClawScan already has a generic "does this look like a secret name" heuristic, but it can miss a value whose variable name doesn't match the pattern. The declared env list is ground truth: those names were explicitly registered as this scanner's secrets.

The fix

Two small helpers:

  • sanitizedDeclaredEnvNames — turns the declared env: entries into bare names (defensively dropping any =value suffix).
  • redactDeclaredEnvValues — replaces every declared env value found in the error text with [redacted].

Wired into the error path:

message := commandError(runErr, output.Stderr, runner.Env)
message = redactDeclaredEnvValues(message, runner.Env, sanitizedDeclaredEnvNames(adapter.config.Env))

So whatever the variable is named, its value cannot survive in ScannerResult.Error. This upholds the repo rule that artifacts record env presence, never secret values.

Verify

go test -count=1 ./internal/runner/ -run 'RedactDeclaredEnv|SanitizedDeclaredEnv|RedactsDeclaredEnvInError'

New tests:

  • TestSanitizedDeclaredEnvNamesStripsValuesSECRET_KEY=value, TOKEN, EMPTY= → names SECRET_KEY, TOKEN, EMPTY.
  • TestRedactDeclaredEnvValuesRemovesSecrets — the value is replaced by [redacted].
  • TestUserDefinedScannerRedactsDeclaredEnvInError — end to end: a failing scanner whose stderr contains the secret produces an Error with [redacted] and without the secret value.

The full internal/runner suite passes apart from two pre-existing macOS /var/private/var symlink tests (TestResolveTargetClassifiesPlugin{Directory,ManifestFile}), which are unrelated to this change.

A user-defined scanner declares env vars precisely because they carry secrets.
When the command fails, commandError composes an error string from stderr that
can echo those secret values, and that string persists in ScannerResult.Error.
Scrub the value of every declared env var from the error text, regardless of
the variable name, so credentials never survive in the artifact even when the
name evades the generic secret-name heuristic.
Copilot AI review requested due to automatic review settings July 23, 2026 12:59

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@clawsweeper

clawsweeper Bot commented Jul 23, 2026

Copy link
Copy Markdown

ClawSweeper status: review started.

I am starting a fresh review of this pull request: sec (7/9): redact declared scanner env values from error text 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.

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.

2 participants