$npx -y skills add ThibautBaissac/rails_ai_agents --skill security-auditAudits Rails application security against OWASP Top 10, detects vulnerabilities with Brakeman, and verifies Pundit authorization policies. Use when the user wants a security audit, vulnerability scan, or when user mentions security, OWASP, Brakeman, XSS, SQL injection, or authori
| 1 | # Security Audit |
| 2 | |
| 3 | You are an expert in Rails application security, OWASP Top 10, and common web vulnerabilities. |
| 4 | You NEVER modify credentials, secrets, or production files. |
| 5 | |
| 6 | ## Audit Process |
| 7 | |
| 8 | ### Step 1: Run Security Tools |
| 9 | |
| 10 | ```bash |
| 11 | bin/brakeman |
| 12 | bin/bundler-audit check --update |
| 13 | bundle exec rspec spec/policies/ |
| 14 | ``` |
| 15 | |
| 16 | ### Step 2: Manual Code Review |
| 17 | |
| 18 | Audit all files in `app/controllers/`, `app/models/`, `app/services/`, |
| 19 | `app/queries/`, `app/forms/`, `app/views/`, `app/policies/`, `config/`. |
| 20 | |
| 21 | ### Step 3: Report Findings |
| 22 | |
| 23 | Format: **Vulnerability** → **Location** (file:line) → **Risk** → **Fix** (code example) |
| 24 | Prioritize: P0 (critical) → P1 (high) → P2 (medium) → P3 (low) |
| 25 | |
| 26 | ## OWASP Top 10 — Rails Patterns |
| 27 | |
| 28 | ### 1. Injection (SQL, Command) |
| 29 | ```ruby |
| 30 | # Bad — SQL Injection |
| 31 | User.where("email = '#{params[:email]}'") |
| 32 | |
| 33 | # Good — Bound parameters |
| 34 | User.where(email: params[:email]) |
| 35 | ``` |
| 36 | |
| 37 | ### 2. Broken Authentication |
| 38 | ```ruby |
| 39 | # Bad — Predictable token |
| 40 | user.update(reset_token: SecureRandom.hex(4)) |
| 41 | |
| 42 | # Good — Sufficiently long token |
| 43 | user.update(reset_token: SecureRandom.urlsafe_base64(32)) |
| 44 | ``` |
| 45 | |
| 46 | ### 3. Sensitive Data Exposure |
| 47 | ```ruby |
| 48 | # Bad — Logging sensitive data |
| 49 | Rails.logger.info("Password: #{password}") |
| 50 | |
| 51 | # Good — Filter sensitive params |
| 52 | Rails.application.config.filter_parameters += [:password, :token, :secret] |
| 53 | ``` |
| 54 | |
| 55 | ### 4. XXE |
| 56 | ```ruby |
| 57 | # Bad |
| 58 | Nokogiri::XML(user_input) |
| 59 | |
| 60 | # Good |
| 61 | Nokogiri::XML(user_input) { |config| config.nonet.noent } |
| 62 | ``` |
| 63 | |
| 64 | ### 5. Broken Access Control |
| 65 | ```ruby |
| 66 | # Bad — No authorization |
| 67 | @entity = Entity.find(params[:id]) |
| 68 | |
| 69 | # Good — Pundit |
| 70 | @entity = Entity.find(params[:id]) |
| 71 | authorize @entity |
| 72 | ``` |
| 73 | |
| 74 | ### 6. Security Misconfiguration |
| 75 | ```ruby |
| 76 | # production.rb |
| 77 | config.force_ssl = true |
| 78 | ``` |
| 79 | |
| 80 | ### 7. XSS |
| 81 | ```erb |
| 82 | <%# Bad %> |
| 83 | <%= raw user_input %> |
| 84 | <%= user_input.html_safe %> |
| 85 | |
| 86 | <%# Good %> |
| 87 | <%= user_input %> |
| 88 | <%= sanitize(user_input) %> |
| 89 | ``` |
| 90 | |
| 91 | ### 8. Insecure Deserialization |
| 92 | ```ruby |
| 93 | # Bad |
| 94 | YAML.load(user_input) |
| 95 | |
| 96 | # Good |
| 97 | YAML.safe_load(user_input, permitted_classes: [Symbol, Date]) |
| 98 | ``` |
| 99 | |
| 100 | ### 9. Vulnerable Dependencies |
| 101 | ```bash |
| 102 | bin/bundler-audit check --update |
| 103 | ``` |
| 104 | |
| 105 | ### 10. Insufficient Logging |
| 106 | ```ruby |
| 107 | Rails.logger.warn("Failed login for #{email} from #{request.remote_ip}") |
| 108 | ``` |
| 109 | |
| 110 | ## Security Checklist |
| 111 | |
| 112 | ### Configuration |
| 113 | - [ ] `config.force_ssl = true` in production |
| 114 | - [ ] CSRF protection enabled |
| 115 | - [ ] Content Security Policy configured |
| 116 | - [ ] Sensitive parameters filtered from logs |
| 117 | - [ ] Secure sessions (httponly, secure, same_site) |
| 118 | |
| 119 | ### Code |
| 120 | - [ ] Strong Parameters on all controllers |
| 121 | - [ ] Pundit `authorize` on all actions |
| 122 | - [ ] No `html_safe`/`raw` on user input |
| 123 | - [ ] Parameterized SQL queries only |
| 124 | - [ ] File upload validation |
| 125 | |
| 126 | ### Dependencies |
| 127 | - [ ] Bundler Audit clean |
| 128 | - [ ] Gems up to date |
| 129 | - [ ] No abandoned gems |