import type { SecretPattern, Finding, ScanResult } from '../types.js'; // Compiled at module load for performance (<20ms detection) export const SECRET_PATTERNS: SecretPattern[] = [ { name: 'OpenAI API Key', pattern: /sk-[a-zA-Z0-9]{20,}/, severity: 'critical' }, { name: 'GitHub PAT', pattern: /ghp_[a-zA-Z0-9]{36}/, severity: 'critical' }, { name: 'GitHub OAuth', pattern: /gho_[a-zA-Z0-9]{36}/, severity: 'critical' }, { name: 'GitHub App Token', pattern: /ghu_[a-zA-Z0-9]{36}/, severity: 'critical' }, { name: 'AWS Access Key', pattern: /AKIA[0-9A-Z]{16}/, severity: 'critical' }, { name: 'AWS Secret Key', pattern: /(?:aws_secret_access_key|AWS_SECRET)\s*[=:]\s*[A-Za-z0-9\/+=]{40}/, severity: 'critical', }, { name: 'Slack Token', pattern: /xox[baprs]-[0-9a-zA-Z-]{10,}/, severity: 'critical' }, { name: 'Slack Webhook', pattern: /https:\/\/hooks\.slack\.com\/services\/T[A-Z0-9]+\/B[A-Z0-9]+\/[a-zA-Z0-9]+/, severity: 'high', }, { name: 'JWT', pattern: /eyJ[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}/, severity: 'high', }, { name: 'Private Key', pattern: /-----BEGIN\s+(RSA|EC|OPENSSH|PGP|DSA)\s+PRIVATE\s+KEY-----/, severity: 'critical', }, { name: 'Generic API Key', pattern: /(?:api[_-]?key|api[_-]?secret|access[_-]?token)\s*[=:]\s*['"][a-zA-Z0-9]{16,}['"]/, severity: 'high', }, { name: 'Anthropic API Key', pattern: /sk-ant-[a-zA-Z0-9-]{20,}/, severity: 'critical' }, { name: 'Google API Key', pattern: /AIza[0-9A-Za-z_-]{35}/, severity: 'critical' }, { name: 'Stripe Key', pattern: /[sr]k_(live|test)_[a-zA-Z0-9]{20,}/, severity: 'critical' }, { name: 'Telegram Bot Token', pattern: /[0-9]+:AA[a-zA-Z0-9_-]{33}/, severity: 'critical' }, { name: 'Discord Bot Token', pattern: /[MN][A-Za-z\d]{23,}\.[\w-]{6}\.[\w-]{27,}/, severity: 'critical', }, { name: 'Vercel Token', pattern: /vcp_[a-zA-Z0-9]{50,}/, severity: 'critical' }, { name: 'npm Token', pattern: /npm_[a-zA-Z0-9]{36}/, severity: 'critical' }, { name: 'Twilio', pattern: /SK[a-fA-F0-9]{32}/, severity: 'critical' }, { name: 'SendGrid', pattern: /SG\.[a-zA-Z0-9_-]{22}\.[a-zA-Z0-9_-]{43}/, severity: 'critical', }, { name: 'Heroku API Key', pattern: /[hH]eroku.*[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}/, severity: 'critical', }, ]; export function scanForSecrets(text: string): ScanResult { const findings: Finding[] = []; for (const p of SECRET_PATTERNS) { const match = p.pattern.exec(text); if (match) { findings.push({ rule: p.name, hook: 'secrets-scanner', severity: p.severity ?? 'high', matched: match[0].slice(0, 20) + (match[0].length > 20 ? '...' : ''), }); } } return { matched: findings.length > 0, findings }; }