I keep a security checklist pinned to my monitor. It's saved me from shipping vulnerabilities at least a dozen times.
Authentication & Sessions
import bcrypt
def hash_password(plain_text):
salt = bcrypt.gensalt(rounds=12)
return bcrypt.hashpw(plain_text.encode(), salt)
def verify_password(plain_text, hashed):
return bcrypt.checkpw(plain_text.encode(), hashed)
Checklist:
- [ ] Passwords hashed with bcrypt/scrypt/argon2
- [ ] Session tokens are random, long, and expire
- [ ] Failed login attempts are rate-limited
Input Validation
import re
def validate_email(email):
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
if not re.match(pattern, email) or len(email) > 254:
raise ValueError("Invalid email format")
return email.lower().strip()
SQL Injection Prevention
# BAD
query = f"SELECT * FROM users WHERE id = {user_id}"
# GOOD
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
HTTP Security Headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'" always;
Secrets Management
# BAD
DATABASE_URL = "postgresql://admin:password123@db:5432/prod"
# GOOD
DATABASE_URL = os.environ["DATABASE_URL"]
My Full Pre-Deploy Checklist
- Auth: Passwords hashed, sessions expire, rate limiting on
- Input: All user input validated server-side
- SQL: Parameterized queries everywhere
- XSS: All output escaped
- Headers: Security headers configured
- Secrets: Nothing hardcoded, .env gitignored
-
Deps:
npm audit/pip-auditclean - HTTPS: TLS everywhere, HSTS enabled
- Logs: Auth events logged, no sensitive data in logs
- Backup: Database backup tested and verified
Resources
- CyberGuard Essentials (FREE) - Security fundamentals with practical examples
- CyberGuard Advanced ($11.99) - Penetration testing, threat modeling, advanced hardening
Print this checklist. Pin it to your monitor.
Top comments (0)