security-essentials
Security Essentials
Use this skill before writing ANY security-sensitive code.
Canonical FP bar: docs/fcis-engineering-rules.md — Functional Core, Imperative Shell: pure domain modules; side effects at edges. Parse/allowlist at the boundary; never trust raw maps deep in core.
RULES — Follow these with no exceptions
1. Never call String.to_atom/1 on user input — use String.to_existing_atom/1 or a whitelist case (Atom Table Exhaustion)
2. Never interpolate user input into an Ecto fragment or raw SQL — use ^value bindings, field/2, or $1/$2 placeholders (SQL Injection)
3. Never redirect to a user-controlled URL — use ~p"..." verified routes or a whitelist of allowed paths (Open Redirects)
4. Never render user content with raw/1 in HEEx — let auto-escaping run, or sanitize with HtmlSanitizeEx first (Cross-Site Scripting (XSS))
5. Never log secrets — log identifiers (user_id, email), never passwords, tokens, or PII (Sensitive Data in Logs)
6. Always compare tokens with Plug.Crypto.secure_compare/2 — never ==, which leaks length/content via timing (Timing Attacks)
7. Never disable Phoenix CSRF protection — keep :protect_from_forgery in the browser pipeline and use <.form>, not raw <form> (CSRF Protection)
8. Always authorize before returning a record — verify ownership to prevent parameter tampering and IDOR (Common Vulnerable Patterns)
9. Always run mix deps.audit && mix hex.audit && mix sobelow before merge — fail CI on any HIGH or CRITICAL finding (Dependency Auditing)