Skip to content

fix(EXPOSED_SECRETS): detect modern API key formats (OpenAI sk-proj/svcacct, Anthropic, GitHub, Google, Slack, Stripe)#29

Open
dmchaledev wants to merge 1 commit into
mainfrom
claude/amazing-franklin-36hvg5
Open

fix(EXPOSED_SECRETS): detect modern API key formats (OpenAI sk-proj/svcacct, Anthropic, GitHub, Google, Slack, Stripe)#29
dmchaledev wants to merge 1 commit into
mainfrom
claude/amazing-franklin-36hvg5

Conversation

@dmchaledev

Copy link
Copy Markdown
Contributor

Summary

The CRITICAL EXPOSED_SECRETS rule (src/rules/runtime-rules.ts) only matched legacy secret formats:

/sk-[a-zA-Z0-9]{20,}/i,           // OpenAI API key
/ghp_[a-zA-Z0-9]{36}/i,            // GitHub PAT
/AKIA[0-9A-Z]{16}/i,               // AWS access key
/[Pp]assword\s*[=:]\s*\S{8,}/,     // Password assignment

It silently missed the secret formats most commonly found in AI/MCP configs today — including the LLM provider keys an MCP server is most likely to carry. Verified against the current patterns:

Secret Before
Legacy OpenAI sk-… ✅ detected
OpenAI project sk-proj-… ❌ missed
OpenAI service-account sk-svcacct-… ❌ missed
Anthropic sk-ant-… ❌ missed
GitHub classic ghp_… ✅ detected
GitHub OAuth/app gho_/ghu_/ghs_/ghr_ ❌ missed
GitHub fine-grained github_pat_… ❌ missed
AWS AKIA… ✅ detected
Google AIza… ❌ missed
Slack xoxb-… ❌ missed
Stripe sk_live_… / rk_live_… ❌ missed

Root cause for the OpenAI miss: modern keys (sk-proj-, sk-svcacct-, sk-ant-) contain hyphens/underscores, and the old [a-zA-Z0-9]-only run stops at the first -, so the {20,} length is never reached.

For a scanner whose CRITICAL rule is "Potential Secret Exposed in Configuration", missing current provider key formats is a meaningful false negative — and especially relevant for an AI/MCP scanner, since sk-proj-/sk-ant- keys are exactly what these servers tend to hold.

Changes

  • Broaden SECRET_PATTERNS to cover modern OpenAI (project/service-account/admin), Anthropic, the full GitHub token family + fine-grained PATs, Google API keys, Slack tokens, and Stripe live/restricted keys. Legacy patterns are preserved.
  • Add EXPOSED_SECRETS tests (the rule previously had zero test coverage): one positive case per supported format, plus negatives for benign config strings and a JWT-style bearer token (the kind used in examples/secure-config.json) to guard against false positives.

Verification

  • npm run typecheck, npm run lint, npm test (113 passing) all green.
  • CLI smoke test: examples/secure-config.json still passes (no new false positives); a config carrying an sk-proj-… key now correctly fails with a CRITICAL EXPOSED_SECRETS finding.
  • Test fixtures are assembled from prefix + filler at runtime so no real-looking credential literal appears in source (keeps secret-scanning push protection happy).

Scope

Detection only. Redaction of matched secrets in finding evidence is tracked separately in #28, and the missed-password case in #14 — this PR is complementary and does not overlap with either.

🤖 Generated with Claude Code


Generated by Claude Code

…vcacct, Anthropic, GitHub, Google, Slack, Stripe)

The CRITICAL EXPOSED_SECRETS rule only matched legacy OpenAI keys
(sk-<alnum>), classic GitHub PATs (ghp_), and AWS access keys. It
silently missed the secret formats most commonly found in AI/MCP
configs today:

  - OpenAI project / service-account / admin keys (sk-proj-, sk-svcacct-,
    sk-admin-) — these contain hyphens/underscores, which the old
    alphanumeric-only pattern stopped on
  - Anthropic keys (sk-ant-)
  - GitHub OAuth / app / refresh tokens (gho_, ghu_, ghs_, ghr_) and
    fine-grained PATs (github_pat_)
  - Google API keys (AIza...)
  - Slack tokens (xox[baprs]-...)
  - Stripe live secret/restricted keys (sk_live_, rk_live_)

For a security scanner whose CRITICAL rule is "Potential Secret Exposed
in Configuration," missing current provider key formats is a meaningful
false negative.

Broaden SECRET_PATTERNS to cover these formats while keeping the legacy
patterns. Add EXPOSED_SECRETS tests (none existed): one positive case per
supported format, plus negative cases for benign strings and a JWT-style
bearer token to guard against false positives.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HiLyXzy6TuD5KXXHLGq3Pu
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants