An image upload should produce an image, not read the server’s environment. CVE-2026-66066 — nicknamed KindaRails2Shell — breaks that boundary in Ruby on Rails applications using Active Storage with libvips.
The immediate primitive is arbitrary file read, not automatic remote code execution. The dangerous part is what application servers keep in readable files and environment variables: signing keys, database passwords, cloud credentials, and third-party tokens. Steal the right secret and a file-read bug becomes account takeover, data access, or a second-stage compromise.
TL;DR
- An application is affected when it uses a vulnerable Active Storage version, processes uploads with libvips, and accepts images from untrusted users.
- Upgrade Active Storage to 7.2.3.2, 8.0.5.1, or 8.1.3.1 as appropriate, and upgrade libvips to 8.13 or later.
- Generating variants is not a separate prerequisite; do not dismiss exposure just because thumbnails are disabled.
- If malicious uploads may have been processed, patch first, preserve evidence, and rotate every secret the application process could read.
Are You Actually Exposed?
The Rails security advisory says all three conditions must apply:
- Active Storage is older than 7.2.3.2, or is Rails 8.0 before 8.0.5.1, or Rails 8.1 before 8.1.3.1.
- Active Storage uses
:vipsas its variant processor. This has been the default for applications loading Rails 7.0 defaults. - The application accepts image uploads from users who are not trusted with server access.
Do not use the framework version in a README as your answer. Check the resolved activestorage gem in the deployed bundle, the application’s effective variant processor, and the installed libvips version. Include worker images and background-processing hosts in that inventory; they may process files separately from the web tier.
🔴 RED TEAM — Why “It Is Only an Image” Fails
Active Storage delegates image handling to libvips. The vulnerable integration failed to block unsafe libvips operations, allowing a crafted upload to make the image-processing path read local files. The attacker then receives or infers data that should never have crossed the upload boundary.
Application accepts an attacker-controlled image ↓Active Storage passes it to a vulnerable libvips processing path ↓An unsafe operation reads a file available to the application process ↓Secrets or configuration leave the server through image processing ↓Stolen credentials enable session forgery, data access, or lateral movementThe Rails team intentionally delayed full technical details until no later than August 28, 2026, to give operators time to patch. Defenders do not need a public proof of concept to act: the affected conditions and corrected versions are already specific enough to make an exposure decision.
🔵 BLUE TEAM — Fix the Whole Chain
1. Upgrade Rails and libvips
Move to the fixed Active Storage release in your maintained Rails line:
| Rails line | First fixed Active Storage version |
|---|---|
| 7.2 | 7.2.3.2 |
| 8.0 | 8.0.5.1 |
| 8.1 | 8.1.3.1 |
Also install libvips 8.13 or later. The framework fix and the image library’s untrusted-operation controls work together; treating either component as somebody else’s dependency leaves a gap.
Where an application already has libvips 8.13 or later but cannot immediately upgrade Rails, the advisory documents VIPS_BLOCK_UNTRUSTED or Vips.block_untrusted(true) with ruby-vips 2.2.1 or later as a temporary workaround. For libvips older than 8.13, Rails provides no equivalent workaround other than removing the libvips dependency. A workaround should have an owner and an expiry date.
2. Contain Untrusted Uploads by Design
Image workers should run with a minimal filesystem view, no access to deployment secrets, and narrowly scoped object-storage credentials. Keep source code, .env files, cloud credentials, and runtime sockets out of the processing container. Block unnecessary outbound traffic so a parser compromise cannot freely exfiltrate data.
Validate file size and decoded dimensions to limit resource abuse, but do not mistake extension, MIME, or magic-byte checks for a fix to a vulnerable decoder. A valid image can still exercise a dangerous processing feature.
3. Investigate and Rotate
Review uploads and image-processing failures for unusual formats, metadata, or repeated errors. Correlate them with file access telemetry, unexpected responses, outbound connections, and later authentication using application credentials. Preserve suspicious originals; reprocessing them on an unpatched workstation can reproduce the risk.
If exploitation is plausible, rotate secret_key_base, RAILS_MASTER_KEY or other credential-encryption keys where exposed, database and object-storage credentials, cloud tokens, and third-party API keys. Changing secret_key_base invalidates signed sessions and may have other application effects, so coordinate the rotation—but do not leave a known exposed key in service for convenience.
4. Make Upload Processing Disposable
Separate upload ingestion, malware scanning, and transformation from the main application. Give each stage a distinct identity and temporary storage. Delete source files according to a defined retention policy, and promote only validated outputs to the application-facing bucket.
This design does not make image libraries bug-free. It makes their inevitable bugs less capable of reading the keys to the rest of your system.
Related Posts
- Dependency Confusion: Your Internal Package Name Is a Public Attack Surface
- The Build Is the Target: CI/CD Pipeline Attacks and How to Detect Them
- Kubernetes and Container Security: Attacks, Misconfigurations, and Defenses