2026-07-31 · view entry permalink →
CVE-2026-66066 — Ruby on Rails Active Storage: an unauthenticated image upload reaches arbitrary file read through libvips' unfuzzed loaders, exposing every application secret (CVSS 4.0 9.5)
The Rails security team disclosed CVE-2026-66066 on 2026-07-29, nicknamed "KindaRails2Shell" by its finders, and CERT-FR carried it the following day (CERT-FR, 2026-07-30). The defect is one of insecure defaults rather than a memory-safety bug. libvips reads and writes image formats through loaders and savers, some of which it explicitly flags "unfuzzed" — meaning the project does not consider them safe against attacker-controlled input. Active Storage, which has used libvips as its default variant processor since Rails 7.0, never disabled those operations before handing it user-supplied files. A crafted upload therefore reaches an unfuzzed loader and yields arbitrary file read in the context of the application process (Ruby on Rails security advisory, 2026-07-29).
The precondition set is narrower than "runs Rails" but wider than most operators will assume. The advisory states an application is affected if it uses libvips for Active Storage image processing — the default that load_defaults 7.0 set and that no later default has changed — and accepts image uploads from untrusted users, and it says in as many words that generating a variant is not a separate requirement. Authentication elsewhere in the application does not help, because the exposure sits in the image-processing pipeline rather than the request-authorisation layer. Ethiack notes one further precondition it is not detailing yet — that the libvips build be linked against certain third-party libraries — so not every deployment on a vulnerable version is equally reachable, and it states that applications configured for the alternative ImageMagick processor are outside this vector entirely (Ethiack, 2026-07-29).
The "possible remote code execution" in the CVE's title is a consequence rather than a direct primitive: file read as the application process exposes secret_key_base, the master key and everything credentials.yml.enc decrypts, storage and database credentials and third-party tokens, and those in turn open paths to code execution or to connected systems (Rapid7, 2026-07-30). That is why remediation does not end at the upgrade — Rapid7 advises rotating secret_key_base and every credential the process can reach on any application believed exposed, while noting that rotating it invalidates active sessions, signed and encrypted cookies, signed global IDs and existing Active Storage URLs.
Fixed releases are activestorage 7.2.3.2, 8.0.5.1 and 8.1.3.1, and the advisory is unusually blunt that the gem upgrade alone is not the fix: libvips itself must be at 8.13 or newer, because earlier versions cannot disable unfuzzed operations at all, and patched Active Storage raises an exception at boot rather than running in a configuration it cannot secure. Separately, Ethiack assesses that Rails versions 6.0.0 through 6.1.7.10 may be affected where Active Storage has been configured for libvips against its own defaults, with no fixed 6.x release available — a point Rapid7 relays with attribution to Ethiack, and which does not appear in the Rails advisory's own affected-version ranges.
No in-the-wild exploitation was reported as of 2026-07-30, and both reporting teams — Ethiack and GMO Flatt Security, who found it independently — are withholding proof-of-concept code and the full chain until no later than 2026-08-28. That is not the same as nothing public existing: Rapid7 records that public code claiming to exploit the flaw exists, while stating it is unclear how closely that code corresponds to the full attack chain reported privately to Rails (Rapid7, 2026-07-30). Ethiack's own framing is the reason this belongs in an out-of-cycle patch conversation rather than a monthly one: it tells operators to assume attackers with AI tooling can reconstruct the chain quickly once the patch diffs are public.
Detection is thin by design here, because a successful read looks like an ordinary upload. The realistic signals are on either side of the processing step: image uploads that fail or crash variant processing at anomalous rates, worker processes reading files well outside the storage tree — application configuration, environment files, key material — and any subsequent use of application secrets from a network location that has never presented them before. The last of these is the one worth instrumenting, since the value of this bug to an attacker is the credential, not the read. Verification is straightforward and worth doing before any of that: check the configured variant processor, the installed gem version against the three fixed points, and the system libvips version against the 8.13 floor.
An application is affected if it meets all of these requirements: Uses libvips for Active Storage image processing. This is config.active_storage.variant_processor = :vips, which load_defaults 7.0 set and no later default has changed. Allows image uploads from untrusted users. Generating variants is not a separate requirement.
Earlier versions of libvips (< 8.13) cannot disable unfuzzed operations at all, and Active Storage will raise an exception during boot in such an unsecurable environment.
No PoC or technical chain details from us yet, but assume attackers with AI tooling can reconstruct one quickly once patches ship and diffs go public, so don't wait to upgrade.