---
name: security
description: 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.
allowed-tools: Read Grep Glob Bash
user-invocable: false
---

# 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 | [reference](references/owasp-top-10.md) |
| 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) |
| A03 | Injection | Untrusted data sent to interpreter as part of a command/query | Parameterized queries, input validation | [reference](references/owasp-top-10.md) |
| A04 | Insecure Design | Missing or ineffective security controls by design | Threat modeling, secure design patterns | [reference](references/owasp-top-10.md) |
| A05 | Security Misconfiguration | Insecure default configs, incomplete setup | Hardened defaults, automated config validation | [reference](references/owasp-top-10.md) |
| A06 | Vulnerable Components | Using components with known vulnerabilities | Dependency scanning, timely updates | [reference](references/owasp-top-10.md) |
| A07 | Auth Failures | Broken authentication/identification | MFA, rate limiting, secure password storage | [reference](references/owasp-top-10.md) |
| A08 | Integrity Failures | Code/data integrity not verified | Signed updates, CI/CD integrity checks | [reference](references/owasp-top-10.md) |
| A09 | Logging Failures | Insufficient logging and monitoring | Log security events, set up alerting | [reference](references/owasp-top-10.md) |
| A10 | SSRF | Server tricked into making unintended requests | Allowlist destinations, sanitize URLs | [reference](references/owasp-top-10.md) |

## 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](references/secure-coding.md) for details.

## Authentication Patterns

Authentication verifies identity — "who are you?" See [auth patterns reference](references/auth-patterns.md) 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](references/auth-patterns.md) 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
