| 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
Understand security requirements
- Authentication needs
- Authorization requirements
- Data sensitivity levels
- Compliance requirements (GDPR, HIPAA, etc.)
- Threat model
Implement security controls
- Input validation
- Output encoding
- Authentication mechanisms
- Authorization checks
- Encryption (at rest and in transit)
- Secure session management
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
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
// ❌ 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
import bcrypt from 'bcrypt';
// Password hashing
async function hashPassword(password: string): Promise<string> {
const saltRounds = 12; // Minimum 10
return await bcrypt.hash(password, saltRounds);
}
// Password verification
async function verifyPassword(password: string, hash: string): Promise<boolean> {
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<string, { count: number; resetTime: number }>();
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
// ❌ 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
<div>{userInput}</div> // 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
// 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
// <input type="hidden" name="_csrf" value="{{ csrfToken }}">
// For APIs: Use custom headers
// X-CSRF-Token: <token>
5. Authorization Best Practices
// 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<boolean> {
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
// 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
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
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
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
- Input Validation: Never trust user input
- Authentication: Strong passwords, MFA, rate limiting
- Authorization: Verify every request
- Encryption: Sensitive data at rest and in transit
- Sessions: Secure configuration
- Headers: Set all security headers
- Dependencies: Keep updated
- Logging: Log security events
- Principle of Least Privilege: Minimum necessary permissions
- Defense in Depth: Multiple layers of security