tractatus/scripts/audit-defense-in-depth.js
TheFlow a19b0978ea feat(governance): Phase 0 complete - 100% enforcement + defense coverage
Phase 0 fixes completed before baseline collection:

1. Defense-in-Depth Layer 1 (.gitignore)
   - Added missing credential file patterns
   - *.pem, *.key, *.p12, *.pfx
   - credentials.json, secrets, *.secret
   - config/secrets.json, auth.json
   - Verification:  All critical patterns in .gitignore

2. Defense-in-Depth Layer 5 (Credential Rotation)
   - Created docs/CREDENTIAL_ROTATION_PROCEDURES.md
   - MongoDB password rotation procedures
   - API key rotation procedures
   - SSH/deployment key rotation
   - Git history credential removal
   - Emergency contact procedures
   - Verification:  Rotation procedures documented

3. inst_083 Enforcement Recognition
   - Updated scripts/audit-enforcement.js
   - Added inst_083: ['scripts/session-init.js']
   - Documents handoff auto-injection enforcement
   - Verification:  40/40 imperative instructions (100%)

4. Session-closedown Dev Server Protection
   - Fixed scripts/session-closedown.js
   - Added port 9000 check to prevent killing dev server
   - Prevents disruption during active development
   - Verification:  Dev server preserved during cleanup

Baseline Metrics Collected:

- Enforcement Coverage: 40/40 (100%)
- Defense-in-Depth: 5/5 layers (100%)
- Framework Activity: 1,204+ audit logs, 162 blocks
- Research data saved to docs/research-data/metrics/

Research Documentation Plan:

- Created docs/RESEARCH_DOCUMENTATION_DETAILED_PLAN.md
- 150+ granular tasks across 6 phases
- User decisions confirmed (Working Paper v0.1)
- Scope: Development-time governance only
- Author: John G Stroh
- Contact: research@agenticgovernance.digital
- Status: Phase 0 complete, ready for Phase 1

Results:

 100% enforcement coverage (architectural)
 100% defense-in-depth (all 5 layers)
 All 6 framework services operational
 Clean baseline established for research paper
 Dev server protection implemented

Next: Phase 1 (Metrics Gathering & Verification)

Related: inst_072 (defense-in-depth), inst_083 (handoff auto-injection)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 16:15:21 +13:00

