SECURITY ADVISORY / 01

CVE-2026-66066 Exploit & Vulnerability Analysis

Complete CVE-2026-66066 security advisory with proof of concept (PoC), exploit details, and patch analysis for rails.

rails products NVD ↗
Exploit PoC Vulnerability Patch Analysis

The Exploit

An attacker with the ability to upload or process an untrusted image file (BMP, ICO, PSD, SVG, JPEG XL, JPEG 2000, Netpbm, FITS, JXL) through a Rails Active Storage application running Rails < 8.1.3.1 can trigger arbitrary code execution during image processing. No authentication is required if the application accepts file uploads from anonymous users.

## Attacker uploads a malicious BMP file via a public endpoint
curl -X POST https://target.rails.app/attachments \
  -F "[email protected]" \
  -F "content_type=image/bmp"

## The application processes the image using libvips without blocking unfuzzed loaders
## BMP is an unfuzzed loader in libvips — processing triggers memory corruption
## or code execution via crafted BMP headers

## Attacker observes: 
## - 500 error with stack trace showing libvips processing, or
## - Successful response followed by arbitrary command execution on the server

The application silently calls Vips::Image.new(file_path) or similar during image validation, attachment processing, or thumbnail generation. Because the vulnerable Rails version does not call Vips.block_untrusted(true) at boot, libvips loads and executes the unfuzzed BMP decoder against attacker-controlled bytes, crossing the trust boundary from untrusted input to arbitrary code.


What the Patch Did

Before:

## Rails 8.1.3.0 and earlier
## No mitigation — libvips unfuzzed loaders enabled by default
## Active Storage processes images directly:
image = Vips::Image.new_from_file(attachment.path)
## BMP, ICO, PSD, SVG, JPEG XL, JPEG 2000, Netpbm, FITS, JXL loaders run unfuzzed

After:

## Rails 8.1.3.1 (July 29, 2026)
Vips.block_untrusted(true)
## Disables all unfuzzed/untrusted image loaders and savers at boot
## Applications needing specific loaders must explicitly re-enable in initializer:
## Vips.block_untrusted(true, libvips_unsafe_loader: true)

The patch added a single security control: Vips.block_untrusted(true) invocation during Rails initialization. This call instructs the libvips C library to reject any format marked as "unfuzzed" (i.e., not fuzz-tested for memory safety). The fix enforces a deny-by-default stance on untrusted image formats, requiring explicit opt-in rather than silent processing.


Root Cause

CWE-94: Improper Control of Generation of Code ('Code Injection') — libvips's unfuzzed loaders contain memory-safety bugs triggered by crafted image headers. The vulnerability exists because Active Storage in Rails < 8.1.3.1 performs image processing without restricting which decoders libvips may use. When an attacker uploads a BMP, ICO, PSD, or other unfuzzed format, the request flows through the attachment controller → storage backend → Vips::Image.new() or similar. At the libvips C layer, the unfuzzed decoder runs against untrusted bytes without bounds checking, allowing heap overflow, use-after-free, or other memory corruption that translates to RCE. The trust boundary is crossed at the moment Vips.block_untrusted() is not called—there is no enforcement that separates trusted image formats from untrusted ones.


Why It Works

The load-bearing line is Vips.block_untrusted(true). Removing it restores the vulnerability immediately: libvips will again attempt to decode any format, including unfuzzed ones. The patch succeeds because it flips the default from "trust all loaders" to "trust none" — a least-privilege approach. The secondary documentation about re-enabling loaders in an initializer exists to preserve backwards compatibility for applications that genuinely need PSD or JXL support and have validated their input or accepted the risk. The changelog entry itself (quoted in the patch evidence) serves as defence-in-depth by alerting maintainers to the issue and the mitigation strategy, ensuring those who run Rails 8.1.3.1 understand why their BMP processing might suddenly fail and how to recover if needed.


Hardening Checklist

  • Call Vips.block_untrusted(true) at application boot (Rails initializer or equivalent). Do not rely on default settings; explicitly deny untrusted formats in every Ruby on Rails or libvips-using application.
  • Validate image MIME type and magic bytes using a library like ruby-magic or fastimage before passing the file to libvips; reject BMP, ICO, PSD, SVG, JPEG XL, JPEG 2000, Netpbm, FITS, and JXL unless explicitly required by business logic.
  • Re-enable unfuzzed loaders only in a scoped initializer with a comment justifying the decision; audit that initializer quarterly to ensure the justification still holds.
  • Use a dedicated image processing worker process (Sidekiq, DelayedJob) rather than processing in the web server, so memory corruption crashes the worker, not the main application.
  • Monitor libvips security advisories and subscribe to Rails security announcements; unfuzzed formats may change as libvips continues development.

References

  • https://nvd.nist.gov/vuln/detail/CVE-2026-66066
  • Rails Security Advisories: GHSA-xr9x-r78c-5hrm (libvips unfuzzed loaders)
  • libvips documentation: Vips.block_untrusted() API reference

Frequently asked questions about CVE-2026-66066

What is CVE-2026-66066?

CVE-2026-66066 is a security vulnerability identified in rails. This security advisory provides detailed technical analysis of the vulnerability, exploit methodology, affected versions, and complete remediation guidance.

Is there a PoC (proof of concept) for CVE-2026-66066?

Yes. This writeup includes proof-of-concept details and a technical exploit breakdown for CVE-2026-66066. Review the analysis sections above for the PoC walkthrough and code examples.

How does CVE-2026-66066 get exploited?

The technical analysis section explains the vulnerability mechanics, attack vectors, and exploitation methodology affecting rails. PatchLeaks publishes this information for defensive and educational purposes.

What products and versions are affected by CVE-2026-66066?

CVE-2026-66066 affects rails. Check the affected-versions section of this advisory for specific version ranges, vulnerable configurations, and compatibility information.

How do I fix or patch CVE-2026-66066?

The patch analysis section provides guidance on updating to patched versions, applying workarounds, and implementing compensating controls for rails.

What is the CVSS score for CVE-2026-66066?

The severity rating and CVSS scoring for CVE-2026-66066 affecting rails is documented in the vulnerability details section. Refer to the NVD entry for the current authoritative score.