Skip to content

Security Scanning

Security isn’t optional - it’s fundamental. Whether you’re handling user data, processing payments, or just building a blog, security vulnerabilities can destroy trust and business. Claude Code transforms security from a checkbox exercise into an integrated development practice, helping you build secure applications from the ground up.

Scenario: Your application handles sensitive data for thousands of users. A single vulnerability could expose everything - credentials, personal information, payment details. Traditional approach: periodic pentests, hoping for the best. With Claude Code: continuous security analysis that catches vulnerabilities before they reach production.

Month 1: Development
- Focus on features
- Security as afterthought
- "We'll fix it later"
Month 3: Security Audit
- External pentest
- Long list of vulnerabilities
- Scramble to fix
Month 4: Breach
- Vulnerability exploited
- Data exposed
- Reputation damaged
Ongoing: Reactive Mode
- Fix after discovery
- Hope nothing missed
- Cross fingers
> Perform a comprehensive security audit of our codebase:
> - OWASP Top 10 vulnerabilities
> - Authentication and authorization flaws
> - Input validation issues
> - Cryptographic weaknesses
> - Configuration problems
> - Dependency vulnerabilities

Claude performs a deep security analysis:

  1. SQL Injection Detection

    // VULNERABLE CODE FOUND
    app.get('/user/:id', async (req, res) => {
    const userId = req.params.id;
    // ❌ Direct string concatenation - SQL injection risk!
    const query = `SELECT * FROM users WHERE id = ${userId}`;
    const result = await db.query(query);
    res.json(result);
    });
    // SECURE REPLACEMENT
    app.get('/user/:id', async (req, res) => {
    const userId = req.params.id;
    // ✅ Input validation
    if (!/^\d+$/.test(userId)) {
    return res.status(400).json({ error: 'Invalid user ID' });
    }
    // ✅ Parameterized query
    const query = 'SELECT * FROM users WHERE id = $1';
    const result = await db.query(query, [userId]);
    // ✅ Don't expose sensitive fields
    const { password_hash, ...safeUser } = result.rows[0] || {};
    res.json(safeUser);
    });
  2. Cross-Site Scripting (XSS) Prevention

    // VULNERABLE CODE FOUND
    app.post('/comment', (req, res) => {
    const comment = req.body.comment;
    // ❌ Direct HTML insertion - XSS risk!
    const html = `<div class="comment">${comment}</div>`;
    saveCommentHTML(html);
    });
    // SECURE REPLACEMENT
    const DOMPurify = require('isomorphic-dompurify');
    const { JSDOM } = require('jsdom');
    app.post('/comment', (req, res) => {
    const comment = req.body.comment;
    // ✅ Sanitize HTML input
    const window = new JSDOM('').window;
    const purify = DOMPurify(window);
    const clean = purify.sanitize(comment, {
    ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a'],
    ALLOWED_ATTR: ['href']
    });
    // ✅ Content Security Policy
    res.setHeader(
    'Content-Security-Policy',
    "default-src 'self'; script-src 'self' 'nonce-${nonce}'"
    );
    const html = `<div class="comment">${clean}</div>`;
    saveCommentHTML(html);
    });
  3. Authentication & Authorization

    // VULNERABLE CODE FOUND
    app.post('/admin/users', (req, res) => {
    // ❌ No authentication check!
    updateUsers(req.body);
    res.json({ success: true });
    });
    // SECURE REPLACEMENT
    const jwt = require('jsonwebtoken');
    const bcrypt = require('bcrypt');
    // Authentication middleware
    const authenticate = async (req, res, next) => {
    const token = req.headers.authorization?.split(' ')[1];
    if (!token) {
    return res.status(401).json({ error: 'No token provided' });
    }
    try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = await User.findById(decoded.userId);
    next();
    } catch (error) {
    return res.status(401).json({ error: 'Invalid token' });
    }
    };
    // Authorization middleware
    const authorize = (...roles) => {
    return (req, res, next) => {
    if (!roles.includes(req.user.role)) {
    return res.status(403).json({ error: 'Insufficient permissions' });
    }
    next();
    };
    };
    // ✅ Protected route with auth & authz
    app.post('/admin/users',
    authenticate,
    authorize('admin', 'superadmin'),
    async (req, res) => {
    // Additional validation
    const { error } = validateUserUpdate(req.body);
    if (error) {
    return res.status(400).json({ error: error.details[0].message });
    }
    await updateUsers(req.body);
    // Audit logging
    await auditLog({
    action: 'UPDATE_USERS',
    userId: req.user.id,
    changes: req.body,
    ip: req.ip
    });
    res.json({ success: true });
    }
    );
  4. Cryptographic Security

    // VULNERABLE CODE FOUND
    const crypto = require('crypto');
    function hashPassword(password) {
    // ❌ Weak hashing - MD5 is broken!
    return crypto.createHash('md5').update(password).digest('hex');
    }
    function encryptData(data) {
    // ❌ Hardcoded key and weak algorithm
    const key = '1234567890123456';
    const cipher = crypto.createCipher('aes-128-ecb', key);
    return cipher.update(data, 'utf8', 'hex') + cipher.final('hex');
    }
    // SECURE REPLACEMENT
    const bcrypt = require('bcrypt');
    const argon2 = require('argon2');
    // ✅ Strong password hashing
    async function hashPassword(password) {
    // Option 1: bcrypt (good)
    const saltRounds = 12;
    return await bcrypt.hash(password, saltRounds);
    // Option 2: argon2 (better)
    return await argon2.hash(password, {
    type: argon2.argon2id,
    memoryCost: 2 ** 16,
    timeCost: 3,
    parallelism: 1,
    });
    }
    // ✅ Secure encryption
    async function encryptData(data) {
    const algorithm = 'aes-256-gcm';
    const key = crypto.scryptSync(
    process.env.ENCRYPTION_PASSWORD,
    process.env.ENCRYPTION_SALT,
    32
    );
    const iv = crypto.randomBytes(16);
    const cipher = crypto.createCipheriv(algorithm, key, iv);
    let encrypted = cipher.update(data, 'utf8', 'hex');
    encrypted += cipher.final('hex');
    const authTag = cipher.getAuthTag();
    return {
    encrypted,
    iv: iv.toString('hex'),
    authTag: authTag.toString('hex')
    };
    }
