A crafted photo upload can read and write files on Rails servers. Upgrade Active Storage to 8.1.4.1 or 8.0.5.2

7 min read

How to fix GHSA-f3w6-w445-fwh9: upgrade activestorage to 8.1.4.1 or 8.0.5.2 (and mini_magick to 5.1+). Rails says an unauthenticated upload processed by ImageMagick can write files on the server and read them on the Disk service, including secret_key_base. A sibling video bug, GHSA-v924-7rp8-4mxh, can disclose files through FFmpeg.

BREAKING: A crafted photo upload can read and write files on Rails servers. Upgrade Active Storage to 8.1.4.1 or 8.0.5.2
On this page

If your Rails app lets strangers upload pictures or videos, a crafted upload may be able to read files off your server or write new ones there, including the file that holds your app's master secrets. Rails shipped the fix late on Tuesday, Nov 3 (ET) as Rails 8.0.5.2 and 8.1.4.1, a security release that closes 21 issues. Two of them are the reason to upgrade tonight rather than next sprint.

GHSA-f3w6-w445-fwh9 (Critical, CVSS 9.8) says an unauthenticated attacker may be able to write arbitrary files on the server through Active Storage's ImageMagick analysis, and read arbitrary files when attachments use the Disk service. GHSA-v924-7rp8-4mxh (High, CVSS 8.8) is the video and audio side: the uploaded filename's extension picks which FFmpeg or ImageMagick decoder runs, which can mean file disclosure through a preview image or, on some FFmpeg builds, code execution. Neither has a CVE ID yet.

The part that makes these worse than a normal image-parsing bug: Active Storage analyzes a file when it is attached. The advisory is explicit that attaching the upload is enough. No thumbnail, variant or preview request is needed.

How to fix

bundle update rails
bundle exec rails runner 'puts Rails.version'

You want 8.1.4.1 or 8.0.5.2. If you pin gems individually, the package that matters for both advisories is activestorage: fixed in 8.1.4.1 and 8.0.5.2, affected in everything below 8.0.5.2 and in 8.1.0 through 8.1.4.

Two things can break or silently undo the fix, both from the critical advisory:

  • If your variant processor is :mini_magick, you need mini_magick 5.1 or newer. With an older mini_magick, the patched Rails raises an exception during boot. Check with bundle list | grep mini_magick and run bundle update mini_magick if it shows 4.x or 5.0.
  • The fix works by shipping an ImageMagick policy.xml and adding its folder to MAGICK_CONFIGURE_PATH through MiniMagick.cli_env. If your app replaces MiniMagick.cli_env after boot, clears the environment with MiniMagick.cli_prefix, or installs its own MiniMagick::Shell, that policy never loads and you still need to deny the coders in the system policy yourself (see "If you cannot upgrade today" below).

Apps that render PDFs or PostScript through ImageMagick will notice: the shipped policy denies every Ghostscript-backed coder and the gs delegate. You have to re-allow the ones you use in the host's policy.xml, on purpose.

Am I using ImageMagick or vips?

bundle exec rails runner 'p Rails.application.config.active_storage.variant_processor'
bundle exec rails runner 'p Rails.application.config.active_storage.analyzers'
bundle exec rails runner 'p Rails.application.config.active_storage.service'

The first line is the one for the critical bug. :mini_magick means you are in scope for it. Rails says that is the default for apps still on load_defaults 6.1 or earlier, which describes a lot of long-lived production apps that were upgraded gem by gem without moving their defaults. The third line tells you whether the file read half applies: :local or any service backed by ActiveStorage::Service::DiskService is the Disk service. Files on S3, GCS or Azure narrow the critical bug to file write, which is still bad.

For the video bug, look for VideoAnalyzer and AudioAnalyzer in the analyzers list. They are on by default. The AviSynth code execution path also needs an FFmpeg built with AviSynth. Check the build on each app server:

ffmpeg -hide_banner -buildconf | grep -i avisynth

No output means your FFmpeg was built without it. Rails notes that upstream FFmpeg and the common Linux distribution and Homebrew packages do not enable it, while the GPL builds downloadable from ffmpeg.org for Windows and Linux do. Hand-built Docker images that curl a static FFmpeg are the place to look.

What actually goes wrong

ImageMagick is not one parser. It is a dispatcher for hundreds of coders, and some of them act on files named inside the image instead of the image itself: the MSL scripting coder, coders that read or delete other files, the Ghostscript family, and @filename indirection. Active Storage handed every uploaded image to ImageMagick for analysis and placed no limit on which coders it could pick. ImageMagick picks from the file's content, so the uploader decides. Rails says one attack chain was reported and that it does not assume that chain is the only one.

The video bug is about the filename. ActiveStorage::Blob#open wrote the upload to a tempfile that kept the uploaded file's extension, then passed that path to ffprobe, ffmpeg and ImageMagick. When the content does not identify its own format, those tools trust the extension. Name a file .avs and an AviSynth-enabled FFmpeg runs it as a script. The fixed releases keep the extension only when Marcel, the MIME library Rails uses, maps that extension to the blob's recorded content type. Otherwise the tempfile gets no extension and the tool has to sniff the content.