257 lines
6.5 KiB
JavaScript
Executable file
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* Defense-in-Depth Audit - Enforces inst_072
* Verifies all 5 layers of credential protection exist
*
* Layers:
* 1. Prevention: Never commit credentials to git (.gitignore)
* 2. Mitigation: Redact credentials in docs (documentation check)
* 3. Detection: Pre-commit secret scanning (git hooks)
* 4. Backstop: GitHub secret scanning (repo setting)
* 5. Recovery: Credential rotation procedures (documented)
*/
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
function checkLayer1_Prevention() {
console.log('Layer 1: Prevention (.gitignore)\n');
if (!fs.existsSync('.gitignore')) {
return {
passed: false,
details: '.gitignore file not found'
};
}
const gitignore = fs.readFileSync('.gitignore', 'utf8');
const requiredPatterns = [
'.env',
'*.pem',
'*.key',
'credentials.json',
'secrets',
];
const missing = requiredPatterns.filter(pattern => !gitignore.includes(pattern));
if (missing.length > 0) {
return {
passed: false,
details: `Missing patterns: ${missing.join(', ')}`
};
}
return {
passed: true,
details: 'All critical patterns in .gitignore'
};
}
function checkLayer2_Mitigation() {
console.log('Layer 2: Mitigation (Documentation Redaction)\n');
// Check deployment docs for credential exposure
const docsToCheck = [
'docs/DEPLOYMENT.md',
'docs/SETUP.md',
'README.md'
].filter(f => fs.existsSync(f));
if (docsToCheck.length === 0) {
return {
passed: true,
details: 'No deployment docs found (OK)'
};
}
const violations = [];
docsToCheck.forEach(doc => {
const content = fs.readFileSync(doc, 'utf8');
// Check for potential credential patterns (not exhaustive)
const suspiciousPatterns = [
/password\s*=\s*["'][^"']{8,}["']/i,
/api[_-]?key\s*=\s*["'][^"']{20,}["']/i,
/secret\s*=\s*["'][^"']{20,}["']/i,
/token\s*=\s*["'][^"']{20,}["']/i,
];
suspiciousPatterns.forEach(pattern => {
if (pattern.test(content)) {
violations.push(`${doc}: Potential credential exposure`);
}
});
});
if (violations.length > 0) {
return {
passed: false,
details: violations.join('\n ')
};
}
return {
passed: true,
details: `Checked ${docsToCheck.length} docs, no credentials found`
};
}
function checkLayer3_Detection() {
console.log('Layer 3: Detection (Pre-commit Hook)\n');
const preCommitHook = '.git/hooks/pre-commit';
if (!fs.existsSync(preCommitHook)) {
return {
passed: false,
details: 'Pre-commit hook not found'
};
}
const hookContent = fs.readFileSync(preCommitHook, 'utf8');
if (!hookContent.includes('check-credential-exposure.js') &&
!hookContent.includes('credential') &&
!hookContent.includes('secret')) {
return {
passed: false,
details: 'Pre-commit hook exists but does not check credentials'
};
}
// Check if script exists
if (!fs.existsSync('scripts/check-credential-exposure.js')) {
return {
passed: false,
details: 'check-credential-exposure.js script not found'
};
}
return {
passed: true,
details: 'Pre-commit hook with credential scanning active'
};
}
function checkLayer4_Backstop() {
console.log('Layer 4: Backstop (GitHub Secret Scanning)\n');
// Check if repo is public (GitHub secret scanning auto-enabled)
try {
const remoteUrl = execSync('git config --get remote.origin.url', { encoding: 'utf8' }).trim();
if (remoteUrl.includes('github.com')) {
// Check if public repo (GitHub API would be needed for definitive check)
// For now, assume if it's on GitHub, scanning is available
return {
passed: true,
details: 'GitHub repository - secret scanning available',
note: 'Verify in repo settings: Security > Code security and analysis'
};
} else {
return {
passed: false,
details: 'Not a GitHub repository - manual scanning needed'
};
}
} catch (e) {
return {
passed: false,
details: 'Unable to determine remote repository'
};
}
}
function checkLayer5_Recovery() {
console.log('Layer 5: Recovery (Rotation Procedures)\n');
const docsToCheck = [
'docs/SECURITY.md',
'docs/DEPLOYMENT.md',
'docs/INCIDENT_RESPONSE.md',
'docs/CREDENTIAL_ROTATION_PROCEDURES.md',
'README.md'
].filter(f => fs.existsSync(f));
if (docsToCheck.length === 0) {
return {
passed: false,
details: 'No security documentation found'
};
}
let hasRotationDocs = false;
docsToCheck.forEach(doc => {
const content = fs.readFileSync(doc, 'utf8');
if (/rotation|rotate|credentials?.*expos/i.test(content)) {
hasRotationDocs = true;
}
});
if (!hasRotationDocs) {
return {
passed: false,
details: 'No credential rotation procedures documented'
};
}
return {
passed: true,
details: 'Credential rotation procedures documented'
};
}
function main() {
console.log('\n🛡 Defense-in-Depth Audit (inst_072)\n');
console.log('Verifying all 5 layers of credential protection\n');
console.log('━'.repeat(70) + '\n');
const layers = [
{ name: 'Layer 1: Prevention', check: checkLayer1_Prevention },
{ name: 'Layer 2: Mitigation', check: checkLayer2_Mitigation },
{ name: 'Layer 3: Detection', check: checkLayer3_Detection },
{ name: 'Layer 4: Backstop', check: checkLayer4_Backstop },
{ name: 'Layer 5: Recovery', check: checkLayer5_Recovery }
];
let allPassed = true;
const results = [];
layers.forEach(layer => {
const result = layer.check();
results.push({ name: layer.name, ...result });
const status = result.passed ? '✅' : '❌';
console.log(`${status} ${layer.name}`);
console.log(` ${result.details}`);
if (result.note) {
console.log(` Note: ${result.note}`);
}
console.log('');
if (!result.passed) {
allPassed = false;
}
});
console.log('━'.repeat(70) + '\n');
if (allPassed) {
console.log('✅ All 5 layers of defense-in-depth are in place\n');
console.log('Credential protection meets inst_072 requirements.\n');
process.exit(0);
} else {
const failedLayers = results.filter(r => !r.passed);
console.log(`${failedLayers.length}/5 layer(s) incomplete\n`);
console.log('Multiple layers are required (defense-in-depth).');
console.log('If one layer fails, others should prevent catastrophic outcome.\n');
process.exit(1);
}
}
main();