content-embedded-secrets¶
Detect potential API keys, tokens, and passwords in instruction files
| Severity | error (auto) |
| Autofix | - |
| Since | v0.7.0 |
| Category | Content Intelligence |
Why¶
Instruction files are checked into version control and often read by multiple agents and users. A hardcoded API key, token, or password in an instruction file is a credential leak — it is visible in the git history even after removal and may be harvested by automated scanners.
Detection¶
Two classes of match are handled differently:
- Structured token formats (
AKIA…,ghp_…,sk-ant-…, private-key blocks, JWTs, …) are high-confidence and scanned everywhere in the file, fenced code included. They are reported unless the complete candidate is an exact, audited documentation literal (the canonical AWS documentation access-key ID, the jwt.io example token), or the value contains a run of one repeated character —ghp_xxxxxxxx…is the documentation idiom for a token, and no real token has that shape. A PEM header is documentation until key material follows it:-----BEGIN OPENSSH PRIVATE KEY-----in a list of patterns to detect is fine; the same header with base64 lines after it still reports. The context scan is bounded by physical lines and characters so hostile files cannot force unbounded repeated work. - Generic credential assignments (
password = "…",api_key: "…",secret_key,access_token) are scanned in prose only — apassword: "SecurePass123!"inside a fenced code block is a teaching example — and are gated to avoid flagging documentation examples:- Placeholder allowlist: values containing obvious substring markers
(
example,placeholder,dummy,changeme,your-…, …), template syntax (<your-key>,${VAR},$(cmd),{{ var }}), or a single repeated character are skipped. Extend the substring list withadditional-placeholders. - Audited examples: exact values (
hunter2,sk_live_abc123xyz789,sk_live_abc123def456, and the literal three-dot valuedjango-insecure-...) are skipped after trimming surrounding whitespace and comparing case-insensitively. Close variants remain reportable. - Entropy gating: the value's Shannon entropy must reach
entropy-threshold(default 3.5 bits/char). Real random secrets pass; English-ish placeholder strings do not. Values shorter than 16 characters are length-normalized before comparison (per-char Shannon entropy of an n-char string is capped at log2(n), so a fully random 10-char password measures only ~3.3 bits/char raw — short random passwords still fire).
- Placeholder allowlist: values containing obvious substring markers
(
Examples¶
Bad:
Good:
Set the API key via the `OPENAI_API_KEY` environment variable.
Store secrets in `.env` (gitignored) — never inline them in instruction
files.
How to fix¶
Replace the hardcoded secret with an environment variable reference
(e.g., $API_KEY) or a note directing the reader to a secure storage
mechanism. Rotate the exposed credential immediately — removing it from
the file does not remove it from git history. A coding agent can
redact detected secrets automatically.
Configuration¶
| Parameter | Description | Default |
|---|---|---|
entropy-threshold |
Minimum Shannon entropy (bits/char) a generic key = "value" match must reach to be reported; structured tokens (AKIA…, ghp_…, private keys) remain reportable except for exact audited documentation literals | 3.5 |
additional-placeholders |
Extra case-insensitive substrings that mark a generic credential value as a placeholder (suppressing the violation) | [] |
Research Basis¶
Detects potential API keys, tokens, and passwords in instruction files.
CLAUDE.md files are loaded into context every session. A hardcoded API key in an instruction file is exposed to every conversation, every collaborator, and potentially every model provider's logging infrastructure. This is CWE-798 (Use of Hard-coded Credentials), mapping to OWASP Top Ten 2021 A07.
References:
- CWE-798: Use of Hard-coded Credentials — Authoritative weakness enumeration
- OWASP Secrets Management Cheat Sheet
- Claude Code Security — Instruction files are loaded into context every session
Run skillsaw explain content-embedded-secrets to see this documentation and the rule's effective configuration in your terminal.