Security
Security is not a feature — it is a property of every feature. Every endpoint, every form, every data flow, every integration point must be designed with security in mind from the start. Bolting security on after the fact is expensive, error-prone, and often incomplete.
This skill provides stack-agnostic guidance for building secure applications. It covers the OWASP Top 10, input validation, authentication and authorization patterns, data protection, secrets management, security headers, and common antipatterns.
When to Use
Consult this skill when:
-
Designing a new feature that handles user input, authentication, or sensitive data
-
Reviewing code for security concerns
-
Implementing authentication or authorization flows
-
Handling secrets, API keys, or credentials
-
Configuring HTTP security headers
-
Assessing whether a dependency or design choice introduces risk
-
Preparing for a security audit or penetration test
-
Responding to a security incident or vulnerability report
OWASP Top 10
The OWASP Top 10 (2021 edition) represents the most critical security risks to web applications. Use this as a starting checklist — not an exhaustive list.
Vulnerability What It Is Primary Defense
A01 Broken Access Control Users act outside intended permissions Deny by default, enforce server-side
A02 Cryptographic Failures Sensitive data exposed due to weak/missing crypto Use strong algorithms, encrypt in transit and at rest
A03 Injection Untrusted data sent to interpreter as part of a command/query Parameterized queries, input validation
A04 Insecure Design Missing or ineffective security controls by design Threat modeling, secure design patterns
A05 Security Misconfiguration Insecure default configs, incomplete setup Hardened defaults, automated config validation
A06 Vulnerable Components Using components with known vulnerabilities Dependency scanning, timely updates
A07 Auth Failures Broken authentication/identification MFA, rate limiting, secure password storage
A08 Integrity Failures Code/data integrity not verified Signed updates, CI/CD integrity checks
A09 Logging Failures Insufficient logging and monitoring Log security events, set up alerting
A10 SSRF Server tricked into making unintended requests Allowlist destinations, sanitize URLs
Input Validation
Input validation is the first line of defense. Validate at every system boundary — not just at the UI.
Core principles:
-
Validate on the server — client-side validation is a UX convenience, not a security control
-
Allowlist over denylist — define what is acceptable rather than trying to block what is dangerous
-
Validate type, length, format, and range — a "name" field should not accept 10MB of data or contain control characters
-
Reject unexpected input — fail closed, do not attempt to "clean" malicious input and proceed
-
Canonicalize before validation — normalize Unicode, decode URL encoding, resolve path traversals before checking
Type coercion dangers:
Loose type comparisons can bypass security checks. A string "0" might equal integer 0 or boolean false depending on the language. Always use strict comparison operators and explicit type casting.
Parameterized queries:
Never concatenate user input into SQL, LDAP, or OS commands. Always use parameterized queries or prepared statements. This applies to ORMs too — raw query methods bypass ORM protections. See secure coding reference for details.
Authentication Patterns
Authentication verifies identity — "who are you?" See auth patterns reference for detailed guidance.
Password hashing:
-
Use bcrypt, scrypt, or Argon2id — never MD5, SHA-1, or SHA-256 alone for passwords
-
Salts must be unique per password and generated by the hashing library
-
Never store plain-text passwords, never use reversible encryption for passwords
-
Enforce minimum complexity but avoid overly restrictive rules that push users to weaker patterns
Multi-factor authentication (MFA):
-
TOTP (time-based one-time passwords) is the baseline
-
WebAuthn/passkeys provide the strongest phishing resistance
-
SMS-based MFA is better than nothing but vulnerable to SIM swapping
-
Always provide recovery codes
Session management:
-
Generate cryptographically random session IDs with sufficient entropy (128+ bits)
-
Set secure cookie attributes: HttpOnly , Secure , SameSite=Lax (or Strict )
-
Regenerate session ID after login to prevent session fixation
-
Implement absolute and idle timeouts
-
Invalidate sessions server-side on logout
Token-based auth (JWT caveats):
-
JWTs are not sessions — they cannot be revoked without additional infrastructure
-
Always validate the signature algorithm server-side; reject alg: none
-
Keep tokens short-lived (minutes, not hours)
-
Use refresh tokens for long-lived sessions; store them securely
-
Never store sensitive data in JWT payloads — they are base64-encoded, not encrypted
OAuth2 flows:
-
Authorization Code with PKCE — standard for web and mobile apps
-
Client Credentials — for machine-to-machine communication
-
Never use Implicit flow — it is deprecated for security reasons
Authorization Patterns
Authorization determines permissions — "what are you allowed to do?" Authorization is not authentication. See auth patterns reference for details.
Principle of least privilege:
-
Grant the minimum permissions needed for a task
-
Default to deny — explicitly grant access rather than revoking it
-
Time-bound elevated privileges when possible
Role-Based Access Control (RBAC):
-
Assign permissions to roles, assign roles to users
-
Keep roles coarse-grained; avoid role explosion
-
Check permissions, not role names, in application code — this decouples authorization logic from role definitions
Attribute-Based Access Control (ABAC):
-
Decisions based on attributes of user, resource, action, and environment
-
More flexible than RBAC for complex policies (e.g., "managers can approve expenses under $10,000 during business hours")
-
Higher complexity — use when RBAC is insufficient
Common authorization mistakes:
-
Checking authorization only in the UI — always enforce server-side
-
Relying on obscurity (unguessable URLs) instead of access controls
-
Failing to check authorization on every request (including API calls, file downloads, and indirect references)
-
IDOR (Insecure Direct Object Reference) — always verify the user has access to the specific resource they are requesting
Data Protection
Encryption at rest:
-
Encrypt sensitive data stored in databases, files, and backups
-
Use AES-256 or equivalent for symmetric encryption
-
Manage encryption keys separately from encrypted data
-
Rotate encryption keys on a schedule and when compromise is suspected
Encryption in transit:
-
Use TLS 1.2+ for all network communication
-
Disable older protocols (SSL, TLS 1.0, TLS 1.1)
-
Validate certificates properly — do not disable certificate verification
PII handling:
-
Identify and classify all personally identifiable information
-
Minimize collection — do not collect data you do not need
-
Implement data retention policies — delete data when no longer needed
-
Provide data export and deletion capabilities for compliance (GDPR, CCPA)
-
Mask PII in logs — never log passwords, tokens, credit card numbers, or full SSNs
Secure deletion:
-
Overwrite sensitive data before freeing memory (when the language allows)
-
Ensure database deletions actually remove data (not just soft-delete for sensitive records)
-
Consider backup retention — deleted data may persist in backups
Secrets Management
Never in code or config files:
-
No API keys, passwords, or tokens in source code, config files, or environment-specific files committed to version control
-
Use .gitignore for local config files, but do not rely on it as your only protection
-
Scan repositories for accidentally committed secrets (use tools like git-secrets, truffleHog, or Gitleaks)
Environment variables:
-
Acceptable for simple deployments but have limitations
-
They are visible to all processes in the same environment
-
They appear in process listings and crash dumps
-
Better than hardcoding, but not the strongest option
Secret managers:
-
Use dedicated secret managers (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, GCP Secret Manager)
-
Access secrets at runtime, not build time
-
Audit access to secrets
Rotation strategy:
-
Rotate secrets on a regular schedule
-
Rotate immediately if compromise is suspected
-
Design systems to support rotation without downtime (support two active versions during transition)
-
Automate rotation where possible
Security Headers
Configure these HTTP response headers on every response. Each addresses a specific class of attack.
Header Purpose Recommended Value
Content-Security-Policy (CSP) Prevents XSS by controlling which sources can load content Start with a restrictive policy; avoid unsafe-inline and unsafe-eval
Strict-Transport-Security (HSTS) Forces HTTPS for all future requests max-age=63072000; includeSubDomains; preload
X-Content-Type-Options
Prevents MIME-type sniffing nosniff
X-Frame-Options
Prevents clickjacking by controlling iframe embedding DENY or SAMEORIGIN
Referrer-Policy
Controls how much referrer info is sent strict-origin-when-cross-origin
Permissions-Policy
Controls browser features (camera, mic, geolocation) Disable features you do not use
CORS (Cross-Origin Resource Sharing):
-
Do not use Access-Control-Allow-Origin: * for authenticated endpoints
-
Allowlist specific origins
-
Be restrictive with Access-Control-Allow-Methods and Access-Control-Allow-Headers
-
Understand that CORS is enforced by browsers — it does not protect server-to-server calls
Common Antipatterns
These are frequently encountered mistakes that create vulnerabilities:
-
Security through obscurity — hiding URLs, using unpredictable IDs, or obfuscating code is not a security control. It supplements real controls; it never replaces them.
-
Client-side validation only — any validation done in JavaScript or mobile code can be bypassed. Always validate server-side.
-
Homegrown cryptography — never implement your own encryption, hashing, or random number generation. Use well-tested libraries.
-
Overly permissive CORS — Access-Control-Allow-Origin: * combined with credentials is a vulnerability. Be specific about allowed origins.
-
Storing secrets in repositories — even in "private" repos, secrets in code spread through forks, CI systems, and developer machines.
-
Disabling security features for convenience — turning off CSRF protection, SSL verification, or authentication in "development" mode that leaks to production.
-
Trusting internal networks — zero-trust means verifying identity and authorization even for internal service-to-service calls.
-
Ignoring dependency vulnerabilities — known vulnerabilities in dependencies are among the easiest attack vectors. Scan and update regularly.
-
Logging sensitive data — passwords, tokens, credit card numbers, and PII in logs create a secondary exposure surface.
-
Catching and silencing exceptions — swallowing errors hides security failures. Log them (without sensitive details) and fail safely.
Security Review Checklist
Use this checklist when reviewing code, designing features, or preparing for release:
Input/Output:
-
All user input is validated server-side
-
Parameterized queries used for all database operations
-
Output is encoded/escaped for the appropriate context (HTML, URL, JavaScript, SQL)
-
File uploads validate type, size, and content; stored outside web root
Authentication:
-
Passwords hashed with bcrypt/Argon2id
-
Session IDs regenerated after login
-
Secure cookie attributes set (HttpOnly, Secure, SameSite)
-
Rate limiting on login endpoints
-
Account lockout or progressive delays after failed attempts
Authorization:
-
Authorization enforced server-side on every request
-
Principle of least privilege applied
-
Direct object references validated against the current user
-
Admin functions protected and not accessible through URL guessing
Data:
-
Sensitive data encrypted at rest and in transit
-
PII not logged
-
Data retention policies implemented
-
Backups encrypted
Configuration:
-
No secrets in source code or config files
-
Security headers configured
-
Debug mode disabled in production
-
Error messages do not leak internal details to clients
-
Dependencies scanned for known vulnerabilities
-
TLS 1.2+ enforced; older protocols disabled
Monitoring:
-
Security events logged (login failures, authorization denials, input validation failures)
-
Alerts configured for suspicious patterns
-
Logs protected from tampering
-
Incident response plan documented