| #!/usr/bin/env node |
|
|
| const fs = require('fs'); |
| const path = require('path'); |
| const { execSync } = require('child_process'); |
|
|
| |
| const secretPatterns = [ |
| /nvapi-[a-zA-Z0-9_-]{40,}/, |
| /sk-[a-zA-Z0-9_-]{40,}/, |
| /hf_[a-zA-Z0-9_-]{40,}/, |
| /[a-zA-Z0-9_-]{32,}@github/, |
| /xoxb-[0-9]+-[0-9]+-[a-zA-Z0-9_-]+/, |
| /[a-zA-Z0-9_-]{64}/, |
| ]; |
|
|
| |
| 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']; |
|
|
| |
| 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)) { |
| |
| 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); |
| } |