> Implement comprehensive input validation:
> - Request body validation
> - Query parameter sanitization
> - File upload security
> - Rate limiting
> - Request size limits
validation.js
const Joi = require('joi');
const rateLimit = require('express-rate-limit');
const mongoSanitize = require('express-mongo-sanitize');
const hpp = require('hpp');
const helmet = require('helmet');
// Schema validation
const schemas = {
createUser: Joi.object({
email: Joi.string().email().required(),
password: Joi.string()
.min(12)
.pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]/)
.required()
.messages({
'string.pattern.base': 'Password must contain uppercase, lowercase, number, and special character'
}),
username: Joi.string()
.alphanum()
.min(3)
.max(30)
.required(),
role: Joi.string()
.valid('user', 'admin')
.default('user')
}),
updateProfile: Joi.object({
bio: Joi.string().max(500),
website: Joi.string().uri(),
phone: Joi.string().pattern(/^\+?[\d\s-()]+$/)
})
};
// Validation middleware
const validate = (schema) => {
return (req, res, next) => {
const { error, value } = schema.validate(req.body, {
abortEarly: false,
stripUnknown: true
});
if (error) {
const errors = error.details.map(detail => ({
field: detail.path.join('.'),
message: detail.message
}));
return res.status(400).json({ errors });
}
req.body = value;
next();
};
};
// Security middleware stack
const securityMiddleware = [
// Helmet for security headers
helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'nonce-${nonce}'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"],
connectSrc: ["'self'"],
fontSrc: ["'self'"],
objectSrc: ["'none'"],
mediaSrc: ["'self'"],
frameSrc: ["'none'"],
},
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
}
}),
// NoSQL injection prevention
mongoSanitize({
replaceWith: '_',
onSanitize: ({ req, key }) => {
console.warn(`NoSQL injection attempt blocked: ${key}`);
}
}),
// Parameter pollution prevention
hpp({
whitelist: ['sort', 'filter']
}),
// Request size limits
express.json({ limit: '10mb' }),
express.urlencoded({ extended: true, limit: '10mb' }),
// Rate limiting
rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: 'Too many requests from this IP',
standardHeaders: true,
legacyHeaders: false,
})
];
// File upload security
const multer = require('multer');
const path = require('path');
const fileFilter = (req, file, cb) => {
// Allowed extensions
const allowedExtensions = ['.jpg', '.jpeg', '.png', '.pdf'];
const ext = path.extname(file.originalname).toLowerCase();
if (!allowedExtensions.includes(ext)) {
return cb(new Error('Invalid file type'), false);
}
// Check MIME type
const allowedMimeTypes = ['image/jpeg', 'image/png', 'application/pdf'];
if (!allowedMimeTypes.includes(file.mimetype)) {
return cb(new Error('Invalid MIME type'), false);
}
// Check for double extensions
const nameWithoutExt = path.basename(file.originalname, ext);
if (path.extname(nameWithoutExt)) {
return cb(new Error('Double extension not allowed'), false);
}
cb(null, true);
};
const upload = multer({
storage: multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads/');
},
filename: (req, file, cb) => {
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
cb(null, uniqueSuffix + path.extname(file.originalname));
}
}),
fileFilter,
limits: {
fileSize: 5 * 1024 * 1024, // 5MB
files: 5
}
});
module.exports = {
schemas,
validate,
securityMiddleware,
upload
};
> Set up automated dependency vulnerability scanning:
> - Check for known CVEs
> - Identify outdated packages
> - Suggest secure alternatives
> - Create update strategy
security-scan.js
const { execSync } = require('child_process');
const fs = require('fs').promises;
class SecurityScanner {
async scanDependencies() {
console.log('🔍 Scanning dependencies for vulnerabilities...\n');
const scanners = [
this.npmAudit.bind(this),
this.snykScan.bind(this),
this.oswScan.bind(this),
this.retireScan.bind(this)
];
const results = await Promise.allSettled(scanners.map(scan => scan()));
return this.consolidateResults(results);
}
async npmAudit() {
try {
const output = execSync('npm audit --json', { encoding: 'utf8' });
const audit = JSON.parse(output);
return {
scanner: 'npm-audit',
vulnerabilities: audit.vulnerabilities,
summary: audit.metadata.vulnerabilities
};
} catch (error) {
// npm audit exits with error code if vulnerabilities found
const audit = JSON.parse(error.stdout);
return {
scanner: 'npm-audit',
vulnerabilities: audit.vulnerabilities,
summary: audit.metadata.vulnerabilities
};
}
}
async snykScan() {
try {
const output = execSync('snyk test --json', { encoding: 'utf8' });
const result = JSON.parse(output);
return {
scanner: 'snyk',
vulnerabilities: result.vulnerabilities,
summary: {
total: result.vulnerabilities.length,
high: result.vulnerabilities.filter(v => v.severity === 'high').length,
medium: result.vulnerabilities.filter(v => v.severity === 'medium').length,
low: result.vulnerabilities.filter(v => v.severity === 'low').length
}
};
} catch (error) {
console.warn('Snyk scan failed:', error.message);
return null;
}
}
async oswScan() {
try {
// OSV Scanner for comprehensive vulnerability database
execSync('osv-scanner --json -o osv-results.json .', { encoding: 'utf8' });
const results = await fs.readFile('osv-results.json', 'utf8');
return {
scanner: 'osv',
results: JSON.parse(results)
};
} catch (error) {
console.warn('OSV scan failed:', error.message);
return null;
}
}
async retireScan() {
try {
// RetireJS for JavaScript-specific vulnerabilities
const output = execSync('retire --outputformat json', { encoding: 'utf8' });
return {
scanner: 'retirejs',
results: JSON.parse(output)
};
} catch (error) {
console.warn('RetireJS scan failed:', error.message);
return null;
}
}
consolidateResults(results) {
const consolidated = {
timestamp: new Date().toISOString(),
scanners: [],
totalVulnerabilities: 0,
criticalFindings: [],
recommendations: []
};
results.forEach(result => {
if (result.status === 'fulfilled' && result.value) {
consolidated.scanners.push(result.value.scanner);
// Extract critical findings
if (result.value.vulnerabilities) {
Object.entries(result.value.vulnerabilities).forEach(([pkg, vuln]) => {
if (vuln.severity === 'high' || vuln.severity === 'critical') {
consolidated.criticalFindings.push({
package: pkg,
severity: vuln.severity,
title: vuln.title,
recommendation: vuln.fixAvailable
});
}
});
}
}
});
// Generate recommendations
if (consolidated.criticalFindings.length > 0) {
consolidated.recommendations.push(
'Immediate action required: Update critical dependencies'
);
}
return consolidated;
}
}
// Automated fix generation
class SecurityFixer {
async generateFixes(scanResults) {
const fixes = [];
for (const finding of scanResults.criticalFindings) {
const fix = await this.generateFix(finding);
if (fix) fixes.push(fix);
}
return fixes;
}
async generateFix(finding) {
// Check if automatic fix is available
if (finding.recommendation?.fixAvailable) {
return {
package: finding.package,
command: `npm update ${finding.package}`,
description: `Update ${finding.package} to fix ${finding.title}`
};
}
// For more complex fixes, generate migration guide
return {
package: finding.package,
manual: true,
steps: [
`Review breaking changes for ${finding.package}`,
`Update code to handle API changes`,
`Test thoroughly before deploying`
]
};
}
}
// CI/CD Integration
module.exports = {
SecurityScanner,
SecurityFixer,
// GitHub Action workflow
githubAction: `
name: Security Scan
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
schedule:
- cron: '0 0 * * *' # Daily scan
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Security Scan
run: |
npm ci
npm audit
- name: Upload results
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: security-results.sarif
`
};
> Implement secure coding patterns for our application:
> - Secure session management
> - CSRF protection
> - Security headers
> - Secure cookie handling
> - API security
security-patterns.js
const session = require('express-session');
const MongoStore = require('connect-mongo');
const csrf = require('csurf');
const crypto = require('crypto');
// Secure session configuration
const sessionConfig = {
secret: process.env.SESSION_SECRET || crypto.randomBytes(64).toString('hex'),
name: 'sessionId', // Don't use default 'connect.sid'
resave: false,
saveUninitialized: false,
store: MongoStore.create({
mongoUrl: process.env.MONGODB_URI,
touchAfter: 24 * 3600, // Lazy session update
crypto: {
secret: process.env.SESSION_STORE_SECRET
}
}),
cookie: {
secure: process.env.NODE_ENV === 'production', // HTTPS only
httpOnly: true, // No JS access
maxAge: 1000 * 60 * 60 * 24, // 24 hours
sameSite: 'strict' // CSRF protection
}
};
// CSRF Protection
const csrfProtection = csrf({
cookie: {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict'
}
});
// API Security Middleware
class ApiSecurity {
static apiKey() {
return async (req, res, next) => {
const apiKey = req.headers['x-api-key'];
if (!apiKey) {
return res.status(401).json({ error: 'API key required' });
}
// Timing-safe comparison
const validKey = await ApiKey.findOne({
key: crypto.createHash('sha256').update(apiKey).digest('hex'),
active: true
});
if (!validKey) {
// Rate limit failed attempts
await this.recordFailedAttempt(req.ip);
return res.status(401).json({ error: 'Invalid API key' });
}
// Check rate limits for this key
if (await this.isRateLimited(validKey)) {
return res.status(429).json({ error: 'Rate limit exceeded' });
}
req.apiKey = validKey;
next();
};
}
static async recordFailedAttempt(ip) {
const key = `failed_auth:${ip}`;
const attempts = await redis.incr(key);
if (attempts === 1) {
await redis.expire(key, 3600); // 1 hour window
}
if (attempts > 10) {
// Block IP temporarily
await redis.setex(`blocked:${ip}`, 3600, '1');
}
}
static async isRateLimited(apiKey) {
const key = `rate:${apiKey._id}`;
const requests = await redis.incr(key);
if (requests === 1) {
await redis.expire(key, 60); // 1 minute window
}
return requests > apiKey.rateLimit;
}
}
// Secure Headers Middleware
const secureHeaders = (req, res, next) => {
// Remove fingerprinting headers
res.removeHeader('X-Powered-By');
// Security headers
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('X-XSS-Protection', '1; mode=block');
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
res.setHeader('Permissions-Policy', 'geolocation=(), microphone=(), camera=()');
// HSTS
if (req.secure) {
res.setHeader(
'Strict-Transport-Security',
'max-age=31536000; includeSubDomains; preload'
);
}
next();
};
// Secure Error Handler
const secureErrorHandler = (err, req, res, next) => {
// Log error details server-side
console.error('Error:', {
message: err.message,
stack: err.stack,
url: req.url,
method: req.method,
ip: req.ip,
user: req.user?.id
});
// Don't leak error details to client
const isDev = process.env.NODE_ENV === 'development';
res.status(err.status || 500).json({
error: {
message: isDev ? err.message : 'Internal server error',
code: err.code || 'SERVER_ERROR',
...(isDev && { stack: err.stack })
}
});
};
// Content Security Policy Builder
class CSPBuilder {
constructor() {
this.directives = {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", 'data:', 'https:'],
connectSrc: ["'self'"],
fontSrc: ["'self'"],
objectSrc: ["'none'"],
mediaSrc: ["'self'"],
frameSrc: ["'none'"],
baseUri: ["'self'"],
formAction: ["'self'"],
frameAncestors: ["'none'"],
upgradeInsecureRequests: []
};
}
addNonce(req, res, next) {
res.locals.nonce = crypto.randomBytes(16).toString('base64');
this.directives.scriptSrc.push(`'nonce-${res.locals.nonce}'`);
next();
}
build() {
return Object.entries(this.directives)
.map(([key, values]) => {
const directive = key.replace(/([A-Z])/g, '-$1').toLowerCase();
return `${directive} ${values.join(' ')}`;
})
.join('; ');
}
}
module.exports = {
sessionConfig,
csrfProtection,
ApiSecurity,
secureHeaders,
secureErrorHandler,
CSPBuilder
};
> Implement OWASP security standards:
> - OWASP Top 10 protection
> - Security logging
> - Audit trails
> - Compliance reporting
owasp-compliance.js
const winston = require('winston');
const { ElasticsearchTransport } = require('winston-elasticsearch');
// Security Event Logger
class SecurityLogger {
constructor() {
this.logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
defaultMeta: {
service: 'security',
environment: process.env.NODE_ENV
},
transports: [
new winston.transports.File({
filename: 'security.log',
level: 'warning'
}),
new ElasticsearchTransport({
level: 'info',
clientOpts: {
node: process.env.ELASTICSEARCH_URL,
auth: {
username: process.env.ELASTIC_USER,
password: process.env.ELASTIC_PASSWORD
}
},
index: 'security-logs'
})
]
});
}
logSecurityEvent(event) {
const logEntry = {
timestamp: new Date().toISOString(),
eventType: event.type,
severity: event.severity,
userId: event.userId,
ip: event.ip,
userAgent: event.userAgent,
resource: event.resource,
action: event.action,
result: event.result,
details: event.details
};
this.logger.log(event.severity || 'info', logEntry);
// Alert on critical events
if (event.severity === 'critical') {
this.sendAlert(logEntry);
}
}
async sendAlert(event) {
// Send to security team
await sendEmail({
to: process.env.SECURITY_TEAM_EMAIL,
subject: `Critical Security Event: ${event.eventType}`,
template: 'security-alert',
data: event
});
// Send to Slack
await sendSlackNotification({
channel: '#security-alerts',
text: `🚨 Critical Security Event: ${event.eventType}`,
attachments: [{
color: 'danger',
fields: [
{ title: 'User', value: event.userId, short: true },
{ title: 'IP', value: event.ip, short: true },
{ title: 'Resource', value: event.resource },
{ title: 'Details', value: event.details }
]
}]
});
}
}
// Audit Trail Implementation
class AuditTrail {
static middleware() {
return async (req, res, next) => {
const auditEntry = {
requestId: req.id,
timestamp: new Date(),
user: req.user?.id || 'anonymous',
method: req.method,
path: req.path,
query: req.query,
ip: req.ip,
userAgent: req.get('user-agent')
};
// Capture response
const originalSend = res.send;
res.send = function(data) {
auditEntry.statusCode = res.statusCode;
auditEntry.responseTime = Date.now() - auditEntry.timestamp;
// Log sensitive operations
if (AuditTrail.isSensitiveOperation(req)) {
auditEntry.body = req.body;
auditEntry.response = data;
AuditLog.create(auditEntry);
}
originalSend.call(this, data);
};
next();
};
}
static isSensitiveOperation(req) {
const sensitivePaths = [
'/api/users',
'/api/auth',
'/api/admin',
'/api/payments',
'/api/settings'
];
const sensitiveMethods = ['POST', 'PUT', 'DELETE', 'PATCH'];
return sensitiveMethods.includes(req.method) &&
sensitivePaths.some(path => req.path.startsWith(path));
}
}
// Compliance Reporting
class ComplianceReporter {
async generateOWASPReport() {
const report = {
generatedAt: new Date().toISOString(),
standard: 'OWASP Top 10 2021',
controls: []
};
// A1: Broken Access Control
report.controls.push({
id: 'A01:2021',
name: 'Broken Access Control',
status: await this.checkAccessControl(),
evidence: [
'Role-based access control implemented',
'Authorization middleware on all sensitive routes',
'Audit logging for permission changes'
]
});
// A2: Cryptographic Failures
report.controls.push({
id: 'A02:2021',
name: 'Cryptographic Failures',
status: await this.checkCryptography(),
evidence: [
'Strong encryption algorithms (AES-256)',
'Secure key management',
'TLS 1.3 enforced'
]
});
// A3: Injection
report.controls.push({
id: 'A03:2021',
name: 'Injection',
status: await this.checkInjectionPrevention(),
evidence: [
'Parameterized queries',
'Input validation',
'Output encoding'
]
});
// Continue for all OWASP Top 10...
return report;
}
async checkAccessControl() {
// Run automated tests
const tests = [
this.testAuthorizationBypass(),
this.testPrivilegeEscalation(),
this.testJWTValidation()
];
const results = await Promise.all(tests);
return results.every(r => r.passed) ? 'PASS' : 'FAIL';
}
async generateCompliancePackage() {
const reports = await Promise.all([
this.generateOWASPReport(),
this.generatePCIDSSReport(),
this.generateSOC2Report()
]);
return {
timestamp: new Date().toISOString(),
reports,
attestation: this.generateAttestation(reports)
};
}
}
module.exports = {
SecurityLogger,
AuditTrail,
ComplianceReporter
};
> Create comprehensive security test suite:
> - Penetration testing
> - Fuzzing
> - Security regression tests
> - Compliance validation
security-tests.spec.js
const request = require('supertest');
const app = require('../app');
const { SecurityTester } = require('./security-tester');
describe('Security Test Suite', () => {
const tester = new SecurityTester(app);
describe('Authentication Security', () => {
test('Should prevent brute force attacks', async () => {
const attempts = Array(10).fill().map((_, i) =>
request(app)
.post('/api/auth/login')
.send({
email: 'test@example.com',
password: `wrong${i}`
})
);
const results = await Promise.all(attempts);
// Should block after threshold
const blocked = results.filter(r => r.status === 429);
expect(blocked.length).toBeGreaterThan(0);
});
test('Should prevent timing attacks on login', async () => {
const timings = [];
// Test with valid and invalid users
for (const email of ['valid@example.com', 'invalid@example.com']) {
const start = process.hrtime.bigint();
await request(app)
.post('/api/auth/login')
.send({ email, password: 'password123' });
const end = process.hrtime.bigint();
timings.push(Number(end - start) / 1000000); // Convert to ms
}
// Timing difference should be minimal (< 50ms)
const difference = Math.abs(timings[0] - timings[1]);
expect(difference).toBeLessThan(50);
});
test('Should enforce strong passwords', async () => {
const weakPasswords = [
'password',
'12345678',
'qwerty123',
'admin123',
'Password1' // No special char
];
for (const password of weakPasswords) {
const response = await request(app)
.post('/api/auth/register')
.send({
email: 'test@example.com',
password,
username: 'testuser'
});
expect(response.status).toBe(400);
expect(response.body.errors).toBeDefined();
}
});
});
describe('Input Validation Security', () => {
test('Should prevent SQL injection', async () => {
const sqlInjectionPayloads = [
"1' OR '1'='1",
"1'; DROP TABLE users; --",
"1' UNION SELECT * FROM users--",
"admin'--",
"' OR 1=1--"
];
for (const payload of sqlInjectionPayloads) {
const response = await request(app)
.get(`/api/users/${payload}`)
.set('Authorization', `Bearer ${validToken}`);
expect(response.status).not.toBe(200);
expect(response.body).not.toContain('password');
}
});
test('Should prevent XSS attacks', async () => {
const xssPayloads = [
'<script>alert("XSS")</script>',
'<img src=x onerror=alert("XSS")>',
'<svg onload=alert("XSS")>',
'javascript:alert("XSS")',
'<iframe src="javascript:alert(\'XSS\')">',
];
for (const payload of xssPayloads) {
const response = await request(app)
.post('/api/comments')
.set('Authorization', `Bearer ${validToken}`)
.send({
content: payload
});
// Check response doesn't contain unescaped payload
expect(response.text).not.toContain(payload);
// Verify stored content is sanitized
const comment = await Comment.findOne().sort({ _id: -1 });
expect(comment.content).not.toContain('<script>');
expect(comment.content).not.toContain('javascript:');
}
});
test('Should prevent NoSQL injection', async () => {
const nosqlPayloads = [
{ $ne: null },
{ $gt: '' },
{ $regex: '.*' },
{ $where: 'this.password.length > 0' }
];
for (const payload of nosqlPayloads) {
const response = await request(app)
.post('/api/auth/login')
.send({
email: payload,
password: 'password'
});
expect(response.status).toBe(400);
}
});
});
describe('Security Headers', () => {
test('Should set all security headers', async () => {
const response = await request(app).get('/');
expect(response.headers['x-content-type-options']).toBe('nosniff');
expect(response.headers['x-frame-options']).toBe('DENY');
expect(response.headers['x-xss-protection']).toBe('1; mode=block');
expect(response.headers['strict-transport-security']).toBeDefined();
expect(response.headers['content-security-policy']).toBeDefined();
expect(response.headers['x-powered-by']).toBeUndefined();
});
});
describe('API Security', () => {
test('Should enforce rate limiting', async () => {
const requests = Array(150).fill().map(() =>
request(app).get('/api/data')
);
const responses = await Promise.all(requests);
const rateLimited = responses.filter(r => r.status === 429);
expect(rateLimited.length).toBeGreaterThan(0);
});
test('Should validate API keys securely', async () => {
// Test missing API key
const response1 = await request(app)
.get('/api/protected')
.expect(401);
// Test invalid API key
const response2 = await request(app)
.get('/api/protected')
.set('X-API-Key', 'invalid-key')
.expect(401);
// Test timing attack resistance
const validKeyTime = await measureApiKeyValidation('valid-key');
const invalidKeyTime = await measureApiKeyValidation('invalid-key');
const timingDifference = Math.abs(validKeyTime - invalidKeyTime);
expect(timingDifference).toBeLessThan(5); // Less than 5ms difference
});
});
describe('Fuzzing Tests', () => {
test('Should handle malformed input gracefully', async () => {
const fuzzInputs = [
null,
undefined,
'',
' ',
'\n\r\t',
'0'.repeat(10000),
'{"a":'.repeat(1000) + '}',
Buffer.from([0xFF, 0xFE, 0xFD]),
'\x00\x01\x02',
''
];
for (const input of fuzzInputs) {
const response = await request(app)
.post('/api/data')
.send({ data: input })
.set('Authorization', `Bearer ${validToken}`);
// Should not crash
expect([400, 422]).toContain(response.status);
}
});
});
});
// Security Testing Utilities
class SecurityTester {
constructor(app) {
this.app = app;
}
async runPenetrationTest() {
const tests = [
this.testAuthBypass(),
this.testPrivilegeEscalation(),
this.testDataExposure(),
this.testCSRF(),
this.testXXE(),
this.testSSRF()
];
const results = await Promise.all(tests);
return this.generatePenTestReport(results);
}
async testCSRF() {
// Test CSRF protection
const response = await request(this.app)
.post('/api/user/delete')
.set('Cookie', 'sessionId=valid-session')
.send({ userId: '123' });
// Should fail without CSRF token
expect(response.status).toBe(403);
// Get CSRF token
const tokenResponse = await request(this.app)
.get('/api/csrf-token')
.set('Cookie', 'sessionId=valid-session');
const csrfToken = tokenResponse.body.token;
// Should succeed with token
const validResponse = await request(this.app)
.post('/api/user/delete')
.set('Cookie', 'sessionId=valid-session')
.set('X-CSRF-Token', csrfToken)
.send({ userId: '123' });
expect(validResponse.status).toBe(200);
}
}
module.exports = { SecurityTester };
> Implement real-time security monitoring:
> - Intrusion detection
> - Anomaly detection
> - Attack pattern recognition
> - Automated response
threat-detection.js
const EventEmitter = require('events');
class ThreatDetector extends EventEmitter {
constructor() {
super();
this.patterns = new Map();
this.alerts = [];
this.initializePatterns();
}
initializePatterns() {
// SQL Injection patterns
this.patterns.set('sql_injection', [
/(\b(union|select|insert|update|delete|drop|create)\b.*\b(from|where|table)\b)/i,
/('|(\')|"|(\"))\s*(or|and)\s*('|(\')|"|(\"))?(\d|[a-z])/i,
/\b(exec|execute)\s*\(/i
]);
// XSS patterns
this.patterns.set('xss', [
/<script[^>]*>.*?<\/script>/gi,
/on\w+\s*=\s*["'][^"']+["']/gi,
/javascript\s*:/gi
]);
// Path traversal patterns
this.patterns.set('path_traversal', [
/\.\.(\/|\\)/g,
/%2e%2e(\/|\\)/gi,
/\.\.(;|%3b|%09|%00)/gi
]);
}
async analyze(request) {
const threats = [];
// Check all input sources
const inputs = [
...Object.values(request.params || {}),
...Object.values(request.query || {}),
...this.flattenObject(request.body || {}),
request.path,
...Object.values(request.headers || {})
];
for (const input of inputs) {
if (typeof input !== 'string') continue;
for (const [threatType, patterns] of this.patterns) {
for (const pattern of patterns) {
if (pattern.test(input)) {
threats.push({
type: threatType,
input: input.substring(0, 100),
pattern: pattern.toString(),
timestamp: new Date(),
request: {
ip: request.ip,
path: request.path,
method: request.method
}
});
}
}
}
}
if (threats.length > 0) {
this.handleThreats(threats);
}
return threats;
}
handleThreats(threats) {
threats.forEach(threat => {
this.emit('threat', threat);
// Log threat
logger.security.warn('Threat detected', threat);
// Update threat intelligence
this.updateThreatIntelligence(threat);
// Trigger automated response
if (this.shouldAutoRespond(threat)) {
this.autoRespond(threat);
}
});
}
async autoRespond(threat) {
switch (threat.type) {
case 'sql_injection':
case 'xss':
// Block IP temporarily
await this.blockIP(threat.request.ip, 3600); // 1 hour
break;
case 'path_traversal':
// Alert security team
await this.alertSecurityTeam(threat);
break;
}
}
flattenObject(obj, prefix = '') {
const flattened = [];
for (const [key, value] of Object.entries(obj)) {
if (typeof value === 'object' && value !== null) {
flattened.push(...this.flattenObject(value, `${prefix}${key}.`));
} else {
flattened.push(String(value));
}
}
return flattened;
}
}
// Anomaly Detection
class AnomalyDetector {
constructor() {
this.baselines = new Map();
this.anomalies = [];
}
async detectAnomalies(metrics) {
const anomalies = [];
// Request rate anomaly
const requestRate = metrics.requestsPerMinute;
const baseline = await this.getBaseline('request_rate');
if (requestRate > baseline.mean + (3 * baseline.stdDev)) {
anomalies.push({
type: 'high_request_rate',
value: requestRate,
baseline: baseline.mean,
severity: 'medium'
});
}
// Failed login anomaly
const failedLogins = metrics.failedLoginsPerHour;
const loginBaseline = await this.getBaseline('failed_logins');
if (failedLogins > loginBaseline.mean + (2 * loginBaseline.stdDev)) {
anomalies.push({
type: 'suspicious_login_activity',
value: failedLogins,
baseline: loginBaseline.mean,
severity: 'high'
});
}
// Geographic anomaly
const unusualLocations = await this.detectGeographicAnomalies(metrics.accessByCountry);
anomalies.push(...unusualLocations);
return anomalies;
}
async detectGeographicAnomalies(accessByCountry) {
const anomalies = [];
const knownCountries = await this.getKnownCountries();
for (const [country, count] of Object.entries(accessByCountry)) {
if (!knownCountries.includes(country) && count > 10) {
anomalies.push({
type: 'unusual_geographic_access',
country,
accessCount: count,
severity: 'medium'
});
}
}
return anomalies;
}
}
module.exports = {
ThreatDetector,
AnomalyDetector
};
> Create incident response system:
> - Automated containment
> - Evidence collection
> - Notification system
> - Recovery procedures
incident-response.js
class IncidentResponseSystem {
async handleIncident(incident) {
const response = {
incidentId: this.generateIncidentId(),
timestamp: new Date(),
type: incident.type,
severity: incident.severity,
actions: []
};
// Phase 1: Containment
const containment = await this.contain(incident);
response.actions.push(...containment);
// Phase 2: Evidence Collection
const evidence = await this.collectEvidence(incident);
response.evidence = evidence;
// Phase 3: Notification
await this.notify(incident, response);
// Phase 4: Recovery
if (incident.severity === 'critical') {
const recovery = await this.recover(incident);
response.actions.push(...recovery);
}
// Phase 5: Documentation
await this.document(response);
return response;
}
async contain(incident) {
const actions = [];
switch (incident.type) {
case 'data_breach':
// Revoke compromised credentials
actions.push(await this.revokeCredentials(incident.affectedUsers));
// Isolate affected systems
actions.push(await this.isolateSystems(incident.affectedSystems));
// Block suspicious IPs
actions.push(await this.blockIPs(incident.suspiciousIPs));
break;
case 'ddos_attack':
// Enable DDoS protection
actions.push(await this.enableDDoSProtection());
// Scale infrastructure
actions.push(await this.scaleInfrastructure());
break;
case 'malware_detected':
// Quarantine affected files
actions.push(await this.quarantineFiles(incident.files));
// Scan all systems
actions.push(await this.fullSystemScan());
break;
}
return actions;
}
async collectEvidence(incident) {
return {
logs: await this.collectLogs(incident.timeRange),
networkCapture: await this.captureNetwork(incident.affectedSystems),
memoryDump: await this.dumpMemory(incident.affectedSystems),
fileSnapshots: await this.snapshotFiles(incident.suspiciousFiles),
databaseAudit: await this.auditDatabase(incident.timeRange)
};
}
async notify(incident, response) {
const notifications = [];
// Internal notifications
if (incident.severity === 'critical') {
notifications.push(
this.notifyCISO(incident, response),
this.notifySecurityTeam(incident, response),
this.notifyLegal(incident, response)
);
}
// External notifications (if required)
if (incident.type === 'data_breach' && incident.affectedUsers.length > 0) {
notifications.push(
this.notifyAffectedUsers(incident),
this.notifyRegulators(incident)
);
}
await Promise.all(notifications);
}
async recover(incident) {
const recovery = [];
// Restore from backups if needed
if (incident.dataCorrupted) {
recovery.push(await this.restoreFromBackup(incident.affectedData));
}
// Reset security measures
recovery.push(
await this.rotateSecrets(),
await this.updateSecurityRules(),
await this.patchVulnerabilities(incident.exploitedVulnerabilities)
);
return recovery;
}
generateIncidentId() {
return `INC-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}
}
// Incident Response Runbook
const runbooks = {
data_breach: {
steps: [
'Identify scope of breach',
'Contain affected systems',
'Preserve evidence',
'Assess data exposed',
'Notify stakeholders',
'Begin forensic analysis',
'Implement remediation',
'Document lessons learned'
],
contacts: {
ciso: 'ciso@company.com',
legal: 'legal@company.com',
pr: 'pr@company.com'
},
timeline: {
initial_response: '15 minutes',
containment: '1 hour',
notification: '4 hours',
full_resolution: '72 hours'
}
}
};
module.exports = {
IncidentResponseSystem,
runbooks
};

You’ve learned how to leverage Claude Code for comprehensive security scanning and protection. The key is treating security as a continuous process, not a one-time check. Build security into every line of code, every deployment, every feature.

Remember: Security is everyone’s responsibility. Use Claude Code to make security accessible and automated, but always maintain vigilance. The best security comes from defense in depth - multiple layers working together to protect your application and users.