Skip to content

Detection Rules

sensitive-canary scans text against the following rules. Patterns are sourced from gitleaks and TruffleHog detector definitions.

Secrets

Cloud

Rule IDDescriptionPattern
aws-access-keyAWS Access Key IDAKIA, ASIA, AGPA, AIDA, AROA, … + 16 uppercase alphanumeric chars

Source Control

Rule IDDescription
github-patGitHub Personal Access Token (ghp_, gho_, ghu_, ghs_, ghr_ prefix)
github-fine-grainedGitHub Fine-Grained Token (github_pat_ prefix)
gitlab-patGitLab Personal Access Token (glpat- prefix)

AI Services

Rule IDDescription
openai-keyOpenAI API Key — legacy format (sk- + 48 chars)
openai-project-keyOpenAI Project API Key (sk-proj- prefix, entropy-filtered)
anthropic-keyAnthropic API Key (sk-ant- prefix)

Communication

Rule IDDescription
slack-tokenSlack Token (xoxb-, xoxa-, xoxp-, xoxr-, xoxs- prefix)
slack-webhookSlack Incoming Webhook URL
discord-webhookDiscord Webhook URL
telegram-bot-tokenTelegram Bot Token
twilio-sidTwilio Account SID

Payment

Rule IDDescription
stripe-secret-keyStripe Secret Key (sk_live_ / sk_test_ prefix)
stripe-restricted-keyStripe Restricted Key (rk_live_ / rk_test_ prefix)

Email Services

Rule IDDescription
sendgrid-keySendGrid API Key (SG. prefix)
mailgun-keyMailgun API Key (key- prefix)
mailchimp-keyMailchimp API Key (32-char hex + -usN suffix)

Auth

Rule IDDescription
jwtJSON Web Token (three Base64URL segments separated by .)
private-keyPEM Private Key header (-----BEGIN … PRIVATE KEY-----)
connection-stringDatabase connection string with embedded credentials

Generic / Env-based

Rule IDDescriptionEntropy threshold
generic-secretapi_key, secret_key, access_token, api_secret assignments3.5
env-assignment.env-style assignments for SECRET, PASSWORD, TOKEN, API_KEY, PRIVATE_KEY3.0

The entropy threshold filters out low-entropy values (e.g. API_KEY=placeholder) that are unlikely to be real secrets. Entropy is calculated using the Shannon entropy formula.

PII

Rule IDDescriptionNotes
pii-emailEmail AddressStandard RFC 5322-like pattern
pii-credit-cardCredit Card NumberVisa, Mastercard, Amex, Discover; validated with Luhn algorithm
pii-ssnUS Social Security NumberExcludes invalid area (000, 666, 9xx), group (00), and serial (0000) numbers
pii-phone-usUS Phone NumberWith or without country code
pii-phone-jpJapanese Phone NumberArea code + subscriber number format
pii-postal-jpJapanese Postal CodeRequires prefix to avoid false positives
pii-ipv4Private IPv4 AddressRFC 1918 ranges only: 10.x, 172.16–31.x, 192.168.x

Credit Card Validation

Credit card numbers are matched by pattern and validated using the Luhn algorithm. This means valid-looking but invalid card numbers (e.g. 4111111111111112) are not flagged.

Allow Tags

All blocks can be bypassed by including an allow tag in your prompt. Allow tags are read only from the current user message — they do not carry over between turns.

TagBypasses
[allow-secret]All findings with category: secret
[allow-pii]All findings with category: pii
[allow-all]All findings regardless of category

Tags are case-insensitive: [ALLOW-SECRET] and [Allow-Secret] work the same as [allow-secret].

Mask Tags

[mask-secret], [mask-pii], and [mask-all] are recognised but not supported. Claude Code hooks cannot rewrite prompt content before it is sent to the API.

If you include a mask tag in your prompt, sensitive-canary shows an explanation and suggests the equivalent allow tag instead. The prompt is not sent until you resend with an allow tag or redact the value manually.

Mask tagSuggested allow tag
[mask-secret][allow-secret]
[mask-pii][allow-pii]
[mask-all][allow-all]

Allow + Mask Tag Priority

When both [allow-*] and [mask-*] tags appear in the same prompt, the tag that appears first wins for each category dimension (secret, pii).

Examplesecretpii
[allow-secret] [mask-secret] …allow
[mask-secret] [allow-secret] …mask (unsupported)
[allow-all] [mask-secret] …allowallow
[mask-all] [allow-secret] …mask (unsupported)mask (unsupported)
[allow-secret] [mask-pii] …allowmask (unsupported)

[allow-all] and [mask-all] resolve both dimensions at once.

.env File Blocking

.env and .env.* files (e.g. .env.local, .env.production) are blocked unconditionally by filename when Claude attempts to read them, regardless of content.

Files that end in .env but don't start with a dot (e.g. production.env) are handled by content scanning rather than name-based blocking.

Any allow tag ([allow-secret], [allow-pii], or [allow-all]) bypasses the name-based block. When an allow tag is present, the file is passed through immediately without scanning its contents.

Bash Command Scanning

When Claude uses the Bash tool, sensitive-canary checks three things:

  1. Environment variables — any $VAR or ${VAR} references in the command are looked up in the current environment; if their values contain secrets or PII, the command is blocked.
  2. Command string — the raw command is scanned (catches inline secrets like echo AKIAIOSFODNN7EXAMPLE).
  3. File-reading commands — for cat, head, tail, less, more, bat, nl, the target files are read and scanned before the command runs. Compound commands using |, ;, &&, || are split and each segment is checked independently.

Released under the MIT License.