Fix cards for Ruby on Rails

A01:2025 Broken Access Control

  • Cross-site request forgery (CSRF)CWE-352

    Keep the protection ActionController::Base already has (load_defaults 5.2 adds protect_from_forgery with: :exception): forms from form_with carry the token, fetch() sends csrf_meta_tags' token in X-CSRF-Token, and Rails also checks Origin.

  • Missing object-level authorization (IDOR and BOLA)CWE-862 · CWE-639 · CWE-863

    Load records through a scope built from the signed-in user, never by ID alone: visible_invoices(current_user).find(params[:id]), where the scope applies the tenant to everyone and the owner to members.

  • Open redirectCWE-601

    Keep Rails' own check on: redirect_to url_from(params[:next]) || account_path, with other trusted hosts in config.action_controller.allowed_redirect_hosts. url_from returns the value only for a path on this site or an allowed host, and redirect_to raises for anything else.

  • Path traversalCWE-22 · CWE-23 · CWE-36 · CWE-59

    Resolve the requested path with File.realpath(File.join(base, requested)), which collapses ../ and follows symlinks, and serve it only if it starts with the realpath of the base plus a separator.

  • Server-side request forgery (SSRF)CWE-918

    Attach the policy to the connection, not the host name string.

A05:2025 Injection

  • Cross-site scripting (XSS)CWE-79

    Let ERB escape: <%= @name %> and tag helpers such as image_tag(..., alt: @name) escape & < > " and ', unless the value is html_safe.

  • CSV formula injectionCWE-1236 · CWE-74

    Before writing a user-controlled value to a cell, prefix it with a single quote when it begins with any formula trigger: =, +, -, @, tab (0x09) or carriage return (0x0D).

  • SQL injectionCWE-89

    Pass values to Active Record as hash conditions or placeholders: where(customers: { name: name }, status: status) or where("customers.name = ?", name).

A06:2025 Insecure Design

  • Unrestricted file uploadCWE-434 · CWE-646 · CWE-73 · CWE-770

    Decide the type from the bytes, and never serve uploads from the web root.

A07:2025 Authentication Failures

  • Missing authentication for a critical functionCWE-306 · CWE-287 · CWE-288 · CWE-290

    Keep the before_action :authenticate in ApplicationController so every action needs it, and skip_before_action only on the public health route.

  • Session fixation and session cookiesCWE-384 · CWE-613 · CWE-614 · CWE-1004 · CWE-1275

    Call reset_session at sign-in, not session.clear: only reset_session issues a new session ID.

A08:2025 Software or Data Integrity Failures

  • Insecure deserializationCWE-502

    Do not rebuild objects from the token: Base64-decode it and JSON.parse the bytes, then copy only the fields you expect into a fixed shape; Marshal.load runs code chosen by the bytes.

  • Mass assignment (over-posting)CWE-915

    Pass only an allowlist to the model: user.update(params.permit(:display_name, :bio)), or params.expect(user: [:display_name, :bio]) for a nested body.

Not covered in Rails yet

These weaknesses have fix cards in other stacks but not in this one.

Supported versions

Each minor release series gets bug fixes for one year and security fixes for two years after its first release; a new minor release is planned about every six months, and if none ships within a year the previous series stays supported until one does. Unsupported series get no new releases. Rails support policy.

Rails
VersionLatestStatusReleasedEnd of support
8.18.1.4Supportedrubyonrails.org lists bug fixes until 10 October 2026 and security fixes until 10 October 2027. Rails 8.2 had not been released on 11 October 2026, and the policy extends the previous release's support when no new feature release ships within a year. The cards use 8.1.4.22 October 202510 October 2027
8.08.0.5.1Security fixes onlyBug fixes ended on 7 May 2026; security fixes end on 7 November 2026.7 November 20247 November 2026
7.27.2.4End of lifeSecurity support ended on 9 August 2026, two years after 7.2.0 under the maintenance policy. 7.2.3.2 (29 July 2026) was the last 7.2 security release, and 7.2.4 (24 September 2026), a bug-fix release, the last 7.2 release; fixes now go to 8.0 and 8.1 only.9 August 20249 August 2026
Ruby
VersionLatestStatusReleasedEnd of support
4.04.0.7Supported25 December 2025No date set
3.43.4.11Supported25 December 2024No date set
3.33.3.12Security fixes only25 December 202331 March 2027
3.23.2.11End of life25 December 20221 April 2026

ruby-lang.org lists each branch as in normal maintenance (bug and security fixes), security maintenance (security fixes only) or end of life, with its expected end date. Rails 8.1 needs Ruby 3.2.0 or later, and Ruby 3.2 reached its end of life on 1 April 2026. Ruby release schedule

How the fix cards choose versions

Minimum secure versions

The lowest release in each supported line that fixes every published advisory listed here. Anything older is missing a security fix.

PackageAt leastWhy
rails8.1.3.1 or 8.0.5.1 (7.2.3.2 on the unsupported 7.2 line)CVE-2026-66066 (critical): with libvips image variants and untrusted uploads, Active Storage can be made to read any file, secret_key_base included. Also run libvips 8.13 or later, and rotate secrets if exposed. Advisory
rails8.1.2.1, 8.0.4.1 or 7.2.3.1Ten advisories of 23 March 2026, including XSS in Action View tag helpers and SafeBuffer#% (CVE-2026-33168, CVE-2026-33170) and path traversal in Active Storage's DiskService (CVE-2026-33195). Advisory
ruby4.0.7, 3.4.11, or 3.3.12 with the resolv gem 0.3.2resolv CVE-2026-80212 and CVE-2026-80213 (27 August 2026): 4.0.7 and 3.4.11 bundle the fixed resolv 0.7.2; 3.3.12 still bundles 0.3.1, so update that gem. Advisory

