grithdocs

7. Secret / credential scanning

1,620+ regex patterns over outbound content. The credential leak filter.

PhasePattern
Score range+3 to +5
Modulecrates/grith-proxy/src/filters/secret_scan.rs
Config fileconfig/filters/secrets.toml

The big one. Sixteen hundred-odd compiled regexes scan outbound content for credential shapes — API keys, tokens, private keys, JWTs, anything that looks like "this is the kind of thing you don't want to send out by accident".

What it catches

The pattern set is sourced from a curated upstream (similar in shape to gitleaks / trufflehog rule sets, but tuned for the false-positive characteristics of an agent workload). Categories:

  • Cloud providers — AWS, Azure, GCP, Vercel, Cloudflare, Heroku, …
  • CI/CD — GitHub, GitLab, CircleCI, BuildKite tokens.
  • SaaS APIs — Stripe, Slack, Twilio, SendGrid, Linear, Notion.
  • Databases — MongoDB connection strings, Postgres URIs with passwords, Redis URLs with auth.
  • Generic credential shapes — RSA/Ed25519 private key headers, JWTs, basic-auth URLs, S3 presigned URLs.
  • Cryptocurrency — wallet seeds, private keys (because exfil patterns are similar).

Each pattern has:

  • A score contribution (+3.0 to +5.0 based on confidence).
  • A label that surfaces in the audit log (e.g. aws_secret_access_key, slack_xoxb).
  • An optional entropy floor — high-entropy detection to reduce false positives on generic-looking shapes.

When it fires

The scanner runs when a call carries content that could leave the box:

  • Network sends (sendto, send, sendmsg, write to a socket fd).
  • Shell command args (the args might be smuggling credentials).
  • File writes where the destination is outside the session's containment zone.

It does not run on reads. A file_read of a .env is caught by sensitive-path-heuristic / path-match, not secret-scan - there's nothing to scan yet at read time. Once that data flows to a sink, secret-scan catches the content if it goes outbound.

Performance

The scanner compiles the rule set into a single regex automaton at start (regex::RegexSet). Matching is linear in the content length, regardless of the number of patterns. For typical syscall content (a few KB), the scan is in the ~0.5-2ms range. There is no scan-length cap: large outbound payloads are scanned in full, so scan cost grows with payload size.

Tuning

Most users never need to touch this filter - the defaults are tuned for low false positives. The pattern set lives in config/filters/secrets.toml; the daemon loads a copy from its working directory if one exists, otherwise the defaults embedded in the binary. Reasons you might edit it:

  • A pattern fires on legitimate content - remove that [[patterns]] entry (or lower its score) in your copy of secrets.toml.

  • Your team uses an internal credential format - add a pattern:

    [[patterns]]
    id = "acme-internal"
    regex = "ACME-[A-Z0-9]{32}"
    score = 4.0
    severity = "critical"
    message = "ACME internal credential detected"

See also

Last updated: 2026-05-14Edit this page on GitHub →