Security Checklist
Comprehensive security checklist for identifying and preventing vulnerabilities in web applications.
Quick Security Scan
Before committing code, verify:
- • No hardcoded secrets (API keys, passwords, tokens)
- • All user inputs validated
- • SQL queries parameterized
- • Output escaped/sanitized (XSS prevention)
- • Authentication/authorization checked
- • HTTPS enforced
- • Error messages don't leak sensitive data
- • Dependencies checked (
npm audit)
OWASP Top 10 Checklist
1. Injection (SQL, NoSQL, Command)
Red Flags:
javascript
// ❌ CRITICAL: SQL injection
db.query(`SELECT * FROM users WHERE id = ${userId}`)
db.query("DELETE FROM posts WHERE id = " + postId)
// ❌ CRITICAL: Command injection
exec(`git log --author=${username}`)
Secure Patterns:
javascript
// ✅ Parameterized queries
db.query('SELECT * FROM users WHERE id = ?', [userId])
db.query('DELETE FROM posts WHERE id = $1', [postId])
// ✅ Input validation + escaping
const safeUsername = escapeShellArg(username)
exec(`git log --author=${safeUsername}`)
Checklist:
- • All database queries use parameterized statements
- • No string concatenation in queries
- • User input never directly in shell commands
- • NoSQL queries use proper escaping
- • ORM/query builders used correctly
2. Broken Authentication
Red Flags:
javascript
// ❌ CRITICAL: Weak password hashing const hash = md5(password) const hash = sha1(password) // ❌ CRITICAL: Insecure JWT jwt.verify(token) // No secret! jwt.sign(data, 'hardcoded-secret') // ❌ CRITICAL: Session fixation session.id = req.query.sessionId
Secure Patterns:
javascript
// ✅ Strong password hashing
import bcrypt from 'bcrypt'
const hash = await bcrypt.hash(password, 10)
// ✅ Secure JWT
const secret = process.env.JWT_SECRET
jwt.verify(token, secret, { algorithms: ['HS256'] })
// ✅ Secure session management
session.regenerate() // After login
Checklist:
- • Passwords hashed with bcrypt/argon2
- • JWT properly validated with secret
- • Sessions regenerated after login
- • Multi-factor authentication available
- • Account lockout after failed attempts
- • Secure password reset flow
3. Sensitive Data Exposure
Red Flags:
javascript
// ❌ CRITICAL: Secrets in code
const apiKey = "sk-proj-xxxxx"
const dbPassword = "admin123"
// ❌ CRITICAL: Secrets in logs
console.log('User data:', { password, ssn })
logger.info(`API Key: ${apiKey}`)
// ❌ CRITICAL: PII in URLs
fetch(`/api/user?ssn=${ssn}&creditCard=${cc}`)
Secure Patterns:
javascript
// ✅ Environment variables
const apiKey = process.env.OPENAI_API_KEY
if (!apiKey) throw new Error('Missing API key')
// ✅ Sanitized logs
console.log('User data:', { id, email }) // No password
logger.info('API call successful') // No secrets
// ✅ PII in request body
fetch('/api/user', {
method: 'POST',
body: JSON.stringify({ ssn, creditCard })
})
Checklist:
- • All secrets in environment variables
- • HTTPS enforced everywhere
- • Sensitive data encrypted at rest
- • Logs don't contain PII/secrets
- • No secrets in version control
- • .env files in .gitignore
4. XML External Entities (XXE)
Checklist:
- • XML parsers disable external entities
- • DTD processing disabled
- • Use JSON instead of XML when possible
5. Broken Access Control
Red Flags:
javascript
// ❌ CRITICAL: Missing authorization
app.delete('/api/users/:id', async (req, res) => {
await db.deleteUser(req.params.id) // Anyone can delete!
})
// ❌ CRITICAL: Direct object reference
const file = req.query.file
fs.readFile(`/uploads/${file}`) // Path traversal!
Secure Patterns:
javascript
// ✅ Authorization check
app.delete('/api/users/:id', auth, async (req, res) => {
if (req.user.id !== req.params.id && !req.user.isAdmin) {
return res.status(403).json({ error: 'Forbidden' })
}
await db.deleteUser(req.params.id)
})
// ✅ Indirect object reference
const fileId = req.query.fileId
const file = await db.getFile(fileId, req.user.id) // Check ownership
Checklist:
- • Authorization on every endpoint
- • Users can only access their own data
- • Admin routes require admin role
- • CORS configured properly
- • Object references indirect
- • Rate limiting enabled
6. Security Misconfiguration
Checklist:
- • Default credentials changed
- • Debug mode disabled in production
- • Error messages don't leak info
- • Security headers set (CSP, HSTS, X-Frame-Options)
- • Unnecessary features disabled
- • Dependencies up to date
7. Cross-Site Scripting (XSS)
Red Flags:
javascript
// ❌ CRITICAL: Unescaped output
element.innerHTML = userInput
dangerouslySetInnerHTML={{ __html: comment }}
eval(userCode)
Secure Patterns:
javascript
// ✅ Escaped output
element.textContent = userInput
<div>{comment}</div> // React escapes by default
// ✅ Content Security Policy
res.setHeader('Content-Security-Policy', "default-src 'self'")
Checklist:
- • Output escaped/sanitized
- • Content-Security-Policy header set
- • No innerHTML with user data
- • No eval() or Function() with user input
- • Frameworks escape by default
8. Insecure Deserialization
Checklist:
- • User input not deserialized unsafely
- • JSON.parse() only on trusted data
- • No eval() on serialized data
9. Using Components with Known Vulnerabilities
Commands:
bash
# Check for vulnerabilities npm audit # High severity only npm audit --audit-level=high # Fix automatically npm audit fix
Checklist:
- •
npm auditclean - • Dependencies regularly updated
- • CVEs monitored
- • Deprecated packages replaced
10. Insufficient Logging & Monitoring
Checklist:
- • Security events logged (login, logout, auth failures)
- • Logs include timestamp, user, action
- • Logs monitored for suspicious activity
- • Alerts configured for critical events
- • Logs sanitized (no PII/secrets)
Secrets Detection
Common Secret Patterns
bash
# Search for potential secrets grep -r "api[_-]?key\|password\|secret\|token" \ --include="*.js" --include="*.ts" --include="*.json" . # Check git history git log -p | grep -i "password\|api_key\|secret" # Automated scanning npx trufflehog filesystem . --json
Secret Patterns to Flag
- •API keys:
sk-,pk_,api_key - •Tokens:
ghp_,gho_,token - •Passwords:
password=,pwd= - •Private keys:
-----BEGIN PRIVATE KEY----- - •Database URLs:
postgresql://,mongodb://with credentials
Security Tools
Dependency Scanning
bash
npm audit # Check vulnerabilities npm audit fix # Auto-fix npm audit --audit-level=high # High severity only
Static Analysis
bash
npx eslint . --plugin security npx semgrep --config auto .
Secrets Scanning
bash
npx trufflehog filesystem . --json git-secrets --scan
Quick Reference
Must-Have Security Headers
javascript
// Express middleware
app.use(helmet()) // Sets multiple security headers
// Manual setup
res.setHeader('X-Frame-Options', 'DENY')
res.setHeader('X-Content-Type-Options', 'nosniff')
res.setHeader('Strict-Transport-Security', 'max-age=31536000')
res.setHeader('Content-Security-Policy', "default-src 'self'")
Environment Variables Checklist
bash
# ✅ Required in .env (never commit) OPENAI_API_KEY=sk-... DATABASE_URL=postgresql://... JWT_SECRET=random-secret-here # ✅ Required in .gitignore .env .env.local .env.*.local
Rate Limiting
javascript
import rateLimit from 'express-rate-limit'
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100 // 100 requests per window
})
app.use('/api/', limiter)
When to Use This Checklist
- •✅ Before committing code
- •✅ During code reviews
- •✅ After implementing authentication
- •✅ When handling user input
- •✅ Before deploying to production
- •✅ When adding new API endpoints
- •✅ After dependency updates
Security Review Workflow
- •
Run automated tools
- •
npm audit - •eslint-plugin-security
- •grep for secrets
- •
- •
Check high-risk areas
- •Authentication code
- •API endpoints with user input
- •Database queries
- •File uploads
- •Payment processing
- •
Verify OWASP Top 10
- •Go through checklist above
- •Test each category
- •
Review findings
- •Fix CRITICAL immediately
- •Plan HIGH severity fixes
- •Document MEDIUM issues
Common Vulnerabilities Summary
| Vulnerability | Detection | Fix |
|---|---|---|
| Hardcoded secrets | grep, git log | Move to .env |
| SQL injection | Code review | Parameterized queries |
| XSS | Code review | Escape output |
| Missing auth | Code review | Add auth middleware |
| Weak passwords | Code review | Use bcrypt |
| Insecure JWT | Code review | Proper validation |
| Path traversal | Code review | Validate paths |
| CORS misconfigured | Headers check | Configure properly |