fix: detect Anthropic API keys (sk-ant-...) in pre-commit secret scan (#2529)

The existing OpenAI pattern sk-[a-zA-Z0-9]{20,} never matches real
Anthropic keys: their sk-ant-api03-... format contains hyphens, which
break the character class before reaching the 20-char threshold. Keys
from the fastest-growing Claude Code user base slipped through the scan.

Adds a dedicated sk-ant-[a-zA-Z0-9_-]{20,} pattern (checked before the
OpenAI one) and extends the staged-secrets test with a realistic
Anthropic key fixture.
This commit is contained in:
KH 2026-07-22 18:17:28 +02:00 committed by GitHub
parent a1bf029cbf
commit 8348fb5387
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 3 additions and 0 deletions

View file

@ -108,6 +108,7 @@ function findFileIssues(filePath) {
// Check for hardcoded secrets (basic patterns) // Check for hardcoded secrets (basic patterns)
const secretPatterns = [ const secretPatterns = [
{ pattern: /sk-ant-[a-zA-Z0-9_-]{20,}/, name: 'Anthropic API key' },
{ pattern: /sk-[a-zA-Z0-9]{20,}/, name: 'OpenAI API key' }, { pattern: /sk-[a-zA-Z0-9]{20,}/, name: 'OpenAI API key' },
{ pattern: /ghp_[a-zA-Z0-9]{36}/, name: 'GitHub PAT' }, { pattern: /ghp_[a-zA-Z0-9]{36}/, name: 'GitHub PAT' },
{ pattern: /AKIA[A-Z0-9]{16}/, name: 'AWS Access Key' }, { pattern: /AKIA[A-Z0-9]{16}/, name: 'AWS Access Key' },

View file

@ -212,6 +212,7 @@ if (test('blocks commits with staged secret patterns across checkable files', ()
inTempRepo(repoDir => { inTempRepo(repoDir => {
writeAndStage(repoDir, 'index.js', [ writeAndStage(repoDir, 'index.js', [
"const openai = 'sk-abcdefghijklmnopqrstuvwxyz';", "const openai = 'sk-abcdefghijklmnopqrstuvwxyz';",
"const anthropic = 'sk-ant-api03-AbCdEf-GhIjKlMnOpQrStUvWx_Yz012345';",
"const token = 'ghp_abcdefghijklmnopqrstuvwxyzABCDEFGHIJ';", "const token = 'ghp_abcdefghijklmnopqrstuvwxyzABCDEFGHIJ';",
'' ''
].join('\n')); ].join('\n'));
@ -227,6 +228,7 @@ if (test('blocks commits with staged secret patterns across checkable files', ()
assert.strictEqual(result.output, input); assert.strictEqual(result.output, input);
assert.strictEqual(result.exitCode, 2); assert.strictEqual(result.exitCode, 2);
assert.ok(stderr.includes('Potential OpenAI API key'), `expected OpenAI secret warning, got: ${stderr}`); assert.ok(stderr.includes('Potential OpenAI API key'), `expected OpenAI secret warning, got: ${stderr}`);
assert.ok(stderr.includes('Potential Anthropic API key'), `expected Anthropic key warning, got: ${stderr}`);
assert.ok(stderr.includes('Potential GitHub PAT'), `expected GitHub PAT warning, got: ${stderr}`); assert.ok(stderr.includes('Potential GitHub PAT'), `expected GitHub PAT warning, got: ${stderr}`);
assert.ok(stderr.includes('Potential AWS Access Key'), `expected AWS key warning, got: ${stderr}`); assert.ok(stderr.includes('Potential AWS Access Key'), `expected AWS key warning, got: ${stderr}`);
assert.ok(stderr.includes('Potential API key'), `expected generic API key warning, got: ${stderr}`); assert.ok(stderr.includes('Potential API key'), `expected generic API key warning, got: ${stderr}`);