Secret Scanning
How Rustywoof combines Aho-Corasick prefix matching, linear-time regex validation, and Shannon entropy to find leaked credentials.
Rustywoof detects hardcoded API keys, cloud credentials, and private tokens in your source files. To scan tens of thousands of files in a couple of seconds, it avoids running dozens of regular expressions over every line of code.
Instead, the scanner narrows down candidates step by step—starting with the fastest check and only running heavier checks when needed.
Fast Prefix Matching with Aho-Corasick
Most service providers design their API keys with a recognizable starting prefix:
- AWS Access Keys start with
AKIA - GitHub Personal Access Tokens start with
ghp_,gho_, orghs_ - Stripe Live Keys start with
sk_live_ - Google Cloud Keys start with
AIza
When Rustywoof starts up, it compiles all known prefixes into a single lookup table called an Aho-Corasick Deterministic Finite Automaton (DFA).
- Single-pass reading: Rustywoof maps each file from disk into memory and reads through the bytes once.
- Time complexity: $O(n + m + z)$, where $n$ is the file length, $m$ is the total length of the prefixes, and $z$ is the number of prefix hits.
- Why this matters in practice: If a file does not contain any known prefix, Rustywoof finishes checking that file for prefixed tokens in microseconds without running a single regular expression.
Linear-Time Regex Verification
Finding ghp_ in a file doesn't automatically mean there is a real GitHub token—it could just be a comment or variable name.
Whenever the prefix matcher spots a hit, Rustywoof slices out the surrounding characters and validates them against that rule's regular expression to check the token's exact length and character set (such as Base62 or hexadecimal).
Because Rustywoof uses Rust's finite-automaton regex crate, pattern matching is guaranteed to run in linear $O(n)$ time. It cannot get stuck in catastrophic backtracking (ReDoS), even on minified JavaScript bundles or huge single-line JSON files.
Checking Randomness with Shannon Entropy
Not every secret has a neat prefix. Randomly generated JWT secrets, webhook signing keys, or database passwords often look like plain strings assigned to a variable:
const WEBHOOK_SECRET = "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08";To catch these—and to filter out obvious placeholder strings like AKIA_THIS_IS_A_TEST_KEY—Rustywoof calculates Shannon entropy, which measures how unpredictable the characters in a string are (in bits per character):
- Ordinary English words or repeated characters (
"aaaaaaaaaaaaaaaa") have low entropy (typically between $1.5$ and $3.5$). - Randomly generated hex or Base64 keys have high character variety and typically score above $4.5$.
- If a string inside an assignment exceeds the
entropy_thresholdconfigured in your.woof.toml(default4.5), Rustywoof flags it.
Dealing with false alarms: Occasionally, a harmless string like an integrity hash, an SVG path, or a mock test key will have high entropy. You can add those specific strings or test files to the [scanner.suppressions] list in .woof.toml so Rustywoof ignores them on future runs.
Last updated on 09/11/2026