Ruby 4.0 Universal RCE Deserialization Gadget Chain - elttam
Skip to main content
Important Update Banner<br>Close Announcement Banner
By
Luke Jahnke
August 14, 2026
Ruby 4.0 Universal RCE Deserialization Gadget Chain<br>A new universal chain that turns a single Marshal.load into command execution on Ruby 4.0.6, the most recent release.
web
ruby
deserialisation
On This Page
TOC Element
Share:
Introduction<br>On August 5, 2026, OpenAI disclosed that a collective of AI agents under evaluation had broken out of their sandboxes and taken admin control of the cluster they were running on. It got there, in part, by exploiting Ruby deserialization to execute commands. That caught our attention, because in 2018 we published the first universal RCE deserialization gadget chain for Ruby, built entirely from the standard library with no dependencies. That chain works only against Ruby versions up to 2.6.10, and the most recent public chain only works up to 3.4-rc.<br>This post releases a new universal chain that turns a single Marshal.load into command execution on Ruby 4.0.6, the most recent release at the time of writing, and works unchanged as far back as 3.3. The chain is built with new gadgets from untapped sources as well as old gadgets put to new use.
Background<br>Serialization is the process of converting an object into a series of bytes which can then be transferred over a network or stored on the filesystem or in a database. These bytes include all the information required to reconstruct the original object. This reconstruction process is called deserialization. Each programming language typically has its own native serialization format and may refer to this process by a name other than serialization/deserialization. In the case of Ruby, the terms marshalling and unmarshalling are commonly used, and the operations are provided by Marshal.dump and Marshal.load.<br>Thirteen years of Ruby deserialization<br>Universal Ruby deserialization gadget chains begin in 2018, built on earlier research into application specific chains against Ruby on Rails, and that universal work then fed back into the application specific chains that came after it. Several of the milestones below supply pieces that this chain builds on.<br>January 10, 2013 - Rails 3.2.10 Remote Code Execution by Hailey Somerville<br>January 31, 2013 - Ruby bug tracker issue by Hailey Somerville<br>May 6, 2016 - Attacking Ruby on Rails Applications by joernchen of Phenoelit<br>November 8, 2018 - Ruby 2.x Universal RCE Deserialization Gadget Chain by Luke Jahnke (elttam)<br>January 2, 2019 - CVE-2019-5420 by ooooooo_q<br>March 2, 2019 - Universal RCE with Ruby YAML.load by Etienne Stalmans<br>June 20, 2019 - Remote Code Execution via Ruby on Rails Active Storage Insecure Deserialization by Sivathmican Sivakumaran and Pengsu Cheng (Trend Micro Security Research Team)<br>January 7, 2021 - Universal Deserialisation Gadget for Ruby 2.x-3.x by William Bowling<br>January 9, 2021 - Universal RCE with Ruby YAML.load (versions > 2.7) by Etienne Stalmans<br>March 28, 2022 - Ruby Deserialization - Gadget on Rails by httpvoid<br>April 4, 2022 - Round Two: An Updated Universal Deserialisation Gadget for Ruby 2.x-3.x by William Bowling<br>May 17, 2022 - Ruby Vulnerabilities: Exploiting Dangerous Open, Send and Deserialization Operations by Ben Lincoln (Bishop Fox)<br>March 13, 2024 - Discovering Deserialization Gadget Chains in Rubyland by Alex Leahu (Include Security)<br>June 20, 2024 - Execute commands by sending JSON? Learn how unsafe deserialization vulnerabilities work in Ruby projects by Peter Stöckli (GitHub)<br>October 17, 2024 - Updated ruby gadget for marshal loading by Leonardo Giovannini (Doyensec)<br>November 24, 2024 - Ruby 3.4 Universal RCE Deserialization Gadget Chain by Luke Jahnke<br>December 3, 2024 - Gem::SafeMarshal escape by Luke Jahnke<br>August 20, 2025 - Marshal madness: A brief history of Ruby deserialization exploits by Matt Schwager (Trail of Bits)<br>August 5, 2026 - Disclosure of in-the-wild exploitation of Ruby (JRuby) deserialization by autonomous AI agents, disclosed by OpenAI at Black Hat USA 2026<br>2026 - Ruby 4.0 Universal RCE Deserialization Gadget Chain by Luke Jahnke (this post)<br>How the 3.4 chain broke<br>The most recent public chain, published in late 2024, reached command execution on Ruby 3.4-rc with this payload:
Marshal.dump(<br>Gem::SpecFetcher,<br>to_s_wrapper(<br>call_url_and_create_folder(<br>"rubygems.org/quick/Marshal.4.8/bundler-2.2.27.gemspec.rz"<br>),<br>to_s_wrapper(exec_gadget)
Ten days after it was published, two commits landed in RubyGems that removed the gadgets it relied on, each citing the writeup as motivation. Both shipped in Ruby 3.4.0, which is why the chain works against the release candidate but not against the release.<br>The first commit, 62b49465f8, is titled "Improve type checking in marshal_load methods" and notes that it "Makes it harder to use those classes as gadgets".<br>Gem::Version#marshal_load had passed the deserialized value straight to the constructor without validation, where...