KindaRails2Shell: The Image Upload That Hands Attackers Your Server (CVE-2026-66066)
If your web application is built on Ruby on Rails and accepts image uploads from untrusted users, you need to act on CVE-2026-66066 today. Dubbed KindaRails2Shell, this critical vulnerability (CVSS v4 9.5) in Rails' Active Storage component lets an unauthenticated attacker read arbitrary files from your server — including the cryptographic secrets that, one step later, translate into full remote code execution. A public proof-of-concept landed July 31, and a Metasploit module was submitted August 3. The attack is now point-and-click.
What the Flaw Actually Is
Active Storage, Rails' built-in file attachment framework, uses libvips as its default image-processing backend since Rails 7.0. libvips supports a wide range of image formats — including some legacy and scientific formats that were never designed to process untrusted input. The library flags these as unfuzzed operations: format loaders that lack hardening against malicious files. The bug in CVE-2026-66066 is that Rails never told libvips to block those unsafe loaders before handing user-uploaded files to it.
The exploit takes advantage of this gap. An attacker crafts a file disguised as a MATLAB Level 5 / HDF5 container with External File List entries that point to arbitrary paths on the filesystem. When Active Storage generates a variant — a thumbnail, an avatar resize, a preview — libvips obediently parses the file, follows those pointers, and returns the contents of whatever file the attacker named. No authentication required; the only precondition is that the application has a publicly accessible upload endpoint, which is true by definition for any app that lets users upload profile photos, attachments, or media.
From File Read to Full Compromise
Arbitrary file read sounds bad. Remote code execution is what it actually enables, and the chain is short. A successful read of /proc/1/environ, config/master.key, or a .env file yields the application's secret_key_base — the master signing secret Rails uses for session cookies, signed global IDs, and serialized objects.
With secret_key_base in hand, an attacker can forge a valid session cookie carrying a serialized Ruby object of their choosing. On applications using certain serialization configurations, deserializing that object executes arbitrary code on the server. Rapid7 confirmed the full chain and published a working Metasploit module (exploit/multi/http/rails_activestorage_vips_rce) that steps through file read, secret recovery, and code execution in a single workflow.
The data exposed before you even reach RCE is significant on its own: database passwords, AWS/GCS/Azure storage credentials, API tokens for third-party services — anything the Rails process can read, the attacker can read.
How Common Is This Configuration?
Very. config.active_storage.variant_processor = :vips has been the Rails default since version 7.0, and it ships as the default in the official Rails Docker images. Debian and Ubuntu install libvips when you install the rails package. Researchers estimate more than 500,000 sites are exposed. If you stood up a Rails 7+ application using standard scaffolding or an official image and you accept file uploads, you are almost certainly running the vulnerable configuration.
ImageMagick users are not affected — the vulnerability is specific to the libvips processor path. Rails 6.x used ImageMagick by default, but 6.x has reached end of life; if you manually enabled vips on a 6.x app, you are also in scope and there is no official patch for that branch.
The Disclosure Got Complicated
Rails maintainers originally planned a coordinated disclosure with full technical details on August 28. They published the security advisory and patched versions on July 29 with attack specifics withheld. That embargo lasted approximately 48 hours. By July 31, independent researchers had reverse-engineered the vulnerability from the patch diff and published working PoC code. Maintainers responded by releasing their own technical write-up and forensic tooling the same day, reasoning that keeping details private after a public PoC exists only hurts defenders.
The Rails team published a forensic investigation repository (rails/rails-forensics-CVE-2026-66066) that 37signals extracted from their own internal investigation work. It includes a tool to determine whether your application was ever vulnerable, a detection tool to scan Active Storage data for crafted malicious files, and documentation of what database and object-store evidence does — and does not — prove about prior exploitation.
What to Do Right Now
The fix requires updates in two places, not one:
- Upgrade Rails/Active Storage to 7.2.3.2, 8.0.5.1, or 8.1.3.1. The patch adds explicit blocking of unfuzzed libvips operations before any user-supplied file is processed.
- Upgrade libvips to 8.13 or later. The Rails patch relies on
VIPS_BLOCK_UNTRUSTED, an environment variable introduced in libvips 8.13. On older libvips, the Rails-side fix has no effect. Runvips --versionto check. If you cannot upgrade libvips immediately, setVIPS_BLOCK_UNTRUSTED=1in your process environment as a temporary mitigation — it will cause some variant operations to fail, but that beats arbitrary file reads. - Rotate all secrets. Patching stops future exploitation; it does not un-expose credentials that were already read. Rotate
secret_key_base, the Rails master key, database passwords, and any third-party API tokens your application holds. Expire all active sessions after rotating session keys. - Run the forensic tools. The Rails team's
rails-forensics-CVE-2026-66066repository can tell you whether malicious files were ever submitted and what was accessed. Run it even if you believe you were not targeted — confirmation is worth the hour. - Rails 6.x users: No official patch exists. Your options are migrating to a supported branch, switching the variant processor back to ImageMagick (
config.active_storage.variant_processor = :mini_magick), or disabling image variant generation entirely until you can migrate.
The Bigger Picture
CVE-2026-66066 is a clean example of a design assumption that made sense in isolation — libvips is fast and efficient — becoming a liability at the interface between trusted library behavior and untrusted network input. Active Storage inherited a broad set of capabilities it never needed for typical web image processing and simply didn't fence them off. The fix is a few lines; discovering that the fence was missing took years.
The accelerated disclosure is also instructive. Once a patch is public, sophisticated attackers don't wait for the vendor's scheduled write-up — they diff the commit and build a PoC. A two-day embargo offered defenders almost nothing. The lesson: treat the patch release date as your effective zero-day window, not the scheduled technical disclosure date.
At Falcon Internet, we handle a lot of application deployments, and situations like this are why keeping dependency stacks current and monitoring for file-system anomalies are standard practice — not optional extras. A Metasploit module in the wild narrows the attacker skill floor considerably; defense has to be systematic to stay ahead of that.