File size: 1,889 Bytes
93c7565 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
// Patterns for common secrets
const secretPatterns = [
/nvapi-[a-zA-Z0-9_-]{40,}/, // NVIDIA API keys
/sk-[a-zA-Z0-9_-]{40,}/, // OpenAI keys
/hf_[a-zA-Z0-9_-]{40,}/, // Hugging Face tokens
/[a-zA-Z0-9_-]{32,}@github/, // GitHub tokens (basic)
/xoxb-[0-9]+-[0-9]+-[a-zA-Z0-9_-]+/, // Slack tokens
/[a-zA-Z0-9_-]{64}/, // Generic long keys (adjust as needed)
];
// Files to skip (contain legitimate hashes)
const skipFiles = ['package-lock.json', 'yarn.lock', 'node_modules/**', 'demo/audit-realT.md', 'fetcher-audit.md', 'phase-4-gateway-quorum-summary.md', 'prover/scorer.js', 'docs/calibration-report.md', 'test/calibrate-prior.js', 'test/recalibrate-thresholds.js', 'test/calibration-data.json', 'test/automate-calibration.sh', 'test/calibration-runs/**', 'test/diagnose-cid.js'];
// Get staged files
try {
const output = execSync('git diff --cached --name-only', { encoding: 'utf8' });
const files = output.trim().split('\n').filter(f => f);
for (const file of files) {
if (!fs.existsSync(file)) continue;
if (skipFiles.some(skip => file.includes(skip))) continue;
const content = fs.readFileSync(file, 'utf8');
for (const pattern of secretPatterns) {
if (pattern.test(content)) {
// Allow known placeholders
if (content.includes('your-key-here') || content.includes('REMOVED_KEY')) continue;
console.error(`❌ Potential secret detected in ${file} matching pattern: ${pattern}`);
console.error('Commit blocked. Remove the secret or use environment variables.');
process.exit(1);
}
}
}
console.log('✅ No secrets detected in staged files.');
} catch (error) {
console.error('Error checking for secrets:', error.message);
process.exit(1);
} |