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.
The Security Revolution
Section titled “The Security Revolution”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.
Traditional vs AI-Powered Security
Section titled “Traditional vs AI-Powered Security”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
Day 1: Secure Foundation> Analyze security requirements> Set up security framework> Implement secure defaults
Continuous: Proactive Security> Scan code as written> Fix vulnerabilities immediately> Update dependencies automatically
Real-time: Threat Prevention> Detect suspicious patterns> Block attack vectors> Monitor for anomalies
Result: Security Confidence> Sleep well at night> Pass audits easily> Build user trust
Vulnerability Detection
Section titled “Vulnerability Detection”Comprehensive Security Analysis
Section titled “Comprehensive Security Analysis”> 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:
-
SQL Injection Detection
// VULNERABLE CODE FOUNDapp.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 REPLACEMENTapp.get('/user/:id', async (req, res) => {const userId = req.params.id;// ✅ Input validationif (!/^\d+$/.test(userId)) {return res.status(400).json({ error: 'Invalid user ID' });}// ✅ Parameterized queryconst query = 'SELECT * FROM users WHERE id = $1';const result = await db.query(query, [userId]);// ✅ Don't expose sensitive fieldsconst { password_hash, ...safeUser } = result.rows[0] || {};res.json(safeUser);}); -
Cross-Site Scripting (XSS) Prevention
// VULNERABLE CODE FOUNDapp.post('/comment', (req, res) => {const comment = req.body.comment;// ❌ Direct HTML insertion - XSS risk!const html = `<div class="comment">${comment}</div>`;saveCommentHTML(html);});// SECURE REPLACEMENTconst DOMPurify = require('isomorphic-dompurify');const { JSDOM } = require('jsdom');app.post('/comment', (req, res) => {const comment = req.body.comment;// ✅ Sanitize HTML inputconst 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 Policyres.setHeader('Content-Security-Policy',"default-src 'self'; script-src 'self' 'nonce-${nonce}'");const html = `<div class="comment">${clean}</div>`;saveCommentHTML(html);}); -
Authentication & Authorization
// VULNERABLE CODE FOUNDapp.post('/admin/users', (req, res) => {// ❌ No authentication check!updateUsers(req.body);res.json({ success: true });});// SECURE REPLACEMENTconst jwt = require('jsonwebtoken');const bcrypt = require('bcrypt');// Authentication middlewareconst 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 middlewareconst 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 & authzapp.post('/admin/users',authenticate,authorize('admin', 'superadmin'),async (req, res) => {// Additional validationconst { error } = validateUserUpdate(req.body);if (error) {return res.status(400).json({ error: error.details[0].message });}await updateUsers(req.body);// Audit loggingawait auditLog({action: 'UPDATE_USERS',userId: req.user.id,changes: req.body,ip: req.ip});res.json({ success: true });}); -
Cryptographic Security
// VULNERABLE CODE FOUNDconst 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 algorithmconst key = '1234567890123456';const cipher = crypto.createCipher('aes-128-ecb', key);return cipher.update(data, 'utf8', 'hex') + cipher.final('hex');}// SECURE REPLACEMENTconst bcrypt = require('bcrypt');const argon2 = require('argon2');// ✅ Strong password hashingasync 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 encryptionasync 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')};}
Input Validation & Sanitization
Section titled “Input Validation & Sanitization”> Implement comprehensive input validation:> - Request body validation> - Query parameter sanitization> - File upload security> - Rate limiting> - Request size limits
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 validationconst 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 middlewareconst 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 stackconst 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 securityconst 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};
Dependency Scanning
Section titled “Dependency Scanning”Automated Vulnerability Scanning
Section titled “Automated Vulnerability Scanning”> Set up automated dependency vulnerability scanning:> - Check for known CVEs> - Identify outdated packages> - Suggest secure alternatives> - Create update strategy
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 generationclass 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 Integrationmodule.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 `};
Secure Coding Patterns
Section titled “Secure Coding Patterns”Security Design Patterns
Section titled “Security Design Patterns”> Implement secure coding patterns for our application:> - Secure session management> - CSRF protection> - Security headers> - Secure cookie handling> - API security
const session = require('express-session');const MongoStore = require('connect-mongo');const csrf = require('csurf');const crypto = require('crypto');
// Secure session configurationconst 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 Protectionconst csrfProtection = csrf({ cookie: { httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'strict' }});
// API Security Middlewareclass 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 Middlewareconst 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 Handlerconst 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 Builderclass 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};
Compliance & Standards
Section titled “Compliance & Standards”OWASP Compliance
Section titled “OWASP Compliance”> Implement OWASP security standards:> - OWASP Top 10 protection> - Security logging> - Audit trails> - Compliance reporting
const winston = require('winston');const { ElasticsearchTransport } = require('winston-elasticsearch');
// Security Event Loggerclass 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 Implementationclass 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 Reportingclass 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};
Automated Security Testing
Section titled “Automated Security Testing”Security Test Suite
Section titled “Security Test Suite”> Create comprehensive security test suite:> - Penetration testing> - Fuzzing> - Security regression tests> - Compliance validation
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 Utilitiesclass 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 };
Security Monitoring
Section titled “Security Monitoring”Real-time Threat Detection
Section titled “Real-time Threat Detection”> Implement real-time security monitoring:> - Intrusion detection> - Anomaly detection> - Attack pattern recognition> - Automated response
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 Detectionclass 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};
Incident Response
Section titled “Incident Response”Automated Incident Response
Section titled “Automated Incident Response”> Create incident response system:> - Automated containment> - Evidence collection> - Notification system> - Recovery procedures
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 Runbookconst 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};
Related Lessons
Section titled “Related Lessons”Next Steps
Section titled “Next Steps”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.