Security Checklist
Overview
This skill provides comprehensive security guidance for building secure applications. Whether performing a security audit, implementing new features, or hardening existing systems, this framework helps identify and mitigate common vulnerabilities.
When to use this skill:
- Conducting security audits or reviews
- Implementing authentication and authorization
- Validating and sanitizing user input
- Handling sensitive data (PII, credentials, payment info)
- Ensuring compliance (GDPR, HIPAA, SOC2)
- Preparing for security assessments or penetration tests
- Reviewing third-party dependencies for vulnerabilities
Required Tools
This skill requires the following tools to be installed on your system:
For JavaScript/TypeScript Projects
- Node.js 18+ with npm
- Command:
npm audit - Install: Node.js comes with npm pre-installed
For Python Projects
- Python 3.8+ with pip
- pip-audit: Security scanner for Python dependencies
- Install:
pip install pip-audit - Command:
pip-audit
- Install:
Optional (Advanced Security Scanning)
-
Semgrep: Static analysis tool
- Install (macOS):
brew install semgrep - Install (pip):
pip install semgrep - Command:
semgrep --config=auto .
- Install (macOS):
-
Bandit: Python security linter
- Install:
pip install bandit - Command:
bandit -r .
- Install:
-
TruffleHog: Secrets detection
- Install (macOS):
brew install trufflesecurity/trufflehog/trufflehog - Install (Go):
go install github.com/trufflesecurity/trufflehog/v3@latest - Command:
trufflehog filesystem .
- Install (macOS):
Installation Verification
# Verify Node.js & npm
node --version
npm --version
# Verify Python & pip
python --version
pip --version
# Verify pip-audit
pip-audit --version
# Verify optional tools
semgrep --version
bandit --version
trufflehog --version
Note: The skill will automatically detect which tools are available and use appropriate commands for your project type.
Security Principles
Defense in Depth
- Multiple layers of security controls
- Assume each layer can fail, design redundancy
- Security at database, application, network, and infrastructure levels
Least Privilege
- Grant minimum permissions necessary
- Separate read/write database accounts
- Service accounts with limited scope
Fail Securely
- Errors don't expose sensitive information
- Authentication failures don't reveal if user exists
- Rate limiting prevents brute force attacks
Don't Trust User Input
- All input is untrusted until validated
- Validate, sanitize, and escape
- Apply principle to query params, headers, cookies, POST data
OWASP Top 10 (2021 Edition)
1. Broken Access Control
Vulnerability: Users can access resources they shouldn't.
Examples:
# ❌ Bad: No authorization check
@app.route('/api/users/<user_id>')
def get_user(user_id):
return db.query(f"SELECT * FROM users WHERE id = {user_id}")
# ✅ Good: Verify user can access this resource
@app.route('/api/users/<user_id>')
@login_required
def get_user(user_id):
current_user = get_current_user()
if current_user.id != user_id and not current_user.is_admin:
abort(403, "Forbidden")
return db.query("SELECT * FROM users WHERE id = ?", [user_id])
Mitigations:
- Deny by default (require explicit authorization)
- Enforce ownership checks (users can only access their own data)
- Implement RBAC (Role-Based Access Control)
- Test for IDOR (Insecure Direct Object References)
- Log access control failures
2. Cryptographic Failures
Vulnerability: Sensitive data exposed due to weak or missing encryption.
Examples:
# ❌ Bad: Storing passwords in plaintext
user.password = request.form['password']
# ✅ Good: Hashing passwords with bcrypt
from bcrypt import hashpw, gensalt
hashed = hashpw(password.encode('utf-8'), gensalt())
user.password_hash = hashed
# ❌ Bad: Using weak hashing (MD5, SHA1)
import hashlib
password_hash = hashlib.md5(password.encode()).hexdigest()
# ✅ Good: Using strong hashing (bcrypt, argon2, scrypt)
from argon2 import PasswordHasher
ph = PasswordHasher()
password_hash = ph.hash(password)
Mitigations:
- Use TLS/HTTPS for all traffic (enforce, not optional)
- Hash passwords with bcrypt, argon2, or scrypt
- Encrypt sensitive data at rest (PII, payment info)
- Never store credit card numbers (use tokenization)
- Use strong random number generators (
secretsmodule in Python) - Rotate encryption keys regularly
3. Injection (SQL, NoSQL, Command, LDAP)
Vulnerability: Untrusted data sent to an interpreter as part of a command.
SQL Injection:
# ❌ Bad: String concatenation (vulnerable to SQL injection)
query = f"SELECT * FROM users WHERE email = '{email}'"
db.execute(query)
# ✅ Good: Parameterized queries
query = "SELECT * FROM users WHERE email = ?"
db.execute(query, [email])
Command Injection:
# ❌ Bad: Shell=True with user input
import subprocess
filename = request.form['filename']
subprocess.run(f"cat {filename}", shell=True)
# ✅ Good: Avoid shell, use list arguments
subprocess.run(["cat", filename], shell=False)
Mitigations:
- Use parameterized queries (prepared statements)
- Use ORMs with proper query builders
- Validate and sanitize all input
- Avoid
eval(),exec(), shell=True - Use allowlists for permitted values
- Escape special characters in dynamic queries
4. Insecure Design
Vulnerability: Design flaws that can't be fixed with implementation.
Examples:
- No rate limiting on login/password reset
- Unlimited file upload sizes
- Sequential or guessable IDs
- Password reset without account verification
Mitigations:
- Threat modeling during design phase
- Rate limiting on all public endpoints
- Use UUIDs instead of sequential IDs for public resources
- Require email verification for password resets
- Implement CAPTCHA for sensitive operations
- Design for secure defaults (opt-in, not opt-out)
5. Security Misconfiguration
Vulnerability: Default configs, incomplete setups, verbose errors.
Examples:
# ❌ Bad: Debug mode in production
app.debug = True
# ✅ Good: Debug mode only in development
app.debug = os.getenv('FLASK_ENV') == 'development'
# ❌ Bad: Verbose error messages
@app.errorhandler(Exception)
def handle_error(e):
return str(e), 500 # Exposes stack traces
# ✅ Good: Generic error messages
@app.errorhandler(Exception)
def handle_error(e):
logger.error(f"Error: {e}")
return {"error": "Internal server error"}, 500
Mitigations:
- Disable debug mode in production
- Remove default credentials
- Close unnecessary ports and services
- Set security headers (CSP, X-Frame-Options, HSTS)
- Keep software updated (dependencies, frameworks, OS)
- Use environment variables for secrets (not hardcoded)
6. Vulnerable and Outdated Components
Vulnerability: Using libraries with known vulnerabilities.
Mitigations:
# Check for vulnerabilities
npm audit
npm audit fix
# Python
pip-audit
safety check
Best Practices:
- Pin dependency versions in lock files
- Scan dependencies regularly (CI/CD integration)
- Subscribe to security advisories (GitHub Dependabot, Snyk)
- Update dependencies regularly (monthly at minimum)
- Remove unused dependencies
7. Identification and Authentication Failures
Vulnerability: Weak authentication, credential stuffing, session hijacking.
Examples:
# ❌ Bad: Weak password requirements
if len(password) < 6:
return "Password too short"
# ✅ Good: Strong password requirements
import re
def validate_password(password):
if len(password) < 12:
return "Password must be at least 12 characters"
if not re.search(r"[A-Z]", password):
return "Password must contain uppercase letter"
if not re.search(r"[a-z]", password):
return