CVE-2026-66066: Rails Active Storage Arbitrary File Read and RCE
How an unsafe libvips default in Active Storage lets an unauthenticated attacker read server files and escalate to remote code execution

On July 29, 2026, the Ruby on Rails security team published CVE-2026-66066, a Critical arbitrary file read and remote code execution flaw in Active Storage variant processing, disclosed through GitHub Security Advisory GHSA-xr9x-r78c-5hrm. GitHub, as CNA, scored it 9.5 on CVSS v4 (CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H). The bug (CWE-1188, insecure default initialization) is that Active Storage hands untrusted uploads to libvips without disabling libvips' "unfuzzed" image loaders, so an unauthenticated attacker who uploads a crafted file and triggers variant generation can read arbitrary files on the server, including the process environment that holds secret_key_base and service credentials. It affects activestorage below 7.2.3.2, 8.0 through 8.0.5.0, and 8.1 through 8.1.3.0 in their default configuration, plus 6.x only where the vips processor was enabled manually. Rails shipped fixes in 7.2.3.2, 8.0.5.1, and 8.1.3.1; the 7.1, 7.0, and 6.x lines are end of life with no OSS fix available.
Affected and unsupported? See NES for Rails.
The Ethiack research team, who discovered and reported the flaw, named it KindaRails2Shell and estimate 500,000+ sites are potentially exposed. Because Active Storage with the vips processor is the default in official Rails Docker images and on Debian/Ubuntu, a large share of production Rails apps that accept image uploads are in scope.
What is CVE-2026-66066?
This is an insecure-default vulnerability (CWE-1188) in how Active Storage processes image variants.
Active Storage generates image variants (thumbnails, avatars, resized previews) through libvips, which reads and writes formats through "loaders" and "savers" backed by third-party libraries. libvips flags a subset of these operations as "unfuzzed": they were never hardened against malicious input and are unsafe to run on untrusted content. Several of them handle formats that have nothing to do with web images.
Active Storage never disabled those unfuzzed operations. So when an application accepts an uploaded file and later builds a variant from it, an attacker who controls the upload can steer processing into an unfuzzed loader. Ethiack and GMO Flatt Security independently reported a chain in which a crafted file causes libvips to read the contents of arbitrary files on the application's filesystem and return them, which the Rails maintainers confirm is not assumed to be the only such chain.
The vulnerable default is set by config.active_storage.variant_processor = :vips, which load_defaults 7.0 turned on and no later default has changed. That is why Rails 7.0 and up are affected out of the box, and Rails 6.x is affected only if someone opted into vips manually.
Severity and exploit conditions
GitHub scored this Critical at CVSS v4 9.5. NVD had not yet published its own analysis at the time of writing.
The PR:N metric is why this is treated as unauthenticated: in the reported scenarios no login is required. The AT:P metric is the real gate. You are exposed only if all of these hold:
- Active Storage uses the vips processor (default on Rails 7.0+).
- The application accepts image uploads from untrusted users, through a feature or direct uploads.
- The app later generates a variant from that upload (avatars, thumbnails, and previews all qualify).
- The libvips build is linked against the affected third-party loaders.
Exploitation status
There is no public proof of concept as of this writing. The Rails maintainers and Ethiack have both intentionally withheld the technical chain, the PoC, and the RCE details to give operators time to patch. That is not a reason to wait. Ethiack's own guidance is blunt: once patches ship and diffs go public, an attacker with modern tooling can reconstruct the chain quickly, so the safe assumption is that the window closes fast. Patch now, before the write-up lands.
What an attacker can do
A successful attack reads files off the application server as the user running the Active Storage worker, and from there escalates. Concretely:
- Read secret_key_base out of the process environment. With that, an attacker can forge signed and encrypted cookies, sessions, signed global IDs, and Active Storage URLs.
- Read the Rails master key (config/master.key or the RAILS_MASTER_KEY environment variable) and decrypt everything in config/credentials.yml.enc.
- Read Active Storage service credentials (S3, GCS, or Azure keys), database credentials, and API tokens for any third-party service the app talks to.
- Use those stolen secrets for remote code execution on the app host and lateral movement into the connected systems whose credentials just leaked.
This is why the Rails advisory pairs the upgrade with mandatory secret rotation. Closing the hole does not un-leak a secret that was already exfiltrated.
Who is affected?
The flaw lives in the activestorage gem. The default fix path for every affected line is to move to 7.2.3.2 or later, because Rails did not ship a patched release on the 7.1, 7.0, or 6.x lines.
Rails 6.x does not ship vips as the default, so a stock 6.x install is not exposed. A 6.x app is only in scope if someone set config.active_storage.variant_processor = :vips by hand and accepts untrusted image uploads.
One EOL note that catches people: Rails 7.2 is still in upstream support, but only until August 9, 2026. Landing on 7.2.3.2 closes this vulnerability, but 7.2 reaches end of life within days of this disclosure, so treat it as a stopgap and not a destination. Source dates are from endoflife.date/rails. For the broader 2026 EOL picture, see Ruby on Rails end-of-life dates.
Mitigation guidance
There are two moving parts here that people miss: the gem upgrade and the libvips floor. The Rails fix depends on libvips being 8.13 or newer, because older libvips cannot disable the unfuzzed operations at all. On libvips below 8.13, a patched Active Storage will raise an exception on boot rather than run in an unsecurable state.
Rotate every secret the app process can read. Upgrading does not undo a secret that was already exfiltrated. Rotate secret_key_base, the master key and everything config/credentials.yml.enc decrypts, Active Storage service keys (S3, GCS, Azure), database credentials, and third-party tokens. Note that rotating secret_key_base expires active sessions and invalidates existing signed and encrypted cookies, signed global IDs, and Active Storage URLs. Do not keep an exposed secret as a fallback.
Related CVEs and HeroDevs Rails coverage
For context on running EOL Rails safely:
- Ruby on Rails end-of-life dates: what you need to know
- The dual Ruby and Rails EOL problem enterprises face in 2026
- Weighing your legacy Rails options: upgrade, switch, or extended support
Taking action
CVE-2026-66066 is a clean, unauthenticated, Critical path from an image upload to your application's secrets and, from there, to code execution and lateral movement. If you run Active Storage with the vips processor and accept image uploads, you are in scope until you upgrade.
If you are on a supported line, patch to 7.2.3.2, 8.0.5.1, or 8.1.3.1, confirm libvips is 8.13 or newer, and rotate every secret the app can read. Do it before the technical write-up publishes on August 28.
If you are on Rails 7.1, 7.0, or 6.x, there is no upstream OSS fix, and the only official remediation is a major-version upgrade that many production applications cannot land on the timeline this vulnerability demands. NES for Rails provides a drop-in remediation for CVE-2026-66066 on those EOL lines, so you can close the vulnerability now and plan your migration on your own schedule rather than under an active-disclosure clock.
Read the upstream advisory at GHSA-xr9x-r78c-5hrm and the discovery write-up from Ethiack.
Resources
View All Articles
.png)
.png)
