| name | security-patterns |
| description | Quick-reference security checklist for XSS, CSRF, PII logging, console statements, multi-tenant isolation, and state machine security in Rails views, controllers, and JavaScript. Auto-activates when writing or modifying controllers, views, or JavaScript that handle user input, reviewing code for security violations, or pre-commit security verification. |
| license | MIT |
| metadata | {"version":"1.1.0","hermes":{"tags":["Security","Rails","XSS","CSRF"],"related_skills":["code-review-methodology","silent-failure-detection-patterns"]}} |
Security-First Quick Reference
All user input is untrusted. Every output must be escaped. Every state transition must be validated.
First, run Brakeman (brakeman -A) — it covers XSS, SQLi, mass-assignment, and open-redirect with far lower false-pos/neg than the greps below. This checklist is a fast manual pass and a mental model, NOT a replacement for a real SAST tool. The greps are FIRST-PASS heuristics: expect false positives and negatives, and they use GNU-grep syntax (\w, \|, \+) — on macOS/BSD use grep -E with POSIX classes.
Security Violations: Fix + Detect
| Priority | Violation | Quick Fix | Detection (first-pass heuristic) |
|---|
| 1 | Unescaped output via raw/html_safe (XSS) | Rails <%= %> auto-escapes — the risk is the ESCAPE-BYPASS: prefer plain <%= %>, avoid raw()/.html_safe/<%== %> on user data; textContent not innerHTML in JS | `grep -rE "raw( |
| 2 | Parameter values in logs (PII) | Log keys only, never values | grep -rE "logger\.(info|debug|warn).*(#\{.*params|params\.inspect|params\))" app/ |
| 3 | Missing CSRF tokens in AJAX | X-CSRF-Token header on all POST/PUT/DELETE (a global axios/fetch default counts) | `grep -rE "fetch( |
| 4 | Console/alert in production | Remove or use structured logging | grep -rE "console\.(log|error|warn|debug)" app/javascript/ |
| 5 | return false in state machines / callbacks | throw(:abort) (plain ActiveRecord callbacks, Rails 5+); throw(:halt) ONLY if the state-machine gem defines a matching catch(:halt) | Check callbacks for return false |
| 6 | Multi-tenant scoping violations | Always scope by current_tenant (e.g. current_tenant.orders, never Order.all) | grep -rEn "\b[A-Z][A-Za-z]+\.(all|where|find)\b" app/controllers/ then check each is tenant-scoped (substitute YOUR model names — never hardcode a fixed list) |
| 7 | Cache poisoning in tenant resolution | Remove caching from auth/tenant paths | Review tenant resolution for memoization or caching |
Not covered here (use Brakeman / a dedicated pass): SQL injection, mass-assignment / strong-parameters, open-redirect.
PII Fields (Never Log Values Of)
email, password, card_number, cvv, ssn, tax_id, phone, address, any params[...]