AI code review for Rails —
catches the mass-assignment + escape-hatch bugs.
Rails is opinionated but the opinions have escape hatches. Mass-assignment via `Model.new(params[:user])` sidesteps strong params. `.where("name = '#{name}'")` sidesteps ActiveRecord's parameterization. LGTM's Rails hints fire in the bugs + security agents whenever it sees `rails` in your Gemfile.
Auto-detected. Zero configuration.
Auto-detected when `rails` appears in your `Gemfile`. LGTM's Rails hint pack loads into the bugs + security + best-practices agents automatically.
Rails bugs that hide in plain sight
Four patterns that get past general-purpose code review because they look like idiomatic Rails. LGTM knows the shape of each.
Mass-assignment via params
`User.new(params[:user])` accepts every attribute the client sends — including `admin: true` if the model has that column. Strong params (`params.require(:user).permit(:name, :email)`) fix it, but only if every controller uses them consistently.
.where() with string interpolation
`User.where("name = '#{params[:name]}'")` is SQL injection. `.where(name: params[:name])` (hash syntax) is safe. The two forms look almost identical in code review — easy to miss the one that took a shortcut.
skip_before_action :verify_authenticity_token
Rails ships CSRF protection on by default via `protect_from_forgery`. Disabling it (usually to fix a stubborn test or make an API endpoint work) leaves the whole controller CSRF-vulnerable. Should almost always be scoped to specific actions.
N+1 queries
`@posts.each { |p| p.author.name }` triggers one query per post. `.includes(:author)` fixes it. Bullet gem catches these in dev but only for endpoints you actually hit — new code paths ship untested.
What LGTM actually catches
Three real examples — the Rails-aware bugs + security agents flag these with inline 🎯 Actionable comments and a clear "why" explanation.
class OrdersController < ApplicationController
def index
name = params[:name]
@orders = Order.where("customer_name = '#{name}'")
end
endWhat: String interpolation inside .where() clause
Why: params[:name] is attacker-controlled. Use hash form: `Order.where(customer_name: name)` — ActiveRecord parameterizes automatically. If a raw string is genuinely needed, use `.where("customer_name = ?", name)`.
class UsersController < ApplicationController
def create
@user = User.new(params[:user])
@user.save
redirect_to @user
end
endWhat: User created directly from params without strong-params filter
Why: If the User model has an `admin:boolean` column, a client can POST `user[admin]=true` and self-promote. Add a private `user_params` method with `params.require(:user).permit(:name, :email)`.
class ApiController < ApplicationController
skip_before_action :verify_authenticity_token
# every action inherits from ApiController — all CSRF-exposed.
endWhat: CSRF protection disabled at the controller level
Why: Scope this to specific actions (`only: [:webhook]`) or use `protect_from_forgery with: :null_session` for genuine API endpoints. Every action that inherits from ApiController is exposed as written.
Rails starter .lgtm.yml
Skip generated schema + migrations + vendor bundles, force the rails framework slug, bump SQL / mass-assignment / CSRF to critical.
version: 1
paths:
- pattern: "db/schema.rb"
skip: true
- pattern: "db/migrate/**"
skip: true
- pattern: "vendor/**"
skip: true
frameworks:
- "rails"
severity_overrides:
sql-injection: "critical"
mass-assignment: "critical"
csrf-disabled: "critical"
auto_approve_docs_only: true
Commit as .lgtm.yml at your repo root, flip the Enable .lgtm.yml toggle in Repo Settings. Next PR picks it up. See all recipes →
What ships on every Rails review
Same pipeline that reviews everything else on LGTM — the Railshints just tune each agent's attention.
6 agents in parallel
Bugs, Security, Performance, Readability, Best-practices, Documentation. Each with framework-specific hints when LGTM detects your stack.
16 CI/CD detectors
LGTM Security scans your GitHub Actions, Dockerfiles, and lockfiles alongside the code review. Merge-blocking Check Run on block-level findings.
Adversarial verifier
Every finding is refuted by a skeptic LLM before it posts. Only survivors reach your PR. Kills the confident-hallucination class of false positives.
Try LGTM on your Rails repo
Free tier: 20 reviews / month, all 6 agents, all 16 security detectors. BYOK OpenAI or Anthropic. No card required.