Harden
Security as a constraint on every line that touches user data, auth, or external systems. This skill is proactive: applied during implementation, not after. For reactive scans, use safe-repo (sensitive data) or deps-audit (CVEs).
Three-Tier Boundary System
Always do (no exceptions)
- Validate every external input at the system boundary (route handler, API entry)
- Parameterize all database queries (never concatenate user input into SQL)
- Encode output to prevent XSS — use framework auto-escaping, don't bypass it
- HTTPS for all external communication
- Hash passwords with bcrypt/scrypt/argon2 (salt rounds ≥ 12); never plaintext
- Set security headers: CSP, HSTS, X-Frame-Options, X-Content-Type-Options
- Session cookies:
httpOnly, secure, sameSite
- Use environment variables for secrets; reference, never inline
- Strip sensitive fields from API responses by default
Ask first (human approval required)
- New authentication flow or auth logic changes
- Storing new categories of sensitive data (PII, payment)
- New external service integrations
- CORS configuration changes
- File upload handlers
- Rate-limit / throttling changes
- Granting elevated permissions or roles
Never do
- Commit secrets to version control
- Log sensitive data (passwords, tokens, full PAN)
- Trust client-side validation as a security boundary
- Disable security headers for convenience
- Use
eval() or innerHTML with user-provided data
- Store sessions in client-accessible storage (e.g., localStorage for auth tokens)
- Expose stack traces or internal errors to users
See OWASP Top 10 quick reference.
Input Validation at Boundaries
Always validate at the system boundary (route handler, message consumer), not in business logic:
- Schema validator (Zod, Joi, Yup, pydantic) defines the contract
- Reject with 422 + structured error before any business logic touches the data
- Trust internal code; validate only at the edges
File Upload Safety
- Allowlist MIME types; deny unknown
- Enforce max size before processing
- Check magic bytes if file type is security-critical (don't trust extension or
mimetype)
- Store outside webroot or behind authenticated access
Verification
After implementing security-relevant code, confirm:
Common Rationalizations
| Rationalization |
Reality |
| "Internal tool, security doesn't matter" |
Internal tools get compromised; attackers target the weakest link |
| "We'll add security later" |
Retrofitting is 10x harder than building it in |
| "No one would exploit this" |
Automated scanners will; security-by-obscurity is not security |
| "Framework handles security" |
Frameworks provide tools, not guarantees |
| "It's a prototype" |
Prototypes become production; habits compound |
1---2name: harden3effort: xhigh4description: Harden code proactively against vulnerabilities at the boundary where untrusted input enters the system. Use when implementing auth, handling user input, storing or transmitting sensitive data, integrating external APIs, adding file uploads, or any code that crosses a trust boundary. Don't use for reactive secret scanning (use `safe-repo`) or dependency CVE checks (use `deps-audit`).5---67# Harden89Security as a constraint on every line that touches user data, auth, or external systems. This skill is **proactive**: applied during implementation, not after. For reactive scans, use `safe-repo` (sensitive data) or `deps-audit` (CVEs).1011## Three-Tier Boundary System1213### Always do (no exceptions)1415- Validate every external input at the system boundary (route handler, API entry)16- Parameterize all database queries (never concatenate user input into SQL)17- Encode output to prevent XSS — use framework auto-escaping, don't bypass it18- HTTPS for all external communication19- Hash passwords with bcrypt/scrypt/argon2 (salt rounds ≥ 12); never plaintext20- Set security headers: CSP, HSTS, X-Frame-Options, X-Content-Type-Options21- Session cookies: `httpOnly`, `secure`, `sameSite`22- Use environment variables for secrets; reference, never inline23- Strip sensitive fields from API responses by default2425### Ask first (human approval required)2627- New authentication flow or auth logic changes28- Storing new categories of sensitive data (PII, payment)29- New external service integrations30- CORS configuration changes31- File upload handlers32- Rate-limit / throttling changes33- Granting elevated permissions or roles3435### Never do3637- Commit secrets to version control38- Log sensitive data (passwords, tokens, full PAN)39- Trust client-side validation as a security boundary40- Disable security headers for convenience41- Use `eval()` or `innerHTML` with user-provided data42- Store sessions in client-accessible storage (e.g., localStorage for auth tokens)43- Expose stack traces or internal errors to users4445See [OWASP Top 10 quick reference](references/owasp.md).4647## Input Validation at Boundaries4849Always validate at the **system boundary** (route handler, message consumer), not in business logic:5051- Schema validator (Zod, Joi, Yup, pydantic) defines the contract52- Reject with 422 + structured error before any business logic touches the data53- Trust internal code; validate only at the edges5455## File Upload Safety5657- Allowlist MIME types; deny unknown58- Enforce max size before processing59- Check magic bytes if file type is security-critical (don't trust extension or `mimetype`)60- Store outside webroot or behind authenticated access6162## Verification6364After implementing security-relevant code, confirm:6566- [ ] `deps-audit` shows no critical or high CVEs (or each is documented with review date)67- [ ] `safe-repo --diff` clean68- [ ] All user input validated at system boundaries69- [ ] Authorization checked on every protected endpoint (ownership, not just auth)70- [ ] Security headers present in response (check via DevTools or `curl -I`)71- [ ] Error responses don't expose internal details72- [ ] Rate limit active on auth endpoints7374## Common Rationalizations7576| Rationalization | Reality |77|-----------------|---------|78| "Internal tool, security doesn't matter" | Internal tools get compromised; attackers target the weakest link |79| "We'll add security later" | Retrofitting is 10x harder than building it in |80| "No one would exploit this" | Automated scanners will; security-by-obscurity is not security |81| "Framework handles security" | Frameworks provide tools, not guarantees |82| "It's a prototype" | Prototypes become production; habits compound |