Writing rules
Rules live in TOML. Built-ins are in src/secretsweep/builtin_rules.toml; yours go in <repo>/.secretsweep.toml (auto-loaded) or any file passed with --rules. A user rule whose id matches a built-in replaces it; new ids are added. disabled_rules = ["id", ...] at the top level removes rules.
disabled_rules = ["jwt"]
[[rules]]
id = "acme-api-key"
description = "ACME Corp API key"
regex = '''\b(acme_[a-z0-9]{32})\b'''
keywords = ["acme_"]
severity = "high"
confidence = "high"
entropy = 3.2
allowlist = ['''(?i)example''']
rotate = "https://acme.example/settings/keys"
Use TOML literal strings ('''...''') so backslashes need no escaping.
| Field | Required | Meaning |
|---|---|---|
id |
yes | Unique kebab-case id; appears in reports, SARIF and baselines |
regex |
yes | Python regex, applied to the whole text (multi-line capable) |
description |
no | Human text for reports |
keywords |
no | Lowercase substrings; if none occur in the file the rule is skipped. This is the main performance lever, so always set it for prefixed formats |
severity |
no | low, medium (default), high, critical |
confidence |
no | Base confidence when no validator speaks: low, medium (default), high |
secret_group |
no | Group holding the secret (default: group 1 if any, else the whole match). Fingerprints, redaction and entropy use this group |
entropy |
no | Minimum Shannon entropy of the secret; weeds out placeholders like aaaaaaaa |
allowlist |
no | Regexes searched in the secret; a hit drops the finding |
path_regex |
no | Rule only runs on paths matching this regex (relative POSIX path; archive members are archive.zip!member) |
validator |
no | github_checksum, jwt, pem, base64_userpass. valid raises confidence to high, invalid lowers it to low |
pairs_with |
no | Rule id; when both rules fire in the same file both become high confidence (used for the AWS key id and secret) |
verifier |
no | github or slack; makes the rule eligible for --verify |
rotate |
no | URL or hint printed by rewrite-guide |
Process
- Pick a distinctive prefix or context phrase and put it in
keywords. - Capture only the secret in a group, with
\bor a negative lookahead to avoid matching a longer string. - Add
entropyfor random-looking secrets, anallowlistfor placeholders. - Test it:
secretsweep rules list --rules my.tomlvalidates the file (bad regexes, unknown validators and severities are errors with exit code 2), then scan a file containing a fake value.
Contributing a built-in rule
Add the rule to builtin_rules.toml and a (path, positive, negative) entry keyed by its id to tests/fakes.py. tests/test_rules.py fails if any rule lacks fixtures, and each positive must fire while the negative (a near miss such as a wrong length or a test-mode prefix) must not. Fixtures must be generated, well-formed but invalid values.