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:
Authentication:
Authorization:
Data:
Configuration:
Monitoring:
1---2name: security3description: Application security principles and OWASP Top 10 for building secure web applications. Use when the user asks to review code for security vulnerabilities, implement authentication or authorization, handle secrets or API keys, configure security headers, prevent injection attacks (SQL, XSS, CSRF), prepare for a security audit, or respond to a vulnerability report. Covers input validation, data protection, secrets management, session handling, and common security antipatterns.4---56# Security78Security 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.910This 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.1112## When to Use1314Consult this skill when:1516- Designing a new feature that handles user input, authentication, or sensitive data17- Reviewing code for security concerns18- Implementing authentication or authorization flows19- Handling secrets, API keys, or credentials20- Configuring HTTP security headers21- Assessing whether a dependency or design choice introduces risk22- Preparing for a security audit or penetration test23- Responding to a security incident or vulnerability report2425## OWASP Top 102627The OWASP Top 10 (2021 edition) represents the most critical security risks to web applications. Use this as a starting checklist — not an exhaustive list.2829| # | Vulnerability | What It Is | Primary Defense |30|---|---|---|---|31| A01 | Broken Access Control | Users act outside intended permissions | Deny by default, enforce server-side | [reference](references/owasp-top-10.md) |32| A02 | Cryptographic Failures | Sensitive data exposed due to weak/missing crypto | Use strong algorithms, encrypt in transit and at rest | [reference](references/owasp-top-10.md) |33| A03 | Injection | Untrusted data sent to interpreter as part of a command/query | Parameterized queries, input validation | [reference](references/owasp-top-10.md) |34| A04 | Insecure Design | Missing or ineffective security controls by design | Threat modeling, secure design patterns | [reference](references/owasp-top-10.md) |35| A05 | Security Misconfiguration | Insecure default configs, incomplete setup | Hardened defaults, automated config validation | [reference](references/owasp-top-10.md) |36| A06 | Vulnerable Components | Using components with known vulnerabilities | Dependency scanning, timely updates | [reference](references/owasp-top-10.md) |37| A07 | Auth Failures | Broken authentication/identification | MFA, rate limiting, secure password storage | [reference](references/owasp-top-10.md) |38| A08 | Integrity Failures | Code/data integrity not verified | Signed updates, CI/CD integrity checks | [reference](references/owasp-top-10.md) |39| A09 | Logging Failures | Insufficient logging and monitoring | Log security events, set up alerting | [reference](references/owasp-top-10.md) |40| A10 | SSRF | Server tricked into making unintended requests | Allowlist destinations, sanitize URLs | [reference](references/owasp-top-10.md) |4142## Input Validation4344Input validation is the first line of defense. Validate at every system boundary — not just at the UI.4546**Core principles:**4748- **Validate on the server** — client-side validation is a UX convenience, not a security control49- **Allowlist over denylist** — define what is acceptable rather than trying to block what is dangerous50- **Validate type, length, format, and range** — a "name" field should not accept 10MB of data or contain control characters51- **Reject unexpected input** — fail closed, do not attempt to "clean" malicious input and proceed52- **Canonicalize before validation** — normalize Unicode, decode URL encoding, resolve path traversals before checking5354**Type coercion dangers:**5556Loose 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.5758**Parameterized queries:**5960Never 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](references/secure-coding.md) for details.6162## Authentication Patterns6364Authentication verifies identity — "who are you?" See [auth patterns reference](references/auth-patterns.md) for detailed guidance.6566**Password hashing:**6768- Use bcrypt, scrypt, or Argon2id — never MD5, SHA-1, or SHA-256 alone for passwords69- Salts must be unique per password and generated by the hashing library70- Never store plain-text passwords, never use reversible encryption for passwords71- Enforce minimum complexity but avoid overly restrictive rules that push users to weaker patterns7273**Multi-factor authentication (MFA):**7475- TOTP (time-based one-time passwords) is the baseline76- WebAuthn/passkeys provide the strongest phishing resistance77- SMS-based MFA is better than nothing but vulnerable to SIM swapping78- Always provide recovery codes7980**Session management:**8182- Generate cryptographically random session IDs with sufficient entropy (128+ bits)83- Set secure cookie attributes: `HttpOnly`, `Secure`, `SameSite=Lax` (or `Strict`)84- Regenerate session ID after login to prevent session fixation85- Implement absolute and idle timeouts86- Invalidate sessions server-side on logout8788**Token-based auth (JWT caveats):**8990- JWTs are not sessions — they cannot be revoked without additional infrastructure91- Always validate the signature algorithm server-side; reject `alg: none`92- Keep tokens short-lived (minutes, not hours)93- Use refresh tokens for long-lived sessions; store them securely94- Never store sensitive data in JWT payloads — they are base64-encoded, not encrypted9596**OAuth2 flows:**9798- Authorization Code with PKCE — standard for web and mobile apps99- Client Credentials — for machine-to-machine communication100- Never use Implicit flow — it is deprecated for security reasons101102## Authorization Patterns103104Authorization determines permissions — "what are you allowed to do?" Authorization is not authentication. See [auth patterns reference](references/auth-patterns.md) for details.105106**Principle of least privilege:**107108- Grant the minimum permissions needed for a task109- Default to deny — explicitly grant access rather than revoking it110- Time-bound elevated privileges when possible111112**Role-Based Access Control (RBAC):**113114- Assign permissions to roles, assign roles to users115- Keep roles coarse-grained; avoid role explosion116- Check permissions, not role names, in application code — this decouples authorization logic from role definitions117118**Attribute-Based Access Control (ABAC):**119120- Decisions based on attributes of user, resource, action, and environment121- More flexible than RBAC for complex policies (e.g., "managers can approve expenses under $10,000 during business hours")122- Higher complexity — use when RBAC is insufficient123124**Common authorization mistakes:**125126- Checking authorization only in the UI — always enforce server-side127- Relying on obscurity (unguessable URLs) instead of access controls128- Failing to check authorization on every request (including API calls, file downloads, and indirect references)129- IDOR (Insecure Direct Object Reference) — always verify the user has access to the specific resource they are requesting130131## Data Protection132133**Encryption at rest:**134135- Encrypt sensitive data stored in databases, files, and backups136- Use AES-256 or equivalent for symmetric encryption137- Manage encryption keys separately from encrypted data138- Rotate encryption keys on a schedule and when compromise is suspected139140**Encryption in transit:**141142- Use TLS 1.2+ for all network communication143- Disable older protocols (SSL, TLS 1.0, TLS 1.1)144- Validate certificates properly — do not disable certificate verification145146**PII handling:**147148- Identify and classify all personally identifiable information149- Minimize collection — do not collect data you do not need150- Implement data retention policies — delete data when no longer needed151- Provide data export and deletion capabilities for compliance (GDPR, CCPA)152- Mask PII in logs — never log passwords, tokens, credit card numbers, or full SSNs153154**Secure deletion:**155156- Overwrite sensitive data before freeing memory (when the language allows)157- Ensure database deletions actually remove data (not just soft-delete for sensitive records)158- Consider backup retention — deleted data may persist in backups159160## Secrets Management161162**Never in code or config files:**163164- No API keys, passwords, or tokens in source code, config files, or environment-specific files committed to version control165- Use `.gitignore` for local config files, but do not rely on it as your only protection166- Scan repositories for accidentally committed secrets (use tools like git-secrets, truffleHog, or Gitleaks)167168**Environment variables:**169170- Acceptable for simple deployments but have limitations171- They are visible to all processes in the same environment172- They appear in process listings and crash dumps173- Better than hardcoding, but not the strongest option174175**Secret managers:**176177- Use dedicated secret managers (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, GCP Secret Manager)178- Access secrets at runtime, not build time179- Audit access to secrets180181**Rotation strategy:**182183- Rotate secrets on a regular schedule184- Rotate immediately if compromise is suspected185- Design systems to support rotation without downtime (support two active versions during transition)186- Automate rotation where possible187188## Security Headers189190Configure these HTTP response headers on every response. Each addresses a specific class of attack.191192| Header | Purpose | Recommended Value |193|---|---|---|194| `Content-Security-Policy` (CSP) | Prevents XSS by controlling which sources can load content | Start with a restrictive policy; avoid `unsafe-inline` and `unsafe-eval` |195| `Strict-Transport-Security` (HSTS) | Forces HTTPS for all future requests | `max-age=63072000; includeSubDomains; preload` |196| `X-Content-Type-Options` | Prevents MIME-type sniffing | `nosniff` |197| `X-Frame-Options` | Prevents clickjacking by controlling iframe embedding | `DENY` or `SAMEORIGIN` |198| `Referrer-Policy` | Controls how much referrer info is sent | `strict-origin-when-cross-origin` |199| `Permissions-Policy` | Controls browser features (camera, mic, geolocation) | Disable features you do not use |200201**CORS (Cross-Origin Resource Sharing):**202203- Do not use `Access-Control-Allow-Origin: *` for authenticated endpoints204- Allowlist specific origins205- Be restrictive with `Access-Control-Allow-Methods` and `Access-Control-Allow-Headers`206- Understand that CORS is enforced by browsers — it does not protect server-to-server calls207208## Common Antipatterns209210These are frequently encountered mistakes that create vulnerabilities:211212- **Security through obscurity** — hiding URLs, using unpredictable IDs, or obfuscating code is not a security control. It supplements real controls; it never replaces them.213- **Client-side validation only** — any validation done in JavaScript or mobile code can be bypassed. Always validate server-side.214- **Homegrown cryptography** — never implement your own encryption, hashing, or random number generation. Use well-tested libraries.215- **Overly permissive CORS** — `Access-Control-Allow-Origin: *` combined with credentials is a vulnerability. Be specific about allowed origins.216- **Storing secrets in repositories** — even in "private" repos, secrets in code spread through forks, CI systems, and developer machines.217- **Disabling security features for convenience** — turning off CSRF protection, SSL verification, or authentication in "development" mode that leaks to production.218- **Trusting internal networks** — zero-trust means verifying identity and authorization even for internal service-to-service calls.219- **Ignoring dependency vulnerabilities** — known vulnerabilities in dependencies are among the easiest attack vectors. Scan and update regularly.220- **Logging sensitive data** — passwords, tokens, credit card numbers, and PII in logs create a secondary exposure surface.221- **Catching and silencing exceptions** — swallowing errors hides security failures. Log them (without sensitive details) and fail safely.222223## Security Review Checklist224225Use this checklist when reviewing code, designing features, or preparing for release:226227**Input/Output:**228- [ ] All user input is validated server-side229- [ ] Parameterized queries used for all database operations230- [ ] Output is encoded/escaped for the appropriate context (HTML, URL, JavaScript, SQL)231- [ ] File uploads validate type, size, and content; stored outside web root232233**Authentication:**234- [ ] Passwords hashed with bcrypt/Argon2id235- [ ] Session IDs regenerated after login236- [ ] Secure cookie attributes set (HttpOnly, Secure, SameSite)237- [ ] Rate limiting on login endpoints238- [ ] Account lockout or progressive delays after failed attempts239240**Authorization:**241- [ ] Authorization enforced server-side on every request242- [ ] Principle of least privilege applied243- [ ] Direct object references validated against the current user244- [ ] Admin functions protected and not accessible through URL guessing245246**Data:**247- [ ] Sensitive data encrypted at rest and in transit248- [ ] PII not logged249- [ ] Data retention policies implemented250- [ ] Backups encrypted251252**Configuration:**253- [ ] No secrets in source code or config files254- [ ] Security headers configured255- [ ] Debug mode disabled in production256- [ ] Error messages do not leak internal details to clients257- [ ] Dependencies scanned for known vulnerabilities258- [ ] TLS 1.2+ enforced; older protocols disabled259260**Monitoring:**261- [ ] Security events logged (login failures, authorization denials, input validation failures)262- [ ] Alerts configured for suspicious patterns263- [ ] Logs protected from tampering264- [ ] Incident response plan documented