Rails CVE-2026-41316: Detection and Patch

On April 21, 2026 the Ruby team shipped Ruby 4.0.3, fixing CVE-2026-41316 - a CVSS 8.1 universal RCE chain through ERB::DeprecatedInstanceVariableProxy and Marshal.load. Advisory: GHSA-q339-8rmv-2mhv
. Every Rails app on 3.2+ is in scope.
The gadget chain #
Marshal.load deserializes arbitrary Ruby objects. ERB::DeprecatedInstanceVariableProxy is a wrapper that triggers method dispatch on to_s. Chain them: an attacker who controls one Marshal-deserialized value pivots through ERB’s instance-variable lookup into arbitrary code execution. The full gadget walkthrough is in httpvoid’s writeup
.
The vector lights up wherever your app deserializes attacker-controlled data:
- Signed cookies, if
cookies_serializeris:marshal(legacy default before Rails 4.1) - Cached fragments via
Rails.cachewith the:marshalserializer ActiveJobarguments persisted through Sidekiq / Solid Queue / DelayedJobserialize :datacolumns in Active Record without an explicit JSON coder- Any in-house code that calls
Marshal.loadon user input
No authentication required for the gadget itself - exploitability depends on whether attacker-controlled bytes reach a Marshal.load call site.
Detection #
ruby -v
# < 4.0.3 → vulnerable
# Find Marshal.load call sites
rg -n -F 'Marshal.load' --type ruby
rg -n -F 'Marshal::load' --type ruby
# Active Record serialize without explicit coder (PCRE2 lookahead)
rg -nP 'serialize\s+:\w+(?!\s*,\s*(JSON|coder))' app/models/
# Cookie serializer
rg -n 'cookies_serializer' config/
If cookies_serializer is :marshal or unset on a Rails 3.2 / 4.0 app, switch to :json or :hybrid and rotate the secret. The Rails team’s signed cookie hardening notes
cover the migration.
Patch #
Bump Ruby. Re-run the test suite. Deploy.
asdf install ruby 4.0.3 # or rbenv install 4.0.3
echo "ruby-4.0.3" > .ruby-version
bundle install
bundle exec rspec
If you can’t drop Ruby 4.0.3 in (a C extension that hasn’t been built against 4.0 yet, a CI image that’s pinned), check the advisory for the documented workaround steps. The advisory is the source of truth - copy from there, not from blog summaries.
Rails 7.0 and 7.1 are EOL #
The Rails security team shipped backports for Rails 7.2.3.1, 8.0.4.1, and 8.1.2.1 alongside Ruby 4.0.3. Rails 7.0 and 7.1 got nothing. Same outcome on the March 23 release : EOL versions skipped.
If your app is on 7.0 or 7.1:
- Upgrade to 7.2 LTS or 8.x. Realistic per-major timeline runs 2-6 weeks when test coverage is above 60%, longer below that.
- Buy backports from HeroDevs . They maintain patches for 6.0 through 7.1.
- Document the gap. Internal compliance reviews and Series A diligence will flag it; have the answer ready.
The dual Ruby-and-Rails EOL stagger is the gotcha - your Ruby may be patched while your Rails version isn’t, or vice versa. Pin both and check both whenever a CVE drops.
Subscribe to the announcement list #
Two CVE drops in 30 days (March 23, April 21) is not a coincidence. The core team has been auditing serialization paths since the 2025 Active Job Continuations rollout, and the gadget chains are cascading. Rails World 2026’s CFP made “Trust, Security, Reliability” an official conference track - which is hint enough that more disclosures land before fall.
If you’re not already on it, subscribe to rubyonrails-security and pipe it into your team’s Slack via RSS. The CVEs ship with mitigation steps; missing the announcement is the only way to be late.
The same monitoring discipline applies to your own app’s deploy log - we wrote about that in Rails 8.1 structured logging .