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

  1. Layer Security Scans: Use multiple scanning types for comprehensive coverage
  2. Automate Everything: Integrate scans into CI/CD pipelines
  3. Prioritize Critical Issues: Focus on high and critical severity vulnerabilities first
  4. Test After Updates: Always run tests after applying security updates
  5. Monitor Continuously: Security is an ongoing process, not a one-time check

See Also