ranwhat clean

Your agent read your .env. The output is still on disk.

When an agent runs cat .env, the result is written into its transcript in plaintext: your database password, your signing secrets, your provider tokens, sitting in files that are never rotated and get read again by agents later.

$ ranwhat clean
Install
01 / The point

Redaction is not remediation.

Masking a value here does not un-expose it. It was already written to disk and already sat in a model context you do not control.

So the report leads with what to rotate and where, and treats masking as the secondary act. A tool that printed “cleaned: 47 secrets” and left you feeling safer would be actively harmful.

ranwhat cleandry run
47 distinct secret(s) in 312 place(s)

These must be rotated.
They have been written to disk in plaintext and sat in a
model context you do not control. Masking them here stops
them leaking again. It does not make them safe.

* AWS access key ID        AKI…AA   20 chars, seen 8x
* DATABASE_URL             pos…pp   42 chars, seen 8x
* PUSHER_APP_SECRET        b99…0a   64 chars, seen 2x

Dry run. Nothing was changed.
02 / Review

The session stays open.

Scanning a real history takes a while and the findings are already in memory. Re-running the whole scan to act on what you just read wastes that.

ranwhat> list           the findings again
ranwhat> show 3         where it appears, and what to roll it at
ranwhat> mask 3         mask just that one
ranwhat> mask all       mask everything listed
ranwhat> keep 3         leave it alone
ranwhat> rotate         grouped by provider

rotate names the place to roll each one, whether that’s the IAM console, Stripe’s API keys page or BotFather, rather than leaving you to work out where a 64-character string came from.

03 / Restraint

A secret is a literal, not code that mentions one.

Run against a machine that does real work, the first build reported 185 secrets and roughly two thirds were not credentials at all.

ReportedWhat it actually is
process.env.DB_PASSWORDa reference to a secret, not its value
crypto.randomBytes(32)a call that produces one
[A-Z]{20}a regex that matches one
${env}-session-ida template literal
/Users/you/projecta path assigned to PWD
your-api-key-herea placeholder

A value now has to be a literal: no code syntax, no environment reference, not a path, not a regex, not already masked. What survives must clear three bits per character of Shannon entropy unless it matches a known credential shape. Generated secrets sit well above that line; words and code sit below.

Measured 15 of 18 false positives before, 0 after, with all eight genuine credentials still found.
Safety Reports by default. --apply writes a timestamped backup first, then parses the rewritten file back before replacing the original.
Scope Masking one finding rewrites only that value, not every other secret in the same file.