Security vulnerabilities cost organizations an average of $4.35 million per breach in 2023. Traditional security scanning catches obvious flaws but misses subtle vulnerabilities hidden in business logic, authentication flows, and complex dependency chains. AI-powered security tools are revolutionizing how we detect, prioritize, and remediate vulnerabilities, enabling true shift-left security that integrates seamlessly into development workflows.
In this comprehensive guide, we'll explore how to leverage AI-enhanced security tools like Snyk, Dependabot, and OWASP ZAP to build a robust security scanning pipeline. You'll learn practical techniques for identifying authentication flaws, detecting injection vulnerabilities, analyzing dependency risks, and generating security patches automatically.
The AI-Powered Security Landscape
Modern AI security tools go far beyond pattern matching. They understand code context, recognize vulnerability patterns across languages, and predict potential attack vectors. Here's what sets AI-powered security apart:
- Contextual analysis - AI understands data flow and can trace tainted input through complex call chains
- Reduced false positives - Machine learning models filter noise, reducing false positives by 60-80%
- Intelligent prioritization - AI ranks vulnerabilities by actual exploitability, not just severity scores
- Automated remediation - Generate fix suggestions that maintain functionality while closing security gaps
- Continuous learning - Models improve from new vulnerability discoveries and attack patterns
Integrating Snyk for Comprehensive Vulnerability Scanning
Snyk provides AI-enhanced security scanning for source code, dependencies, containers, and infrastructure as code. Let's set up a comprehensive Snyk integration.
Initial Snyk Setup and Configuration
# Install Snyk CLI
npm install -g snyk
# Authenticate with Snyk
snyk auth
# Test your project for vulnerabilities
snyk test
# Monitor project for new vulnerabilities
snyk monitor
Create a comprehensive Snyk configuration file:
# .snyk - Snyk policy file
version: v1.25.0
# Ignore specific vulnerabilities with justification
ignore:
SNYK-JS-LODASH-567746:
- '*':
reason: 'Low severity, no user input reaches affected function'
expires: 2025-06-01T00:00:00.000Z
# Patch vulnerabilities where possible
patch:
SNYK-JS-AXIOS-1038255:
- axios:
patched: '2025-01-15T10:30:00.000Z'
# Exclude test files from scanning
exclude:
global:
- '**/__tests__/**'
- '**/*.test.ts'
- '**/test/**'
Snyk CI/CD Pipeline Integration
Integrate Snyk into your GitHub Actions workflow for continuous security scanning:
# .github/workflows/security-scan.yml
name: Security Scanning Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
schedule:
# Run daily at midnight
- cron: '0 0 * * *'
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
jobs:
snyk-code:
name: Snyk Code Analysis (SAST)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run Snyk Code test
uses: snyk/actions/node@master
continue-on-error: true
with:
command: code test
args: --severity-threshold=high --sarif-file-output=snyk-code.sarif
- name: Upload SARIF to GitHub
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: snyk-code.sarif
snyk-deps:
name: Dependency Vulnerability Scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run Snyk dependency test
uses: snyk/actions/node@master
with:
command: test
args: --severity-threshold=medium --json-file-output=snyk-deps.json
- name: Parse and comment on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const results = JSON.parse(fs.readFileSync('snyk-deps.json', 'utf8'));
if (results.vulnerabilities && results.vulnerabilities.length > 0) {
const vulnSummary = results.vulnerabilities
.slice(0, 10)
.map(v => `- **${v.severity}**: ${v.title} in \`${v.packageName}\``)
.join('\n');
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## Security Scan Results\n\n${vulnSummary}\n\n[View full report](${results.projectUrl})`
});
}
snyk-container:
name: Container Security Scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t myapp:${{ github.sha }} .
- name: Run Snyk container test
uses: snyk/actions/docker@master
with:
image: myapp:${{ github.sha }}
args: --severity-threshold=high
snyk-iac:
name: Infrastructure as Code Scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Snyk IaC test
uses: snyk/actions/iac@master
with:
args: --severity-threshold=medium
Configuring Dependabot for Automated Updates
Dependabot automatically creates pull requests to update vulnerable dependencies. Configure it for intelligent, security-focused updates:
# .github/dependabot.yml
version: 2
updates:
# NPM dependencies
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
time: "09:00"
timezone: "America/New_York"
open-pull-requests-limit: 10
# Group security updates
groups:
security-patches:
applies-to: security-updates
patterns:
- "*"
update-types:
- "patch"
development-dependencies:
patterns:
- "@types/*"
- "eslint*"
- "prettier*"
- "jest*"
- "vitest*"
update-types:
- "minor"
- "patch"
# Ignore specific packages
ignore:
- dependency-name: "aws-sdk"
update-types: ["version-update:semver-major"]
# Customize commit messages
commit-message:
prefix: "deps"
prefix-development: "deps-dev"
include: "scope"
# Labels for categorization
labels:
- "dependencies"
- "security"
# Reviewers for security updates
reviewers:
- "security-team"
# Allow specific ecosystems
allow:
- dependency-type: "production"
# Docker dependencies
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "weekly"
labels:
- "docker"
- "infrastructure"
# GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
labels:
- "ci-cd"
Automating Dependabot PR Management
# .github/workflows/dependabot-automation.yml
name: Dependabot Automation
on:
pull_request:
types: [opened, synchronize]
permissions:
contents: write
pull-requests: write
jobs:
auto-approve-merge:
runs-on: ubuntu-latest
if: github.actor == 'dependabot[bot]'
steps:
- name: Fetch Dependabot metadata
id: dependabot-metadata
uses: dependabot/fetch-metadata@v2
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Auto-approve patch updates
if: steps.dependabot-metadata.outputs.update-type == 'version-update:semver-patch'
run: gh pr review --approve "$PR_URL"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Auto-merge security patches
if: steps.dependabot-metadata.outputs.update-type == 'version-update:semver-patch' &&
contains(steps.dependabot-metadata.outputs.dependency-names, 'security')
run: gh pr merge --auto --squash "$PR_URL"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SAST Implementation with AI Enhancement
Static Application Security Testing (SAST) analyzes source code for vulnerabilities without execution. Here's how to implement comprehensive SAST with AI enhancement:
// security/sast-config.ts
import { ESLint } from 'eslint';
import { exec } from 'child_process';
import { promisify } from 'util';
const execAsync = promisify(exec);
interface SecurityFinding {
severity: 'critical' | 'high' | 'medium' | 'low' | 'info';
category: string;
message: string;
file: string;
line: number;
column: number;
rule: string;
cwe?: string;
owasp?: string;
remediation?: string;
}
export class SASTScanner {
private findings: SecurityFinding[] = [];
async runSecurityLinting(): Promise<SecurityFinding[]> {
const eslint = new ESLint({
overrideConfigFile: '.eslintrc.security.js',
extensions: ['.js', '.ts', '.jsx', '.tsx']
});
const results = await eslint.lintFiles(['src/**/*']);
for (const result of results) {
for (const message of result.messages) {
if (this.isSecurityRule(message.ruleId)) {
this.findings.push({
severity: this.mapSeverity(message.severity),
category: this.categorizeRule(message.ruleId!),
message: message.message,
file: result.filePath,
line: message.line,
column: message.column,
rule: message.ruleId || 'unknown',
cwe: this.getCWE(message.ruleId),
owasp: this.getOWASP(message.ruleId),
remediation: this.getRemediation(message.ruleId)
});
}
}
}
return this.findings;
}
private isSecurityRule(ruleId: string | null): boolean {
if (!ruleId) return false;
const securityPrefixes = [
'security/',
'no-secrets/',
'@typescript-eslint/no-explicit-any',
'no-eval',
'no-implied-eval',
'no-new-func'
];
return securityPrefixes.some(prefix => ruleId.startsWith(prefix));
}
private mapSeverity(severity: number): SecurityFinding['severity'] {
switch (severity) {
case 2: return 'high';
case 1: return 'medium';
default: return 'low';
}
}
private categorizeRule(ruleId: string): string {
if (ruleId.includes('injection')) return 'Injection';
if (ruleId.includes('xss')) return 'Cross-Site Scripting';
if (ruleId.includes('auth')) return 'Authentication';
if (ruleId.includes('crypto')) return 'Cryptography';
if (ruleId.includes('secret')) return 'Secret Exposure';
return 'General Security';
}
private getCWE(ruleId: string | null): string | undefined {
const cweMapping: Record<string, string> = {
'no-eval': 'CWE-95',
'security/detect-sql-injection': 'CWE-89',
'security/detect-xss': 'CWE-79',
'security/detect-path-traversal': 'CWE-22',
'security/detect-command-injection': 'CWE-78'
};
return ruleId ? cweMapping[ruleId] : undefined;
}
private getOWASP(ruleId: string | null): string | undefined {
const owaspMapping: Record<string, string> = {
'security/detect-sql-injection': 'A03:2021',
'security/detect-xss': 'A03:2021',
'security/detect-broken-auth': 'A07:2021',
'security/detect-sensitive-data': 'A02:2021'
};
return ruleId ? owaspMapping[ruleId] : undefined;
}
private getRemediation(ruleId: string | null): string | undefined {
const remediationGuide: Record<string, string> = {
'no-eval': 'Replace eval() with JSON.parse() for data or use a sandboxed interpreter',
'security/detect-sql-injection': 'Use parameterized queries or an ORM with proper escaping',
'security/detect-xss': 'Sanitize user input with DOMPurify and use Content-Security-Policy headers'
};
return ruleId ? remediationGuide[ruleId] : undefined;
}
async generateReport(): Promise<string> {
const findings = await this.runSecurityLinting();
const summary = {
total: findings.length,
critical: findings.filter(f => f.severity === 'critical').length,
high: findings.filter(f => f.severity === 'high').length,
medium: findings.filter(f => f.severity === 'medium').length,
low: findings.filter(f => f.severity === 'low').length
};
return JSON.stringify({ summary, findings }, null, 2);
}
}
ESLint Security Configuration
// .eslintrc.security.js
module.exports = {
plugins: [
'security',
'no-secrets',
'@typescript-eslint'
],
extends: [
'plugin:security/recommended'
],
rules: {
// Injection Prevention
'security/detect-object-injection': 'error',
'security/detect-non-literal-regexp': 'warn',
'security/detect-non-literal-require': 'error',
'security/detect-non-literal-fs-filename': 'error',
'security/detect-eval-with-expression': 'error',
'security/detect-child-process': 'warn',
// XSS Prevention
'security/detect-possible-timing-attacks': 'warn',
// Secret Detection
'no-secrets/no-secrets': ['error', {
tolerance: 4.5,
additionalRegexes: {
'AWS Key': /AKIA[0-9A-Z]{16}/,
'Slack Token': /xox[baprs]-[0-9a-zA-Z]{10,}/,
'GitHub Token': /ghp_[0-9a-zA-Z]{36}/,
'Private Key': /-----BEGIN (RSA|EC|OPENSSH) PRIVATE KEY-----/
}
}],
// Dangerous Functions
'no-eval': 'error',
'no-implied-eval': 'error',
'no-new-func': 'error',
// TypeScript Security
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-unsafe-assignment': 'warn',
'@typescript-eslint/no-unsafe-call': 'warn',
'@typescript-eslint/no-unsafe-member-access': 'warn'
},
overrides: [
{
files: ['**/*.test.ts', '**/*.spec.ts'],
rules: {
'security/detect-object-injection': 'off',
'no-secrets/no-secrets': 'off'
}
}
]
};
DAST with OWASP ZAP
Dynamic Application Security Testing (DAST) tests running applications. Here's how to integrate OWASP ZAP for automated DAST:
# .github/workflows/dast-scan.yml
name: DAST Security Scan
on:
deployment:
types: [completed]
jobs:
zap-scan:
runs-on: ubuntu-latest
if: github.event.deployment.environment == 'staging'
steps:
- uses: actions/checkout@v4
- name: Wait for deployment
run: |
echo "Waiting for staging deployment to be ready..."
sleep 60
curl --retry 10 --retry-delay 10 --retry-connrefused \
${{ secrets.STAGING_URL }}/health
- name: ZAP Baseline Scan
uses: zaproxy/action-baseline@v0.10.0
with:
target: ${{ secrets.STAGING_URL }}
rules_file_name: 'zap-rules.tsv'
cmd_options: '-a -j -l WARN'
- name: ZAP Full Scan
uses: zaproxy/action-full-scan@v0.10.0
with:
target: ${{ secrets.STAGING_URL }}
rules_file_name: 'zap-rules.tsv'
cmd_options: '-a -j'
- name: Upload ZAP Report
uses: actions/upload-artifact@v4
with:
name: zap-report
path: report_html.html
- name: Parse ZAP results
id: zap-results
run: |
HIGH_ALERTS=$(grep -c "High" report_html.html || echo 0)
MEDIUM_ALERTS=$(grep -c "Medium" report_html.html || echo 0)
echo "high_count=$HIGH_ALERTS" >> $GITHUB_OUTPUT
echo "medium_count=$MEDIUM_ALERTS" >> $GITHUB_OUTPUT
- name: Fail on critical findings
if: steps.zap-results.outputs.high_count > 0
run: |
echo "Found ${{ steps.zap-results.outputs.high_count }} high severity vulnerabilities!"
exit 1
ZAP Custom Rules Configuration
# zap-rules.tsv - Custom ZAP scan rules
# Rule ID Rule Name Threshold Action
10016 Web Browser XSS Protection Not Enabled MEDIUM WARN
10017 Cross-Domain JavaScript Source File Inclusion LOW IGNORE
10019 Content-Type Header Missing MEDIUM WARN
10020 X-Frame-Options Header Not Set HIGH FAIL
10021 X-Content-Type-Options Header Missing MEDIUM WARN
10023 Information Disclosure - Debug Error Messages HIGH FAIL
10024 Information Disclosure - Sensitive Information in URL HIGH FAIL
10025 Information Disclosure - Sensitive Information in HTTP Referrer Header MEDIUM WARN
10027 Information Disclosure - Suspicious Comments LOW IGNORE
10028 Open Redirect HIGH FAIL
10029 Cookie Poisoning HIGH FAIL
10030 User Controllable Charset MEDIUM WARN
10031 User Controllable HTML Element Attribute MEDIUM WARN
10032 Viewstate LOW IGNORE
10035 Strict-Transport-Security Header Not Set HIGH FAIL
10036 Server Leaks Version Information via "Server" HTTP Response Header Field LOW WARN
10037 Server Leaks Information via "X-Powered-By" HTTP Response Header Field LOW WARN
10038 Content Security Policy (CSP) Header Not Set MEDIUM WARN
10039 X-Backend-Server Header Information Leak MEDIUM WARN
10040 Secure Pages Include Mixed Content MEDIUM WARN
10054 Cookie Without SameSite Attribute MEDIUM WARN
10055 CSP: Wildcard Directive MEDIUM WARN
10056 CSP: script-src unsafe-inline HIGH FAIL
10057 CSP: style-src unsafe-inline MEDIUM WARN
10061 X-AspNet-Version Response Header LOW WARN
10062 PII Disclosure HIGH FAIL
10096 Timestamp Disclosure LOW IGNORE
10097 Hash Disclosure MEDIUM WARN
10098 Cross-Domain Misconfiguration MEDIUM WARN
10105 Weak Authentication Method HIGH FAIL
10108 Reverse Tabnabbing MEDIUM WARN
10109 Modern Web Application LOW IGNORE
10110 Dangerous JS Functions MEDIUM WARN
AI-Generated Security Patches
Leverage AI to generate security patches for identified vulnerabilities:
// security/patch-generator.ts
import Anthropic from '@anthropic-ai/sdk';
interface Vulnerability {
type: string;
file: string;
line: number;
code: string;
cwe: string;
description: string;
}
interface SecurityPatch {
originalCode: string;
patchedCode: string;
explanation: string;
testCases: string[];
}
export class AISecurityPatchGenerator {
private client: Anthropic;
constructor() {
this.client = new Anthropic();
}
async generatePatch(vulnerability: Vulnerability): Promise<SecurityPatch> {
const prompt = `You are a security expert. Analyze this vulnerability and provide a secure fix.
Vulnerability Type: ${vulnerability.type}
CWE: ${vulnerability.cwe}
File: ${vulnerability.file}
Line: ${vulnerability.line}
Vulnerable Code:
\`\`\`
${vulnerability.code}
\`\`\`
Description: ${vulnerability.description}
Provide:
1. Patched code that fixes the vulnerability
2. Explanation of the fix
3. Test cases to verify the fix works
Respond in JSON format:
{
"patchedCode": "...",
"explanation": "...",
"testCases": ["...", "..."]
}`;
const response = await this.client.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 2000,
messages: [{ role: 'user', content: prompt }]
});
const content = response.content[0];
if (content.type !== 'text') {
throw new Error('Unexpected response type');
}
const result = JSON.parse(content.text);
return {
originalCode: vulnerability.code,
patchedCode: result.patchedCode,
explanation: result.explanation,
testCases: result.testCases
};
}
async batchGeneratePatches(
vulnerabilities: Vulnerability[]
): Promise<Map<string, SecurityPatch>> {
const patches = new Map<string, SecurityPatch>();
for (const vuln of vulnerabilities) {
try {
const patch = await this.generatePatch(vuln);
patches.set(`${vuln.file}:${vuln.line}`, patch);
} catch (error) {
console.error(`Failed to generate patch for ${vuln.file}:${vuln.line}`, error);
}
}
return patches;
}
}
// Example usage
const generator = new AISecurityPatchGenerator();
const sqlInjectionVuln: Vulnerability = {
type: 'SQL Injection',
file: 'src/api/users.ts',
line: 45,
cwe: 'CWE-89',
code: `
async function getUser(userId: string) {
const query = \`SELECT * FROM users WHERE id = '\${userId}'\`;
return await db.query(query);
}
`,
description: 'User input is directly concatenated into SQL query'
};
const patch = await generator.generatePatch(sqlInjectionVuln);
console.log('Patched code:', patch.patchedCode);
console.log('Explanation:', patch.explanation);
Intelligent Dependency Scanning
Go beyond basic dependency checking with intelligent vulnerability correlation:
// security/dependency-analyzer.ts
import { execSync } from 'child_process';
interface DependencyVulnerability {
package: string;
version: string;
vulnerability: {
id: string;
severity: 'critical' | 'high' | 'medium' | 'low';
title: string;
description: string;
exploitMaturity: 'proof-of-concept' | 'functional' | 'high' | 'no-known-exploit';
isUpgradable: boolean;
isPatchable: boolean;
fixedIn: string | null;
};
paths: string[][];
reachability: 'reachable' | 'potentially-reachable' | 'not-reachable' | 'unknown';
}
export class DependencySecurityAnalyzer {
async scanDependencies(): Promise<DependencyVulnerability[]> {
// Run npm audit with JSON output
const auditOutput = execSync('npm audit --json', {
encoding: 'utf-8',
stdio: ['pipe', 'pipe', 'pipe']
});
const auditData = JSON.parse(auditOutput);
return this.parseAuditResults(auditData);
}
async analyzeReachability(
vulnerability: DependencyVulnerability
): Promise<'reachable' | 'not-reachable' | 'unknown'> {
// Check if vulnerable function is actually called in codebase
const vulnerableFunctions = await this.getVulnerableFunctions(
vulnerability.vulnerability.id
);
for (const func of vulnerableFunctions) {
const isUsed = await this.checkFunctionUsage(
vulnerability.package,
func
);
if (isUsed) return 'reachable';
}
return 'not-reachable';
}
private async getVulnerableFunctions(vulnId: string): Promise<string[]> {
// Query vulnerability database for affected functions
// This would integrate with Snyk or NVD API
return [];
}
private async checkFunctionUsage(
packageName: string,
functionName: string
): Promise<boolean> {
try {
const grepResult = execSync(
`grep -r "import.*${functionName}.*from.*${packageName}" src/ || true`,
{ encoding: 'utf-8' }
);
return grepResult.trim().length > 0;
} catch {
return false;
}
}
private parseAuditResults(auditData: any): DependencyVulnerability[] {
const vulnerabilities: DependencyVulnerability[] = [];
for (const [name, advisory] of Object.entries(auditData.vulnerabilities || {})) {
const adv = advisory as any;
vulnerabilities.push({
package: name,
version: adv.range,
vulnerability: {
id: adv.via[0]?.source || 'unknown',
severity: adv.severity,
title: adv.via[0]?.title || 'Unknown vulnerability',
description: adv.via[0]?.url || '',
exploitMaturity: 'unknown' as any,
isUpgradable: adv.fixAvailable !== false,
isPatchable: false,
fixedIn: adv.fixAvailable?.version || null
},
paths: adv.nodes || [],
reachability: 'unknown'
});
}
return vulnerabilities;
}
generateRemediationPlan(
vulnerabilities: DependencyVulnerability[]
): string {
const critical = vulnerabilities.filter(v => v.vulnerability.severity === 'critical');
const high = vulnerabilities.filter(v => v.vulnerability.severity === 'high');
let plan = '# Security Remediation Plan\n\n';
plan += '## Immediate Actions (Critical)\n\n';
for (const vuln of critical) {
plan += `### ${vuln.package}@${vuln.version}\n`;
plan += `- **Issue**: ${vuln.vulnerability.title}\n`;
plan += `- **Fix**: ${vuln.vulnerability.fixedIn ? `Upgrade to ${vuln.vulnerability.fixedIn}` : 'No fix available'}\n`;
plan += `- **Command**: \`npm update ${vuln.package}\`\n\n`;
}
plan += '## High Priority\n\n';
for (const vuln of high) {
plan += `### ${vuln.package}@${vuln.version}\n`;
plan += `- **Issue**: ${vuln.vulnerability.title}\n`;
plan += `- **Reachability**: ${vuln.reachability}\n`;
plan += `- **Fix**: ${vuln.vulnerability.fixedIn ? `Upgrade to ${vuln.vulnerability.fixedIn}` : 'Consider alternative package'}\n\n`;
}
return plan;
}
}
Authentication and Authorization Scanning
Detect common authentication flaws with specialized scanning:
// security/auth-scanner.ts
import { parse } from '@babel/parser';
import traverse from '@babel/traverse';
import * as fs from 'fs';
import * as glob from 'glob';
interface AuthVulnerability {
type: 'broken-auth' | 'broken-access-control' | 'session-management' | 'credential-exposure';
severity: 'critical' | 'high' | 'medium' | 'low';
file: string;
line: number;
description: string;
recommendation: string;
}
export class AuthenticationScanner {
private vulnerabilities: AuthVulnerability[] = [];
async scanProject(srcPath: string): Promise<AuthVulnerability[]> {
const files = glob.sync(`${srcPath}/**/*.{ts,js,tsx,jsx}`);
for (const file of files) {
await this.scanFile(file);
}
return this.vulnerabilities;
}
private async scanFile(filePath: string): Promise<void> {
const code = fs.readFileSync(filePath, 'utf-8');
try {
const ast = parse(code, {
sourceType: 'module',
plugins: ['typescript', 'jsx']
});
traverse(ast, {
// Detect hardcoded credentials
VariableDeclarator: (path) => {
const init = path.node.init;
if (init?.type === 'StringLiteral') {
const value = init.value.toLowerCase();
const name = path.node.id.type === 'Identifier'
? path.node.id.name.toLowerCase()
: '';
if (
(name.includes('password') || name.includes('secret') || name.includes('key')) &&
value.length > 5 &&
!value.includes('${')
) {
this.vulnerabilities.push({
type: 'credential-exposure',
severity: 'critical',
file: filePath,
line: path.node.loc?.start.line || 0,
description: 'Hardcoded credential detected',
recommendation: 'Use environment variables or a secrets manager'
});
}
}
},
// Detect weak JWT configurations
CallExpression: (path) => {
const callee = path.node.callee;
if (
callee.type === 'MemberExpression' &&
callee.property.type === 'Identifier' &&
callee.property.name === 'sign'
) {
const args = path.node.arguments;
if (args.length >= 3) {
const options = args[2];
if (options.type === 'ObjectExpression') {
const hasExpiry = options.properties.some(
p => p.type === 'ObjectProperty' &&
p.key.type === 'Identifier' &&
p.key.name === 'expiresIn'
);
if (!hasExpiry) {
this.vulnerabilities.push({
type: 'session-management',
severity: 'high',
file: filePath,
line: path.node.loc?.start.line || 0,
description: 'JWT token without expiration',
recommendation: 'Add expiresIn option to jwt.sign()'
});
}
}
}
}
// Detect missing CSRF protection
if (
callee.type === 'Identifier' &&
(callee.name === 'post' || callee.name === 'put' || callee.name === 'delete')
) {
// Check for CSRF middleware in the handler chain
// This is a simplified check
const middlewares = path.node.arguments.slice(1, -1);
const hasCsrf = middlewares.some(m => {
if (m.type === 'Identifier') {
return m.name.toLowerCase().includes('csrf');
}
return false;
});
if (!hasCsrf && path.node.arguments.length > 1) {
this.vulnerabilities.push({
type: 'broken-access-control',
severity: 'medium',
file: filePath,
line: path.node.loc?.start.line || 0,
description: 'State-changing endpoint may lack CSRF protection',
recommendation: 'Add CSRF middleware to POST/PUT/DELETE routes'
});
}
}
}
});
} catch (error) {
console.warn(`Failed to parse ${filePath}:`, error);
}
}
}
Security Improvement Metrics
Track and measure your security posture over time:
// security/metrics-collector.ts
interface SecurityMetrics {
timestamp: Date;
vulnerabilities: {
total: number;
critical: number;
high: number;
medium: number;
low: number;
};
coverage: {
sastCoverage: number;
dastCoverage: number;
dependencyScanning: number;
secretsScanning: number;
};
mttr: {
critical: number; // Mean time to remediate in hours
high: number;
medium: number;
};
compliance: {
owaspTop10: number; // Percentage compliance
pciDss: number;
hipaa: number;
};
}
export class SecurityMetricsCollector {
private metricsHistory: SecurityMetrics[] = [];
async collectMetrics(): Promise<SecurityMetrics> {
const metrics: SecurityMetrics = {
timestamp: new Date(),
vulnerabilities: await this.countVulnerabilities(),
coverage: await this.calculateCoverage(),
mttr: await this.calculateMTTR(),
compliance: await this.checkCompliance()
};
this.metricsHistory.push(metrics);
return metrics;
}
private async countVulnerabilities(): Promise<SecurityMetrics['vulnerabilities']> {
// Aggregate from all security tools
return {
total: 0,
critical: 0,
high: 0,
medium: 0,
low: 0
};
}
private async calculateCoverage(): Promise<SecurityMetrics['coverage']> {
return {
sastCoverage: 85, // Percentage of code analyzed
dastCoverage: 70, // Percentage of endpoints tested
dependencyScanning: 100, // All dependencies scanned
secretsScanning: 95 // Files scanned for secrets
};
}
private async calculateMTTR(): Promise<SecurityMetrics['mttr']> {
// Calculate from historical vulnerability data
return {
critical: 4, // 4 hours average for critical vulns
high: 24,
medium: 168 // 1 week
};
}
private async checkCompliance(): Promise<SecurityMetrics['compliance']> {
return {
owaspTop10: 92,
pciDss: 88,
hipaa: 90
};
}
generateDashboard(): string {
const latest = this.metricsHistory[this.metricsHistory.length - 1];
return `
# Security Dashboard
## Vulnerability Summary
- Critical: ${latest.vulnerabilities.critical}
- High: ${latest.vulnerabilities.high}
- Medium: ${latest.vulnerabilities.medium}
- Low: ${latest.vulnerabilities.low}
## Coverage
- SAST: ${latest.coverage.sastCoverage}%
- DAST: ${latest.coverage.dastCoverage}%
- Dependencies: ${latest.coverage.dependencyScanning}%
- Secrets: ${latest.coverage.secretsScanning}%
## Mean Time to Remediate
- Critical: ${latest.mttr.critical} hours
- High: ${latest.mttr.high} hours
- Medium: ${latest.mttr.medium} hours
## Compliance
- OWASP Top 10: ${latest.compliance.owaspTop10}%
- PCI-DSS: ${latest.compliance.pciDss}%
- HIPAA: ${latest.compliance.hipaa}%
`;
}
}
Security Scanning Best Practices
- Shift left - Integrate security scanning early in development, not just before deployment
- Layer defenses - Combine SAST, DAST, SCA, and container scanning for comprehensive coverage
- Prioritize intelligently - Focus on reachable, exploitable vulnerabilities first
- Automate remediation - Use AI to generate patches and Dependabot for dependency updates
- Measure continuously - Track MTTR, vulnerability trends, and compliance metrics
- Context matters - Not all vulnerabilities are equal; assess actual risk to your application
Implementing Shift-Left Security
Shift-left security integrates security checks as early as possible in development:
// Pre-commit hook for security checks
// .husky/pre-commit
#!/bin/sh
echo "Running security checks..."
# Check for secrets
npx secretlint "**/*"
if [ $? -ne 0 ]; then
echo "Secrets detected! Please remove before committing."
exit 1
fi
# Run security linting
npm run lint:security
if [ $? -ne 0 ]; then
echo "Security issues found! Please fix before committing."
exit 1
fi
# Check dependencies
npm audit --audit-level=high
if [ $? -ne 0 ]; then
echo "High severity vulnerabilities in dependencies!"
exit 1
fi
echo "Security checks passed!"
// package.json security scripts
{
"scripts": {
"security:check": "npm run security:sast && npm run security:deps && npm run security:secrets",
"security:sast": "eslint --config .eslintrc.security.js src/",
"security:deps": "npm audit --audit-level=moderate",
"security:secrets": "secretlint **/*",
"security:full": "npm run security:check && snyk test && snyk code test",
"lint:security": "eslint --config .eslintrc.security.js --fix src/"
}
}
Conclusion
AI-powered security scanning transforms how we identify and remediate vulnerabilities. By combining tools like Snyk for comprehensive scanning, Dependabot for automated updates, and OWASP ZAP for dynamic testing, you create multiple layers of security defense. The key is integrating these tools seamlessly into your CI/CD pipeline and development workflow.
Remember that security is not a one-time activity but a continuous process. Use AI to accelerate vulnerability detection and patch generation, but always apply human judgment for risk assessment and prioritization. The goal is not zero vulnerabilities but managing risk effectively while maintaining development velocity.
In our next article, we'll explore AI for Performance Monitoring and Optimization, where you'll learn how to leverage AI tools for identifying performance bottlenecks, optimizing resource usage, and building self-healing systems.