Why the secrets matter more than the server

Both advisories end with the same instruction, and it is the one most teams will skip: upgrading closes the hole but does not take back anything already read. If you were in scope for the read half (ImageMagick plus Disk service for the critical bug, or an AviSynth FFmpeg for the video bug), Rails says to treat everything the app process can read as exposed and change it: secret_key_base, the master key and everything in config/credentials.yml.enc, storage credentials, database passwords and third-party tokens. Do not keep the old secret as a fallback.

Rotating secret_key_base logs everyone out and breaks existing signed and encrypted cookies, signed global IDs and Active Storage URLs. That is the point. A leaked secret_key_base lets an attacker forge those same things, which is how the advisory gets from "file read" to possible remote code execution.

Who is not in scope

  • Apps that never accept uploads from untrusted users. Both advisories require attacker-supplied files. An internal admin tool where only staff upload is a much smaller risk.
  • For the critical ImageMagick bug: apps on :vips, the default for load_defaults 7.0 and later. You still need the upgrade for the video bug if analyzers are on.
  • Hosts whose ImageMagick policy already denies MSL, the Ghostscript coders and the gs delegate. Rails points out that the policies Debian and Ubuntu ship do not.
  • GraphicsMagick. Rails says GraphicsMagick does not read ImageMagick policies, so the shipped fix does nothing there, but the advisory scopes the bug to ImageMagick.

What this is not

This is not a known exploited bug. Rails reports both issues as responsibly disclosed through HackerOne, they are not in the CISA KEV catalog, and as of publication we have seen no public exploit. It is also not "every Rails app": it needs file uploads from strangers plus either ImageMagick processing or video and audio analysis, which is common but not universal.

If you cannot upgrade today

For the critical bug, copy the rules from the policy that the fixed versions ship (activestorage/lib/active_storage/image_magick/policy.xml) into ImageMagick's system policy, for example /etc/ImageMagick-7/policy.xml. The advisory's minimum is:

<policy domain="coder" rights="none" pattern="MSL"/>
<policy domain="delegate" rights="none" pattern="gs"/>
<policy domain="coder" rights="none" pattern="{PS,PS2,PS3,EPS,EPS2,EPS3,EPI,EPSF,EPSI,EPT,EPT2,EPT3,PDF,AI,EPDF,PDFA,POCKETMOD,XPS,PCL}"/>

Confirm ImageMagick sees it with magick -list policy (or convert -list policy on ImageMagick 6).

For the video bug, remove ActiveStorage::Previewer::VideoPreviewer from config.active_storage.previewers and ActiveStorage::Analyzer::VideoAnalyzer and ActiveStorage::Analyzer::AudioAnalyzer from config.active_storage.analyzers. Swapping to an FFmpeg without AviSynth closes the script path but not the extension-selected ImageMagick decoders. Rails also published patch files for 8.0 and 8.1 on each advisory.

Apps still on Rails 7.2 or older get no fixed release. Rails says older versions are unsupported and recommends at least the 8.0 series, and security support for 8.0 ends on Nov 7, 2026. If that is you, the policy and analyzer workarounds above are your fix until you move to 8.1.

The rest of the release

The same release fixes a Strong Parameters bypass (GHSA-wm3x-v3qw-4jh3, High) where passing the return value of params.each_key { ... } to new, update or assign_attributes skips the permit check. It is an incomplete fix of CVE-2020-8164, and Rails itself makes no such call, so grep your app for each_key next to mass assignment. The other 18 issues are XSS in Action View helpers, denial of service, session handling, cache poisoning and Google Cloud Storage direct upload checks, all fixed by the same upgrade.

Evidence and sources

What do people ask about the Rails Active Storage vulnerability?

Which Rails versions fix the Active Storage file read and write bugs?

Rails 8.1.4.1 and 8.0.5.2, released Nov 3, 2026 (ET). activestorage below 8.0.5.2, and 8.1.0 through 8.1.4, are affected. Rails 7.2 and older get no fix.

Is my Rails app affected by GHSA-f3w6-w445-fwh9?

It is if it accepts uploads from untrusted users, uses ImageMagick for Active Storage (variant_processor set to mini_magick, the default on load_defaults 6.1 or earlier), and runs ImageMagick under a policy that does not deny the risky coders. Debian and Ubuntu policies do not deny them.

Do I need to rotate secret_key_base after upgrading?

Rails says yes if you stored attachments with the Disk service and used ImageMagick, or if your FFmpeg was built with AviSynth. Change secret_key_base, the master key, everything in credentials.yml.enc, storage and database credentials, and third-party tokens.

Why does my app fail to boot after upgrading Rails?

If your variant processor is mini_magick, the fixed releases require mini_magick 5.1 or newer to apply the shipped ImageMagick policy and raise an exception during boot with an older version. Update mini_magick.

Are the Rails Active Storage bugs being exploited?

Not as far as anyone has reported. They were disclosed through HackerOne, are not in the CISA KEV catalog, and had no CVE IDs or public exploits at publication.

All articles

Keep exploring

The engineering desk continues across the ecosystem: security research on shipping agents safely, and plugins that put the standards to work.