Safeguard
Application Security•

What belongs on a secure coding checklist for Ruby and Rails teams?

Twelve code review checks for Ruby teams, from eval and html_safe to open redirects, file paths, sessions and gem updates, each with a smell to search for.

Safeguard Security Team
5 min read

A good Ruby secure coding checklist is short enough to use in code review: search for dangerous methods, check that every record lookup is authorised, constrain redirects and file paths, protect sessions, keep secrets out of the repository, and keep gems current. Here are twelve checks, each with the code smell to grep for.

What do you search for before you read a diff?

Start with a few text searches, because they find the riskiest lines fast.

  1. Dynamic code and shell calls. OWASP's Rails cheat sheet lists the Ruby functions that build code or run commands from strings: eval, system, backticks, exec, spawn, and open with a pipe, plus several IO methods that accept a leading pipe. Its advice is that this is usually a bad idea, and that if you must, you use an allow-list and validate input thoroughly. Search for each, and treat any user-influenced argument as a defect.
  2. String-built SQL. A where clause assembled with string addition is injectable. The cheat sheet shows the fix: placeholders, and sanitize_sql_like when the value goes inside a pattern.
  3. Escaping bypasses. raw, html_safe and similar calls turn off the default output escaping. OWASP says html_safe is confusingly named and itself unsafe: it asserts that the string is safe, it does not make it so. For rich text, accept a markup language such as Markdown and disallow HTML tags.

What do you check in controllers?

  1. Authorisation per record. The cheat sheet notes that a vanilla Rails app has no built-in protection against a user changing an id in a guessable RESTful path to reach someone else's data. Authorise each action, by hand or with a resource-based library such as Pundit or CanCanCan. Ask of every find: whose record is this?
  2. Redirects. The Rails guide says passing user input directly into redirect_to is generally dangerous. Compare against an allow-list of paths or hosts.
  3. File access. send_file with a name from params lets someone pass ../../ style input and download any file. The guide recommends normalising the path and confining it to a directory, or storing files under database ids.
  4. Parameters. Permit only the attributes a form should set, and review any new permitted key like a new public API field.
  5. Forgery protection. The Rails guide says CSRF protection is on by default for newly created apps, using a security token in non-GET requests. Check nobody skipped it for an action that changes data, and remember XSS bypasses it.

What about sessions, secrets and logs?

  1. Sessions. Reset the session after sign in, as the guide recommends, to defeat fixation. Expire sessions on the server and not only in the cookie, and turn on force_ssl. The default cookie store keeps the session in an encrypted cookie, so changing secret_key_base logs everyone out and also affects other signed or encrypted data.
  2. Secrets and sensitive files. The OWASP sheet lists files that should be excluded or carefully managed, such as config/database.yml, the old secret token initializer, seed files with admin users and development databases. Use encrypted credentials.
  3. Logs. Add sensitive parameter names to filter_parameters. Rails ships defaults that partially match password, secret and token, but a field called ssn or card is yours to add.
  4. Rate limits. The guide shows a one-line rate_limit on the sessions controller to slow brute force against logins.

What about gems?

OWASP warns that most gems are not signed and that you should audit what you use and have a defined process for updating dependencies. RubyGems' own security guide adds practical controls: commit the lockfile with checksums, use bundler-audit against the advisory database in CI, give each gem an explicit source, and consider a cooldown on brand new releases. Brakeman, a static scanner for Rails apps, is also named by OWASP as a way to find XSS problems.

A constructed example

A pull request adds a "download invoice" action: send_file with a path built from params[:name], no check that the invoice belongs to the signed in user, and a redirect_to params[:return] after the download. Three checklist items fail in one diff (6, 4 and 5). The fix takes ten lines: look the invoice up through the current user's own invoices, send the stored file by id, and redirect to a named route.

What to do

  1. Put the twelve checks in your pull request template.
  2. Run Brakeman and bundler-audit in CI so the mechanical checks are automatic.
  3. Add the greps to a pre-review script.
  4. Require a second reviewer for authorisation changes.
  5. Review gems when they are added and on a schedule.
  6. Keep Rails and Ruby on supported versions.

Safeguard's code scan and dependency scanning can run these checks in pull requests, as in the pull request gate demo.

Quick check

Does html_safe sanitize a string?

No. It only marks the string as already safe, which skips escaping. Use it only on content you built yourself.

Is CSRF protection enough if the app has XSS?

No. XSS lets an attacker read the token from the page and submit the form, so it bypasses CSRF protection.

Sources

Last reviewed: 18 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.