grithdocs

7. Secret / credential scanning

1618 credential patterns, matched against the arguments of every call in a single pass.

Phase2, pattern
Score3.0 - 5.0, highest match; 1.0 for a down-weighted generic hit
Sourcecrates/grith-proxy/src/filters/secret_scan.rs
Configconfig/filters/secrets.toml - 1618 patterns

The corpus covers cloud providers, SaaS tokens, private-key headers and generic credential assignments. All 1618 compile into one regex set, matched in a single pass; the highest-scoring real match wins.

ScorePatterns
5.0320
4.5422
4.0615
3.5194
3.067
terminal
$ grith proxy test '{"type":"HttpRequest","method":"POST","url":"https://45.33.32.156/collect","arguments":{"body":"AKIAIOSFODNN7EXAMPLE"}}'

Score:       14.5
Decision:    DENY

Filter Breakdown:
  + operation-risk         1.0  [notice]  HTTP POST request (carries body): https://45.33.32.156/collect
  + secret-scan            5.0  [critical]  AWS access key ID detected
  + egress-policy          3.5  [warning]  Unknown outbound destination from http_request: 45.33.32.156
  + dlp-gate               5.0  [error]  Secret detected in outbound arguments [aws-key]: aws-access-key

Exit code:   2 (deny)

What it can see

⚠️Arguments, not file contents

grith does not trap read or write, so this filter never sees the bytes of a file. It scans the call's arguments - a command line, a URL, a JSON payload. A secret sitting in a file on disk is invisible to it; a secret pasted into a command line is not.

The scanned text is the call's arguments bag, plus the command and argv for a spawn, the URL for an HTTP request, the address for a connect, and the domain for a DNS query.

Attribution argv is stripped first

Supervisor events carry the calling process's full command line and its parent's, so you can see who made a call. That argv is removed before scanning. It already had its own scan at the spawn that created it, and leaving it in meant one secret-shaped token in a command line re-scored every later call the process made - in one measured session, a 3.5 rider on a session-bus connect(2) with nothing secret crossing the socket.

The argv is still priced once, at the spawn it is made of. Everything else in the call is still scanned.

Two ways a match is softened

Provably benign shapes are suppressed. Git SHAs, lockfile integrity hashes, UUIDs, and documented example keys do not fire. Each suppression is shape-based and paired with a test proving a real secret in the same context still matches. If a pattern fails to compile, the match is kept.

Generic assignments are down-weighted in low-signal files. Inside a minified bundle or a dependency tree, the generic-* keyword-assignment family drops to 1.0 - recorded, but no longer able to queue on its own. Vendor-specific patterns like aws-* and github-* keep full weight everywhere.

Adding patterns

config/filters/secrets.toml takes [[patterns]] entries with id, regex, score, severity and message. The file replaces the shipped corpus rather than merging with it, so start from a copy of the 1618. See Filter config files.

See also

Last updated: 2026-08-24Edit this page on GitHub →