Middleware and security order

  1. ActionDispatch::HostAuthorization: First in the stack; it checks the Host header against config.hosts, which is empty, so off, outside development until you set it.
  2. ActionDispatch::SSL: Added by config.force_ssl = true: redirects HTTP to HTTPS, sends HSTS and marks cookies Secure. Set config.assume_ssl = true too when a proxy terminates TLS.
  3. ActionDispatch::Cookies, the session store, ActionDispatch::Flash: Cookies are signed or encrypted with secret_key_base; the session store (cookie store by default) comes after them.
  4. ActionDispatch::ContentSecurityPolicy::Middleware: Sends the policy from config.content_security_policy, which a new app leaves commented out.
  5. Controller callbacks: protect_from_forgery with: :exception (added to ActionController::Base by load_defaults 5.2 and later), then authentication in before_action, then strong parameters and queries scoped to current_user in the action.

Secure defaults and settings

SettingValueWhy
config.force_ssl, config.assume_sslCommented out in a new app's production.rb (set when the app skips Kamal)Set force_ssl = true unless a proxy you control redirects to HTTPS, sends HSTS and keeps cookies Secure.
config.hostsEmpty outside development, so no Host header checksList your host names.
config.content_security_policyNot set (the generated initializer is commented out)Define a policy; content_security_policy_nonce_generator adds nonces.
config.action_controller.action_on_open_redirect, action_on_path_relative_redirect:raise (load_defaults 7.0 and 8.1)Keep them; list other trusted hosts in allowed_redirect_hosts.
config.action_controller.default_protect_from_forgery, forgery_protection_origin_checktrue, true (load_defaults 5.2 and 5.0)Keep them.
config.action_dispatch.cookies_same_site_protection:lax (load_defaults 6.1)Keep it.
config.active_support.message_serializer:json_allow_marshal (load_defaults 7.1)Switch to :json once no Marshal-serialized messages remain; the Rails guide warns that Marshal is a deserialization vector if a signing secret leaks.
config.action_controller.action_on_unpermitted_parameters:log in development and test, false otherwiseSet :raise in development and test.
config.session_storeCookie store, _<app>_sessionStore a sign-in time and enforce an absolute timeout, or use a server-side store so sessions can be ended; call reset_session at sign-in.

Escape hatches to search for

Framework APIs that switch a protection off. Each one is sometimes needed; search for them in review and make each use justify itself.

APIRiskInstead
raw, html_safe, <%==Turns off HTML escaping.<%= %> and tag helpers; sanitize with an allowlist for rich text.
skip_forgery_protection, skip_before_action :verify_authenticity_tokenRemoves CSRF protection, also for requests that carry the session cookie.Keep it; token-authenticated APIs that never read the session cookie can use ActionController::API.
String interpolation in where, order, find_by_sql, Arel.sqlSQL injection.Hash conditions, ? placeholders and allowlisted Arel attributes for sorting.
permit!, to_unsafe_hMass assignment of every attribute.permit or expect with the keys users may set.
redirect_to params[...], allow_other_host: trueOpen redirect.url_from(params[...]) || fallback and allowed_redirect_hosts.
Rails.root.join(params[...]), send_file params[...]Path traversal; an absolute path replaces the base.Look files up by ID, or check File.realpath against the base directory.
Model.find(params[:id])IDOR for every signed-in user.Find through a scope built from current_user.

Checklist, mapped to ASVS 5.0.0

  • v5.0.0-1.2.1 Views rely on ERB escaping; no request data reaches raw, html_safe or <%==.
  • v5.0.0-3.5.1 Forgery protection is on and no controller that reads the session cookie skips it.
  • v5.0.0-8.2.2 Actions load records through scopes built from current_user.
  • v5.0.0-1.2.4 No SQL fragment is built by string interpolation.
  • v5.0.0-15.3.3 Controllers permit explicit keys; no permit! or to_unsafe_h reaches a model.
  • v5.0.0-3.7.2 Redirects to request data go through url_from, and no allow_other_host: true takes request data.
  • v5.0.0-7.2.4 Sign-in calls reset_session.
  • v5.0.0-3.4.1 config.force_ssl (or the proxy) sends HSTS for at least a year.
  • v5.0.0-3.3.1 Session and other cookies are Secure.
  • v5.0.0-13.4.2 consider_all_requests_local is false in production, so errors show the generic page.

References

  1. Rails: maintenance policy and supported releases
  2. Ruby: maintenance branches
  3. Rails Guides: Securing Rails Applications
  4. Rails Guides: configuring Rails applications (middleware and defaults)
  5. Rails Guides: Rails on Rack, the internal middleware stack
  6. GHSA-xr9x-r78c-5hrm: arbitrary file read in Active Storage variant processing (CVE-2026-66066)
  7. Rails Versions 7.2.3.1, 8.0.4.1 and 8.1.2.1 have been released (ten advisories)
  8. Rails Version 7.2.4 has been released (the last 7.2 release)

All fix cards