Ruby 4.0 Universal RCE Deserialization Gadget Chain

Ruby 4.0 Universal RCE Deserialization Gadget Chain

A new universal gadget chain turns a single Marshal.load into command execution on Ruby 4.0.6, the latest release. It works unchanged on Ruby 3.3 and above. The chain reuses old gadgets in new ways and introduces new ones, bypassing the fixes that broke the previous 3.4 chain. It exploits a Time deserialization quirk and a directory traversal to write and execute arbitrary code.

Removing it would mean changing the way core data structures behave, which is exactly the kind of tradeoff where a gadget can be cheap to use and expensive to forbid.
  1. Nextgrid

    Doesn't this already require to be "on the other side of the airtight hatchway", or am I missing something?

    The Marshal.load docs explicitly have a warning that you should not pass it untrusted data: https://docs.ruby-lang.org/en/master/Marshal.html#module-mar...

  2. sebiw

    Which brings us to the old saying: Do not deserialize untrusted data.

    In the context of Rubygems and their specs this obviously is harder to manage but dependencies such as Rubygems are and will always be part of your app's Trusted Computing Base.

  3. schwag09

    I wrote one of the referenced posts describing the history here: https://blog.trailofbits.com/2025/08/20/marshal-madness-a-br...

    I was also part of the team that audited RubyGems.org: https://github.com/trailofbits/publications/blob/master/revi...

    Look at TOB-RGM-9 (an informational, largely out-of-scope finding) if you want to understand what could be done to mitigate some of these concerns. Nearly all of these gadget chains rely on Gem library functionality, which has this wonky .gemspec.rz metadata file that sits alongside the actual gem file. I understand that it'd be a challenging, backwards-incompatible change, but moving this file from Marshal to JSON would break a lot of these gadget chains. Perhaps there would be others, but it would raise the bar.

More from this day

2026-08-14