Docs

Secret scanner

The scanner runs before every torii save. It is not a hook you install, not a CI job that tells you an hour later, and not something you can forget to enable on a new machine.

staged files the index scanner AKIA… ghp_… glpat- sk_live PEM blocks · JWTs user:pass@host + .toriignore [secrets] *.example · *.sample · *.template skip the gate commit written object enters history commit aborted file and line printed override with --yes torii scan --history runs the same patterns over every commit already written torii history replace-text --redact-secrets rewrites what it finds

What it matches

FamilyShapesExample prefix
AWSaccess keys, session keys, role idsAKIA… ASIA… AROA…
GitHubpersonal, OAuth, server, fine-grainedghp_ gho_ ghs_ github_pat_
GitLabpersonal and trigger tokensglpat- glptt-
Payments and mailStripe live keys, SendGrid, Twilio, Brevosk_live_ SG.
Bare bearersa literal header value with no vendor prefixBearer …
Private keysPEM blocks, SSH private keys-----BEGIN … PRIVATE KEY-----
Connection stringsuserinfo carrying a real user:password@postgres:// postgresql:// mysql:// mongodb:// mongodb+srv://
Generichigh entropy next to a name that means secretTOKEN SECRET API_KEY PASSWORD

Files named *.example, *.sample or *.template are always skipped.

Detection matches the shape a key actually appears in, not only a token standing alone as a word. KEY=ghp_… with no spaces around it — the shape every .env file and every -e KEY=value container argument uses — is the case that slipped through before 0.13.0, and the case the current patterns were rewritten around.

Scanning what is already committed

torii scan                # staged files
torii scan --history      # every commit, from the root

If --history finds something, the key is already public. Rotate it first, then clean the history:

torii history replace-text --redact-secrets

False positives

Only syntactic placeholders are excluded — ${VAR}, $VAR, <placeholder>. Word-shaped ones like password or changeme are not, because a real weak password collides with them. So a documentation example containing user:pass@localhost will be flagged.

SituationWhat to do
A one-off, and the finding is not realtorii save -am "msg" --yes
A file that will keep tripping itan allow: entry under [secrets] in .toriignore
One line, vetted// torii:allow-secret on that line
CI, or any run without a terminal--yes is required: the scanner cannot prompt and refuses to hang

Your own patterns

torii ignore secret 'PROP_[a-z]{20}' --name internal     # lands in .toriignore.local
torii ignore secret 'AKIA[0-9A-Z]{16}' --public          # lands in .toriignore, with a warning
torii ignore list                                         # the effective, merged rules

.toriignore.local is machine-private and gitignored automatically. It is where a pattern belongs when the pattern itself is a hint: a proprietary key format, an internal path, an audit regex. Publishing the regex that matches your internal tokens tells an attacker what to look for.