agentleFS
ashrafiucseashrafiucse/security-audit-skills/skills/rails-security/SKILL.md

rails-security

Skill2 starsChanged 49 days agoMITView on GitHub

Audits Ruby on Rails applications for framework-specific vulnerabilities — SQL injection via interpolated where/order/find_by_sql, mass assignment through params.permit!, XSS via raw/html_safe/<%==, CSRF skips (protect_from_forgery absent, skip_before_action), missing authenticate/authorize before_actions, send_file/IO path traversal, open redirects via redirect_to(params), Marshal/Oj unsafe deserialization, send/public_send with params, committed secret_key_base, and force_ssl disabled. Use when the project has a Gemfile with rails or app/controllers.

3 other projects use a version of this.

Adopted by

Most recently taken up by

The file

Files
SKILL.md

Rails Security

Step 0 — Detect

rg -n "^\s*gem ['\"]rails" -g 'Gemfile'
ls app/controllers config 2>/dev/null

Record Rails version (Gemfile.lock), auth stack (Devise/etc.), deployment hints.

Step 1 — SQL injection

rg -n "where\([\"'].*#\{|order\(params|find_by_sql|group\(params|pluck\(params|select\(params" app/
  • where("name = '#{params[:name]}'") → Critical
  • order(params[:sort]) / pluck(params[:col]) — column names can't be bound → High (allowlist required)
  • Safe counterparts: where(name: params[:name]), where("name = ?", ...) → note as positives

Step 2 — Mass assignment

rg -n "permit!|params\[:user\]$|\.update_attributes" app/
  • params.permit! (or raw params hash) into new/update on models with role columns (admin, role, credits) → Critical
  • Narrow permit(:name, :email) → safe; check listed columns for role leakage

Step 3 — XSS

rg -n "<%=\s*raw\b|\.html_safe|<%==" app/ app/views/
  • raw/.html_safe/<%== on user-derived values → direction-triaged (ERB <%= %> escapes by default)

Census, don't sample: disposition every hit. Severity by privilege direction per ../injection-flaws/SKILL.md (XSS table) — raw @user.bio where the bio is student-authored and the view is staff-facing = Critical.

Step 4 — CSRF & authz

rg -n "protect_from_forgery" app/controllers/application_controller.rb
rg -n "skip_before_action :verify_authenticity|skip_forgery_protection" app/
rg -n "before_action :authenticate|before_action :authorize" app/controllers/ | head
  • No protect_from_forgery in ApplicationController (and Rails new-app default absent in API mode with cookie sessions) → High
  • skip_before_action :verify_authenticity_token on non-webhook controllers → High
  • Controllers with mutations but no authenticate_*! before_action → High
  • Devise current_user absent + Model.find(params[:id]) in show/edit → IDOR, High

Step 5 — Files, redirects, dispatch

rg -n "send_file|File\.read|IO\.foreach|File\.open" app/
rg -n "redirect_to\s+(params|request\.referer)" app/
rg -n "\bsend\(|public_send\(" app/ | rg "params" | head
  • send_file(params[:path]) → traversal, High
  • render file: params[:path] → arbitrary file read (CVE-2019-5418 pattern — Action View reads and returns the file); fixed rails versions still make this a design bug → High
  • render file: with a first-party literal (Rails.root.join(...)) is fine
  • redirect_to(params[:return_to]) → open redirect (phishing/SSRF in OAuth flows), Medium/High
  • send(params[:method]) → arbitrary method dispatch, High

Step 6 — Deserialization & config

rg -n "Marshal\.load|Oj\.load|YAML\.load\(" app/ config/
rg -n "secret_key_base" config/ -g '!*.lock' | head
rg -n "force_ssl" config/environments/
  • Marshal.load / Oj.load(mode: :object) / YAML.load (non-safe) on external data → Critical
  • secret_key_base committed in secrets.yml/initializers → Critical (session forgery)
  • config.force_ssl = false in production.rb → Medium

Reporting

Severity table above; fixes are idiomatic one-liners (where(hash:), permit lists, redirect_to allowlist). Note strong-params/ORM positives. Dependency CVEs via ../dependency-vulns/SKILL.md.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.