Skip to content

fix(export): redact secrets in-place instead of aborting#3383

Merged
la14-1 merged 2 commits intoOpenRouterTeam:mainfrom
AhmedTMM:fix-export-redact-secrets
May 2, 2026
Merged

fix(export): redact secrets in-place instead of aborting#3383
la14-1 merged 2 commits intoOpenRouterTeam:mainfrom
AhmedTMM:fix-export-redact-secrets

Conversation

@AhmedTMM
Copy link
Copy Markdown
Collaborator

@AhmedTMM AhmedTMM commented May 2, 2026

Summary

Before: matching any of the API-key regexes in a staged file killed the export — the user got a JSON error and had to SSH in and clean up by hand.

After: matched strings are replaced with `REDACTED-BY-SPAWN-EXPORT` via `sed -i -E`, the file is re-staged, and the export proceeds. The redacted file list is included in the success result and surfaced on the host CLI:

```
✓ Exported to https://github.com/alice/my-vm
⚠ Redacted potential secrets in 1 file:

  • project/test/brain-sync.test.ts
    ```

Reproduces the user-reported failure where a test fixture (project/test/brain-sync.test.ts) tripped the scan and the whole export bailed.

Notes

  • Regex unchanged — same Anthropic / OpenRouter / OpenAI / GitHub / AWS / Hetzner / DO / PEM coverage as before.
  • Placeholder is intentionally loud (`REDACTED-BY-SPAWN-EXPORT`) so a reader of the public repo can tell something was scrubbed.
  • Result schema gains an optional `redacted: string[]` field; the host CLI shows it as a clack warning, not an error.
  • Bumps CLI `1.0.33` → `1.0.34`.

Test plan

  • `bunx @biomejs/biome check src/` — clean
  • `bun test` — 2168 pass / same 4 pre-existing fails
  • 34 export tests pass; legacy "aborts on hit" assertion replaced with new redact assertions
  • Manual: re-run the failing export from the user's session — confirm `brain-sync.test.ts` is redacted and the spawn link is printed

🤖 Generated with Claude Code

Before: any staged file matching the secret regex caused the export
to fail with `{"ok":false,"error":"Possible secrets detected..."}`,
forcing the user to SSH in and clean things up by hand.

After: matched strings are replaced with `***REDACTED-BY-SPAWN-EXPORT***`
via sed -i -E, the file is re-staged, and the export proceeds. The list
of redacted files is included in the success result and surfaced as a
warning on the host CLI:

  ✓ Exported to https://github.com/alice/my-vm
  ⚠ Redacted potential secrets in 1 file:
    - project/test/brain-sync.test.ts

The regex is unchanged. The redact placeholder is intentionally loud so
a casual reader of the published repo can tell that something was
scrubbed and isn't just blank.

Bumps CLI 1.0.33 -> 1.0.34.
@AhmedTMM AhmedTMM marked this pull request as ready for review May 2, 2026 07:19
Previously the VM would silently redact any staged files matching the
secret regex and push the repo — meaning a regex miss (OpenRouterTeam#3381 tracks
broadening) would publish a real secret without the user ever seeing
the file list. That's a fail-open posture on a tool that can push to
public GitHub.

New flow:

- buildExportScript takes allowRedact: boolean.
- First pass (allowRedact=false): VM stages, runs the secret scan,
  and on hits writes a needs_confirmation result (hits=[...]) and
  exits 0 before any commit or push. No hits → commit + push as
  before.
- Host reads the result. If needs_confirmation: print the file list,
  explain that the regex has known gaps, and ask "Redact these N files
  and continue pushing?" (initialValue false). Decline → exit 0, no
  push. Approve → re-run the script with allowRedact=true, which now
  actually does the sed + re-stage + commit + push.

Other changes:
- ResultSchema gains the needs_confirmation variant.
- cmdExport factors the runServer + downloadFile + parse cycle into
  runPassAndParseResult so the two-pass orchestration is readable.
- Tests: 4 new cases cover the gate scripting (ALLOW_REDACT=0 writes
  needs_confirmation and exits 0, ALLOW_REDACT=1 redacts) and the
  end-to-end host flow (approve → two passes with ALLOW_REDACT 0→1;
  decline → one pass, exit 0; no-secrets happy path → one pass, no
  confirm). 38/38 export tests, 2176/0 fail overall.
- CLI 1.0.34 → 1.0.35.
@la14-1
Copy link
Copy Markdown
Member

la14-1 commented May 2, 2026

Pushed a gate in commit 855a89e to turn the silent redact-and-push into a two-pass flow:

First pass (ALLOW_REDACT=0): VM stages + scans. If hits found, writes {"ok":false,"needsConfirmation":true,"hits":[...]} and exits 0 before any commit or push.

Host: reads the result, prints the file list, notes the regex has known gaps (#3381), and asks:

Redact these N files and continue pushing to GitHub? (initialValue: false)

  • Declineexit 0, nothing pushed.
  • Approve → re-run with ALLOW_REDACT=1, which does the sed + re-stage + commit + push, and returns the redacted list in the success result.

No-hits path is unchanged: single pass, single push.

Diff

  • packages/cli/src/commands/export.ts (+161 / -41): ResultSchema gains a needs_confirmation variant; buildExportScript takes allowRedact: boolean; cmdExport factors the run+download+parse cycle into runPassAndParseResult so two-pass orchestration is readable.
  • packages/cli/src/__tests__/export.test.ts (+147 / -2): 4 new tests — two scripting assertions (ALLOW_REDACT=0 writes needs_confirmation and exits 0; ALLOW_REDACT=1 redacts) and three end-to-end flows (approve → two passes 0→1; decline → one pass, exit 0; no-secrets → one pass, no confirm).
  • CLI 1.0.34 → 1.0.35.

Verification

  • bunx @biomejs/biome check src/ clean
  • bun test → 2176/0 fail (38/38 export tests, up from 34)
  • bash -n on both rendered script variants → both parse

Ready for another look / merge.

Copy link
Copy Markdown
Member

@la14-1 la14-1 left a comment

Choose a reason for hiding this comment

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

Gate wired up in 855a89e. First pass scans + pauses on hits; host prompts with the file list; only on approval does the redact+push run. Tests cover all four flows (approve / decline / no-secrets / script variants). All CI green. Approving.

@la14-1 la14-1 merged commit 3152a19 into OpenRouterTeam:main May 2, 2026
5 checks passed
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.

3 participants