Code Scanning and Analysis
Overview
Comprehensive security scanning patterns that integrate dependency vulnerability scanning, static code analysis, secret detection, and automated remediation workflows using Claude Code.
Multi-Layer Scanning Approach
// security/comprehensive-scanner.ts
export class ComprehensiveSecurityScanner {
private scanners = {
dependencies: new DependencyScanner(),
staticAnalysis: new StaticAnalysisScanner(),
secrets: new SecretScanner(),
containers: new ContainerScanner()
};
async performFullScan(project: Project): Promise<ScanReport> {
const results = await Promise.all([
this.scanners.dependencies.scan(project),
this.scanners.staticAnalysis.scan(project),
this.scanners.secrets.scan(project),
this.scanners.containers.scan(project)
]);
return this.consolidateResults(results);
}
}Dependency Vulnerability Scanning
Configuration
// .claude/security-scan-config.ts
interface SecurityScanConfig {
scanFrequency: 'daily' | 'weekly' | 'on-commit';
severityThreshold: 'low' | 'medium' | 'high' | 'critical';
autoRemediate: boolean;
notificationChannels: string[];
}
export const securityConfig: SecurityScanConfig = {
scanFrequency: 'daily',
severityThreshold: 'medium',
autoRemediate: true,
notificationChannels: ['slack', 'email']
};Automated Remediation
// .claude/hooks/security-remediation-hook.ts
import { ClaudeHook } from '@claude/types';
export const securityRemediationHook: ClaudeHook = {
name: 'security-remediation',
trigger: 'scheduled',
schedule: '0 2 * * *', // Daily at 2 AM
async execute(context) {
const scanResult = await context.runCommand('npm audit --json');
const vulnerabilities = JSON.parse(scanResult.stdout);
if (vulnerabilities.metadata.vulnerabilities.total === 0) {
return { continue: true };
}
// Create remediation branch
await context.runCommand('git checkout -b security/dependency-updates');
// Apply fixes
await context.runCommand('npm audit fix --force');
// Run tests
const testResult = await context.runCommand('npm test');
if (testResult.exitCode !== 0) {
await context.runCommand('git checkout main');
await context.runCommand('git branch -D security/dependency-updates');
return {
continue: false,
message: 'Security updates broke tests, manual intervention required'
};
}
// Commit and create PR
await context.runCommand('git add package*.json');
await context.runCommand('git commit -m "fix: update dependencies to resolve security vulnerabilities"');
await context.runCommand('git push origin security/dependency-updates');
await context.runCommand(`gh pr create --title "Security: Dependency Updates" --body "Automated security updates from vulnerability scan"`);
return { continue: true };
}
};Static Code Analysis
ESLint Security Configuration
// .eslintrc.security.js
module.exports = {
extends: [
'plugin:security/recommended',
'plugin:security-node/recommended'
],
plugins: [
'security',
'security-node',
'no-secrets'
],
rules: {
// Prevent XSS vulnerabilities
'security/detect-no-csrf-before-method-override': 'error',
'security/detect-possible-timing-attacks': 'warn',
'security/detect-eval-with-expression': 'error',
// Prevent injection attacks
'security/detect-child-process': 'error',
'security/detect-non-literal-regexp': 'warn',
'security/detect-non-literal-require': 'error',
// Prevent secrets in code
'no-secrets/no-secrets': ['error', {
tolerance: 4.5,
additionalRegexes: {
'Anthropic API Key': /sk-ant-[a-zA-Z0-9-_]{40,}/
}
}]
}
};Custom TypeScript Security Analyzer
// tools/ts-security-analyzer.ts
import * as ts from 'typescript';
class TypeScriptSecurityAnalyzer {
private issues: SecurityIssue[] = [];
analyzeFile(filePath: string): SecurityIssue[] {
const sourceCode = readFileSync(filePath, 'utf-8');
const sourceFile = ts.createSourceFile(
filePath,
sourceCode,
ts.ScriptTarget.Latest,
true
);
this.visitNode(sourceFile, sourceFile);
return this.issues;
}
private visitNode(node: ts.Node, sourceFile: ts.SourceFile) {
// Check for eval usage
if (ts.isCallExpression(node) &&
node.expression.getText() === 'eval') {
this.addIssue(sourceFile, node, {
severity: 'critical',
type: 'eval-usage',
message: 'Use of eval() is a security risk',
suggestion: 'Use Function constructor or JSON.parse instead'
});
}
// Check for SQL injection vulnerabilities
if (ts.isTemplateExpression(node) || ts.isStringLiteral(node)) {
const text = node.getText();
if (text.includes('SELECT') || text.includes('INSERT') ||
text.includes('UPDATE') || text.includes('DELETE')) {
this.addIssue(sourceFile, node, {
severity: 'high',
type: 'sql-injection',
message: 'Potential SQL injection vulnerability',
suggestion: 'Use parameterized queries or an ORM'
});
}
}
ts.forEachChild(node, child => this.visitNode(child, sourceFile));
}
}Secret Detection and Management
Secret Patterns
interface SecretPattern {
name: string;
pattern: RegExp;
severity: 'low' | 'medium' | 'high' | 'critical';
verifier?: (match: string) => Promise<boolean>;
}
export class SecretScanner {
private patterns: SecretPattern[] = [
{
name: 'AWS Access Key',
pattern: /AKIA[0-9A-Z]{16}/,
severity: 'critical',
verifier: this.verifyAWSKey
},
{
name: 'GitHub Token',
pattern: /ghp_[a-zA-Z0-9]{36}/,
severity: 'critical',
verifier: this.verifyGitHubToken
},
{
name: 'Anthropic API Key',
pattern: /sk-ant-api[0-9]{2}-[a-zA-Z0-9-_]{48}/,
severity: 'critical',
verifier: this.verifyAnthropicKey
},
{
name: 'Private Key',
pattern: /-----BEGIN (RSA |EC )?PRIVATE KEY-----/,
severity: 'critical'
}
];
async scanFile(filePath: string): Promise<SecretMatch[]> {
const content = await readFile(filePath, 'utf-8');
const matches: SecretMatch[] = [];
for (const pattern of this.patterns) {
const regex = new RegExp(pattern.pattern, 'g');
let match;
while ((match = regex.exec(content)) !== null) {
const secretMatch: SecretMatch = {
type: pattern.name,
value: match[0],
file: filePath,
line: this.getLineNumber(content, match.index),
column: this.getColumnNumber(content, match.index),
severity: pattern.severity,
verified: false
};
if (pattern.verifier) {
secretMatch.verified = await pattern.verifier(match[0]);
}
matches.push(secretMatch);
}
}
return matches;
}
}Git Pre-commit Hook
#!/usr/bin/env node
async function preCommitSecretScan() {
const scanner = new SecretScanner();
const git = new GitHelper();
const stagedFiles = await git.getStagedFiles();
let secretsFound = false;
const allMatches: SecretMatch[] = [];
for (const file of stagedFiles) {
const matches = await scanner.scanFile(file);
if (matches.length > 0) {
secretsFound = true;
allMatches.push(...matches);
}
}
if (secretsFound) {
console.error('\n🚨 SECRETS DETECTED IN COMMIT! 🚨\n');
for (const match of allMatches) {
console.error(`
File: ${match.file}
Line: ${match.line}
Type: ${match.type}
Severity: ${match.severity.toUpperCase()}
${match.verified ? '⚠️ This secret is ACTIVE!' : ''}
`);
}
process.exit(1);
}
console.log('✅ No secrets detected in commit');
}Integrated Scanning Workflow
// .claude/static-analysis-workflow.ts
import { ClaudeWorkflow } from '@claude/sdk';
export const staticAnalysisWorkflow: ClaudeWorkflow = {
name: 'static-code-analysis',
async execute(context) {
const analysisSteps = [
{
tool: 'ESLint',
command: 'npx eslint . --config .eslintrc.security.js --format json',
processor: processESLintResults
},
{
tool: 'Semgrep',
command: 'semgrep --config=auto --json',
processor: processSemgrepResults
},
{
tool: 'TypeScript Security',
command: 'npx ts-security-scan',
processor: processTSSecurityResults
}
];
const vulnerabilities = [];
for (const step of analysisSteps) {
const result = await context.runCommand(step.command);
const issues = step.processor(result);
vulnerabilities.push(...issues);
}
// Generate fixes using Claude
for (const vuln of vulnerabilities.filter(v => v.severity === 'high')) {
const fix = await context.generateFix({
file: vuln.file,
line: vuln.line,
issue: vuln.description,
rule: vuln.rule
});
if (fix.confidence > 0.8) {
await context.applyFix(fix);
}
}
return { vulnerabilities, fixed: vulnerabilities.filter(v => v.fixed) };
}
};CI/CD Integration
# .github/workflows/security-scan.yml
name: Security Scan
on: [push, pull_request]
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- name: Dependency Scan
run: |
npm audit --json
npx snyk test --severity-threshold=medium
- name: Static Analysis
run: |
npx eslint . --ext .ts,.tsx --config .eslintrc.security.js
npx semgrep --config=auto --error
- name: Secret Scanning
run: npm run scan:secrets
- name: Container Scan
if: contains(github.event.head_commit.message, 'docker')
run: trivy image ${{ env.IMAGE_NAME }}Best Practices
- Layer Security Scans: Use multiple scanning types for comprehensive coverage
- Automate Everything: Integrate scans into CI/CD pipelines
- Prioritize Critical Issues: Focus on high and critical severity vulnerabilities first
- Test After Updates: Always run tests after applying security updates
- Monitor Continuously: Security is an ongoing process, not a one-time check