--- name: Secure Code Guardian description: Expert in writing secure code and preventing vulnerabilities. Use when implementing security features, writing authentication/authorization, handling sensitive data, preventing common vulnerabilities (OWASP Top 10), or when the user mentions secure coding, security, authentication, authorization, or vulnerabilities. --- # Secure Code Guardian Expert in writing secure code and implementing security best practices to prevent vulnerabilities. ## Instructions ### Core Workflow 1. **Understand security requirements** - Authentication needs - Authorization requirements - Data sensitivity levels - Compliance requirements (GDPR, HIPAA, etc.) - Threat model 2. **Implement security controls** - Input validation - Output encoding - Authentication mechanisms - Authorization checks - Encryption (at rest and in transit) - Secure session management 3. **Prevent OWASP Top 10** - Injection attacks - Broken authentication - Sensitive data exposure - XML External Entities (XXE) - Broken access control - Security misconfiguration - Cross-Site Scripting (XSS) - Insecure deserialization - Using components with known vulnerabilities - Insufficient logging & monitoring 4. **Secure development practices** - Principle of least privilege - Defense in depth - Fail securely - Keep security simple - Don't trust user input ### OWASP Top 10 Prevention #### 1. SQL Injection Prevention ```typescript // ❌ Vulnerable to SQL injection const query = `SELECT * FROM users WHERE email = '${userEmail}'`; db.query(query); // ✅ Use parameterized queries const query = 'SELECT * FROM users WHERE email = $1'; db.query(query, [userEmail]); // ✅ Or use an ORM const user = await User.findOne({ where: { email: userEmail } }); ``` #### 2. Authentication Best Practices ```typescript import bcrypt from 'bcrypt'; // Password hashing async function hashPassword(password: string): Promise { const saltRounds = 12; // Minimum 10 return await bcrypt.hash(password, saltRounds); } // Password verification async function verifyPassword(password: string, hash: string): Promise { return await bcrypt.compare(password, hash); } // Strong password requirements function isStrongPassword(password: string): boolean { const minLength = 12; const hasUpperCase = /[A-Z]/.test(password); const hasLowerCase = /[a-z]/.test(password); const hasNumbers = /\d/.test(password); const hasSpecialChar = /[!@#$%^&*]/.test(password); return password.length >= minLength && hasUpperCase && hasLowerCase && hasNumbers && hasSpecialChar; } // Rate limiting for login attempts const loginAttempts = new Map(); function checkRateLimit(ip: string): boolean { const now = Date.now(); const attempts = loginAttempts.get(ip); if (!attempts || now > attempts.resetTime) { loginAttempts.set(ip, { count: 1, resetTime: now + 15 * 60 * 1000 }); // 15 min return true; } if (attempts.count >= 5) { return false; // Too many attempts } attempts.count++; return true; } ``` #### 3. XSS Prevention ```typescript // ❌ Vulnerable to XSS element.innerHTML = userInput; // ✅ Use textContent or sanitize element.textContent = userInput; // Or use a sanitization library import DOMPurify from 'dompurify'; element.innerHTML = DOMPurify.sanitize(userInput); // React automatically escapes
{userInput}
// Safe // Backend: Set Content-Security-Policy header app.use((req, res, next) => { res.setHeader( 'Content-Security-Policy', "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'" ); next(); }); ``` #### 4. CSRF Prevention ```typescript // Use CSRF tokens import csrf from 'csurf'; app.use(csrf({ cookie: true })); app.get('/form', (req, res) => { res.render('form', { csrfToken: req.csrfToken() }); }); // In form // // For APIs: Use custom headers // X-CSRF-Token: ``` #### 5. Authorization Best Practices ```typescript // Role-Based Access Control (RBAC) enum Role { USER = 'user', ADMIN = 'admin', MODERATOR = 'moderator', } interface User { id: string; role: Role; } function requireRole(allowedRoles: Role[]) { return (req, res, next) => { const user: User = req.user; if (!user) { return res.status(401).json({ error: 'Not authenticated' }); } if (!allowedRoles.includes(user.role)) { return res.status(403).json({ error: 'Insufficient permissions' }); } next(); }; } // Usage app.delete('/users/:id', requireRole([Role.ADMIN]), deleteUser); // Resource-based authorization async function canAccessResource(userId: string, resourceId: string): Promise { const resource = await Resource.findById(resourceId); return resource.ownerId === userId || await isAdmin(userId); } app.get('/resource/:id', async (req, res) => { if (!await canAccessResource(req.user.id, req.params.id)) { return res.status(403).json({ error: 'Access denied' }); } // Return resource }); ``` #### 6. Sensitive Data Handling ```typescript // Environment variables for secrets const JWT_SECRET = process.env.JWT_SECRET; const DB_PASSWORD = process.env.DB_PASSWORD; // Never log sensitive data // ❌ Don't do this console.log('User:', user); // May contain password hash // ✅ Log safely console.log('User:', { id: user.id, email: user.email }); // Encrypt sensitive data at rest import crypto from 'crypto'; const algorithm = 'aes-256-gcm'; const key = Buffer.from(process.env.ENCRYPTION_KEY, 'hex'); function encrypt(text: string): { encrypted: string; iv: string; tag: string } { const iv = crypto.randomBytes(16); const cipher = crypto.createCipheriv(algorithm, key, iv); let encrypted = cipher.update(text, 'utf8', 'hex'); encrypted += cipher.final('hex'); return { encrypted, iv: iv.toString('hex'), tag: cipher.getAuthTag().toString('hex'), }; } function decrypt(encrypted: string, iv: string, tag: string): string { const decipher = crypto.createDecipheriv( algorithm, key, Buffer.from(iv, 'hex') ); decipher.setAuthTag(Buffer.from(tag, 'hex')); let decrypted = decipher.update(encrypted, 'hex', 'utf8'); decrypted += decipher.final('utf8'); return decrypted; } ``` #### 7. Security Headers ```typescript import helmet from 'helmet'; app.use(helmet()); // Sets various security headers // Or manually: app.use((req, res, next) => { res.setHeader('X-Content-Type-Options', 'nosniff'); res.setHeader('X-Frame-Options', 'DENY'); res.setHeader('X-XSS-Protection', '1; mode=block'); res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains'); next(); }); ``` ### Input Validation ```typescript import { z } from 'zod'; // Define schema const userSchema = z.object({ email: z.string().email(), password: z.string().min(12), age: z.number().int().positive().max(150), website: z.string().url().optional(), }); // Validate input function validateUser(data: unknown) { try { return userSchema.parse(data); } catch (error) { if (error instanceof z.ZodError) { throw new ValidationError(error.errors); } throw error; } } // Sanitize strings function sanitizeString(input: string): string { return input .trim() .replace(/[<>]/g, '') // Remove < and > .substring(0, 1000); // Limit length } ``` ### Secure Session Management ```typescript import session from 'express-session'; import RedisStore from 'connect-redis'; app.use(session({ store: new RedisStore({ client: redisClient }), secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: false, cookie: { secure: true, // HTTPS only httpOnly: true, // No JavaScript access maxAge: 1000 * 60 * 60 * 24, // 1 day sameSite: 'strict', // CSRF protection }, })); // Regenerate session ID after login app.post('/login', async (req, res) => { const user = await authenticateUser(req.body); req.session.regenerate((err) => { if (err) { return res.status(500).json({ error: 'Session error' }); } req.session.userId = user.id; res.json({ success: true }); }); }); ``` ## Critical Rules ### Always Do - Validate all input - Use parameterized queries - Hash passwords with bcrypt/argon2 - Use HTTPS in production - Implement rate limiting - Set security headers - Use least privilege principle - Encrypt sensitive data - Log security events - Keep dependencies updated ### Never Do - Never trust user input - Never store passwords in plain text - Never log sensitive data - Never use weak encryption (MD5, SHA1 for passwords) - Never expose stack traces to users - Never disable security features "temporarily" - Never hardcode secrets - Never use predictable IDs for sensitive resources - Never trust client-side validation alone ## Knowledge Base - **OWASP Top 10**: Common web vulnerabilities - **Cryptography**: Hashing, encryption, signing - **Authentication**: JWT, OAuth, session management - **Authorization**: RBAC, ABAC, resource-based - **Standards**: OWASP, NIST, PCI DSS ## Best Practices Summary 1. **Input Validation**: Never trust user input 2. **Authentication**: Strong passwords, MFA, rate limiting 3. **Authorization**: Verify every request 4. **Encryption**: Sensitive data at rest and in transit 5. **Sessions**: Secure configuration 6. **Headers**: Set all security headers 7. **Dependencies**: Keep updated 8. **Logging**: Log security events 9. **Principle of Least Privilege**: Minimum necessary permissions 10. **Defense in Depth**: Multiple layers of security