Creuto is now an OpenAI Select Partner Read More
VIPS_BLOCK_UNTRUSTED closes CVE-2026-66066 without touching your Rails version, if libvips is 8.13+. It also stops BMP, ICO and PSD transforms working.

VIPS_BLOCK_UNTRUSTED is an environment variable libvips reads while initializing, and setting it closes CVE-2026-66066 without changing a line of Rails. The Rails advisory offers it as a genuine mitigation, with one hard prerequisite — libvips 8.13 or newer — and one consequence nobody advertises: the official patch does the same thing internally, and it stops BMP, ICO and PSD transformations working.
That side effect is why teams stall halfway through this fix. Better to know which formats break before you deploy than to find out from a support ticket.
From the Rails security advisory, in its own order of preference:
| Option | Requires | How |
|---|---|---|
| Upgrade Active Storage | libvips >= 8.13 | 7.2.3.2, 8.0.5.1 or 8.1.3.1 |
| Block untrusted loaders | libvips >= 8.13 | VIPS_BLOCK_UNTRUSTED in the environment |
| Block from Ruby | ruby-vips >= 2.2.1 | Vips.block_untrusted(true) in an initializer |
| Remove the dependency | — | Drop ruby-vips from the Gemfile |
Note what the first row means: upgrading Rails is not sufficient on its own. The advisory states that "The minimum version of libvips must be upgraded to >= 8.13" — so if your base image carries an older libvips, bumping the gem leaves you exposed. Check the library, not just the gem.
Below libvips 8.13 the advisory is blunt that "there are no workarounds available other than removing the dependency on libvips from the application". It adds a useful observation for a subset of teams: some applications declare ruby-vips only for image analysis, and those "may be able to simply remove ruby-vips from the Gemfile". If you never generate variants and only read dimensions, that is the cheapest exit available.
The mitigation and the official patch both work by telling libvips to refuse loaders it classifies as untrusted. Ethiack's analysis of the patch commit names them: matload, svgload, fitsload, niiload, radload and openslideload.
matload is the one carrying the vulnerability — the MATLAB loader that routes a crafted file into libmatio. The other five are swept up because libvips flags them as unfuzzed, which is the right call for a general mitigation and the reason it has collateral effects.
This is the part worth reading before you deploy, because it is a functional regression rather than a security trade-off. Per Ethiack's analysis of the patch, there are two distinct categories.
Transformations that now raise an error. BMP, ICO and PSD transformation "now raises Vips::Error". If a user uploads a BMP and your code calls variant on it, you get an exception where you previously got an image. On an upload path without careful error handling, that is a 500.
Analysis that silently stops recording. Analysis of SVG, JPEG XL, JPEG 2000 and Netpbm stops recording width and height. This one is worse, because nothing raises. You get a blob with nil dimensions, and anything downstream that reasoned about aspect ratio or built a responsive srcset quietly produces wrong output.
SVG is the one to check first. It is common as a logo or avatar upload, it is in the blocked set, and the failure is silent.
If you can upgrade Rails and libvips together, do that and read the format list as a release note — you are getting the same restrictions either way, so the question is only whether you also get the Rails-side fix.
The environment variable earns its place in two situations. First, when an Active Storage upgrade is blocked on something else — a framework version, a stuck dependency, a change freeze — and you need the loader closed today. Second, as a belt-and-braces setting you leave in place permanently after upgrading, because it closes the loaders at the libvips level regardless of what a future Active Storage default does. Given that the advisory's own CWE for this is CWE-1188, "Initialization of a Resource with an Insecure Default", not relying on a default is a reasonable conclusion to draw.
Prefer VIPS_BLOCK_UNTRUSTED over the Ruby call where you can set environment variables, because libvips reads it during initialization — earlier than an initializer runs. Use Vips.block_untrusted(true) when you control the application but not the environment, such as a platform that will not let you set arbitrary variables.
Do not assume the variable reached the process. Deployment systems drop environment variables in more ways than anyone expects, and a mitigation you believe is active is worse than one you know is not.
The check that actually proves something is a negative one: attempt to load a format you know is in the blocked set and confirm you get Vips::Error rather than an image. A small BMP is the easiest probe, because it is in the "raises" category rather than the silent one. Run it in the same process context as your workers — the web process and the background worker often have different environments, and the upload path runs in both.
Then upgrade anyway. The mitigation closes this vector; it does not fix the signed-variation-key weakness underneath it, and the advisory's ordering puts the upgrade first for a reason. The same "a patch does not reach backwards" problem showed up in the eMudhra CA block, where sessions begun before the upgrade kept being trusted until they timed out. The full chain, and the researchers' disagreement with the advisory over Rails 6.x, is its own subject, and worth reading before you decide this mitigation is sufficient.
One last thing the advisory is clear about and most coverage omits: closing the loader does not undo a read that already happened. If the vulnerable configuration was exposed to untrusted uploads, rotating secret_key_base and anything else reachable in the environment is part of the work, not an optional extra. We do not work in Rails, so everything here is read off the advisory and the researchers' write-ups rather than our own testing — which is also why the verification step above matters more than our recommendation does. If image handling is a load-bearing part of a product we are building, that audit sits inside how we scope the build rather than after it — the same reasoning we applied to a decoder bug in Node's bundled Brotli, where the vulnerable code was also three dependencies deep.
It is an environment variable libvips reads during initialization that makes it refuse loaders classified as untrusted, including matload, svgload, fitsload, niiload, radload and openslideload. Setting it closes CVE-2026-66066 without changing your Rails version, provided libvips is 8.13 or newer.
Yes, if libvips is 8.13 or newer. Set the VIPS_BLOCK_UNTRUSTED environment variable, or on ruby-vips 2.2.1 or later call Vips.block_untrusted(true) from an initializer. Below libvips 8.13 the advisory says the only option is removing the libvips dependency entirely.
Transformation of BMP, ICO and PSD raises Vips::Error, and analysis of SVG, JPEG XL, JPEG 2000 and Netpbm stops recording width and height. The analysis failures are silent, so check SVG handling first since it is common as a logo or avatar upload.
No. The Rails advisory states that the minimum version of libvips must also be upgraded to 8.13 or newer. If your base image carries an older libvips, bumping the gem leaves you exposed, so verify the system library version and not just the gem version.
Attempt to load a format in the blocked set and confirm you get a Vips::Error rather than an image. A small BMP works well because it raises rather than failing silently. Test in both the web process and the background worker, since their environments often differ.
Ready to take the first step towards unlocking opportunities, realizing goals, and embracing innovation? We're here and eager to connect.