Rails 8.0.5.2 and 8.1.4.1 came out today with fixes for 21 security issues: 1 critical, 4 high, 13 medium, and 3 low. If your app accepts file uploads and uses ImageMagick, start with the critical one, because attaching a crafted file is enough to trigger it.
If you're on 8.0, there's also a deadline. Security support for the 8.0 series ends on November 7, and the maintenance policy lists 8.1 as supported until October 10, 2027. This batch has no 7.2 release, and the announcement recommends moving to at least 8.0. Take the patch now and plan the move to 8.1.
The issues are identified by GHSA IDs (GitHub Security Advisory numbers). None of the 21 had a CVE ID (the usual public vulnerability number) when I wrote this.
The Five That Need a Closer Look
Critical: File Write and Read in Active Storage Image Analysis
GHSA-f3w6-w445-fwh9 (CVSS severity score: 9.8 out of 10). An unauthenticated attacker may be able to write arbitrary files on the server. When attachments use the Disk service (Active Storage saving files to local disk), they may also be able to read any file the app process can read, including secret_key_base and other credentials.
ImageMagick picks a coder (its handler for a file format) based on the file's content, and some coders act on other files named inside the image. Active Storage didn't restrict them. The ImageMagick analyzer runs at attach time, so no variant (a resized copy of an image), preview, or analyze call is needed.
You're affected if all three are true:
- Your app sets
config.active_storage.variant_processor = :mini_magick, which is the default onload_defaults 6.1or earlier. - Your ImageMagick security policy doesn't already deny these coders. The policies packaged by Debian and Ubuntu don't.
- Untrusted users can upload files.
To check the first two:
grep -rnE 'variant_processor|load_defaults' config
identify -list policy
Run the second command somewhere that matches production, like inside your production image. Look for rules denying MSL (ImageMagick's scripting format) and Ghostscript coders like PDF.
In July's CVE-2026-66066, the exposed apps were the ones using libvips, the other image library Active Storage supports. This one affects apps using ImageMagick.
High: File Read and Possible RCE in Video Previews and Analysis
GHSA-v924-7rp8-4mxh (CVSS 8.8). Active Storage kept the uploaded file's extension on the tempfile it handed to ffprobe, ffmpeg, and ImageMagick, and those tools can choose a decoder from the extension. So whoever uploads the file can influence which decoder runs. On an FFmpeg built with support for AviSynth (a video scripting tool), a .avs file gets evaluated as a script, which could disclose files or lead to remote code execution (RCE, running the attacker's code on your server).
You're affected if you accept untrusted uploads and either analyze video or audio, generate video previews, or process images with ImageMagick. Active Storage analyzes video and audio on attach by default, so moving to libvips doesn't rule you out here.
The AviSynth attack also needs FFmpeg built with --enable-avisynth plus the AviSynthPlus runtime. The advisory says upstream FFmpeg and the common Linux distribution and Homebrew packages don't enable it, while the GPL builds from ffmpeg.org do. It also warns that other decoders may be reachable without AviSynth. To see how yours was built:
ffmpeg -version | grep -o enable-avisynth
No output means it isn't enabled.
High: Strong Parameters Bypass in each_key
GHSA-wm3x-v3qw-4jh3 (CVSS 7.5). ActionController::Parameters#each_key with a block returned the raw internal hash, which mass assignment (setting many attributes at once from a hash) accepts without a permit check. This only matters if your code passes that return value to new, update, or assign_attributes, and Rails itself never does. It's a quick search:
grep -rn 'each_key' app lib
Most hits will have nothing to do with params. You're looking for a call on params whose result gets used.
High: Crash via safe_constantize and Action Cable
GHSA-8474-xrp6-wh69 (CVSS 7.5). This one reminded me of the Ruby regexp bugs from last month. When a constant lookup raised LoadError, safe_constantize built a regular expression from the constant name without escaping it. A crafted pattern can trigger defects in Ruby's regexp compiler and possibly crash the server process. The advisory doesn't name those bugs or say whether a patched Ruby prevents this crash, so I'd upgrade Rails either way.
Action Cable passes the channel value from each subscribe command to safe_constantize, and new Rails apps mount Action Cable at /cable by default. If Action Cable is mounted and you haven't added a check to ApplicationCable::Connection#connect, an unauthenticated client can reach this code, even if you never built a channel.
High: IP Spoofing in remote_ip (8.1 Only)
GHSA-2gff-2mmg-m73p (CVSS 7.4). Since 8.1.0 under Rack 3, request.remote_ip prefers the Forwarded header over X-Forwarded-For. If your proxy passes a client-supplied Forwarded header through unchanged, the client chooses its own IP. That can get around IP-based access rules, falsify logs, and bypass rate_limit, whose default by: uses the client address.
Upgrading doesn't fully close this. The fix only detects spoofing when the proxy also sets X-Forwarded-For, so it's worth configuring your proxy to remove or overwrite Forwarded either way.
The Other 16
Each row is what your app has to be doing to be exposed. XSS is cross-site scripting (an attacker's script running in another user's browser), DoS is denial of service (making the app unavailable), and proxy mode is when Active Storage streams files through your app instead of redirecting to the storage service.
| Severity | Advisory | You're exposed if |
|---|---|---|
| Medium | XSS in text helpers | You use the HTML5 sanitizer and pass untrusted text to highlight, or to simple_format with html_options
|
| Medium | XSS in highlight |
A custom :highlighter puts a placeholder inside an attribute value, and users control the text or phrases |
| Medium | XSS in strip_tags |
You render strip_tags output from untrusted input inside an HTML attribute |
| Medium | XSS in tag helpers | Users can specify custom HTML attribute names |
| Medium | XSS in MessagePack serializer (8.1 only) | You use a MessagePack serializer and store a SafeBuffer (Rails' HTML-safe string type) mutated in place with untrusted input |
| Medium | DoS in Action Controller Live | You stream with ActionController::Live or send_stream, or serve large files through Active Storage proxy mode |
| Medium | DoS in proxy streaming | You store files on S3, an S3-compatible service, or Google Cloud Storage and use Active Storage's default routes, which are on unless you've turned them off |
| Medium | DoS in filename handling | Users can upload attachments and you're on a database that accepts NUL bytes, like SQLite or MySQL/MariaDB. PostgreSQL isn't affected |
| Medium | Unsigned Content-Type on GCS | You use Google Cloud Storage with cache_control configured and accept direct uploads |
| Medium | File size bypass on GCS | You use Google Cloud Storage and accept direct uploads |
| Medium | Destroyed sessions restored | You use config.session_store :cache_store
|
| Medium | Session leak in proxy mode | You serve files through the proxy controllers, have a cookie rotation or :hybrid serializer migration configured, and run behind a cache that stores Set-Cookie on public responses |
| Medium | Cache poisoning | You render responses whose format depends on request headers from public actions behind a shared cache that honors Vary, such as Thruster or Rack::Cache
|
| Low | Local file disclosure via FFmpeg | You accept untrusted uploads and preview or analyze video or audio with FFmpeg |
| Low | Mailgun signature replay | You receive inbound email through the Action Mailbox Mailgun ingress |
| Low | Missing SameSite | You use a session store other than CookieStore and don't pass same_site:
|
What Might Break When You Upgrade
These are the behavior changes I found in the advisories that may need action from you:
| If your app… | Then… |
|---|---|
Uses :mini_magick as the variant processor |
You need mini_magick 5.1 or later, or the app raises at boot |
| Renders PDF or PostScript through ImageMagick | Those are now denied. Re-allow the gs delegate (how ImageMagick calls Ghostscript, its PDF and PostScript tool) and the coders you use in the host's policy.xml
|
Replaces MiniMagick.cli_env after boot, clears the environment with MiniMagick.cli_prefix, installs its own MiniMagick::Shell, or uses GraphicsMagick |
The shipped policy doesn't reach you, so the rules need to go in ImageMagick's system policy |
| Uses browser direct uploads to Google Cloud Storage | Add x-goog-content-length-range to responseHeader in the bucket's CORS config (its rules for browser requests from other sites), or uploads fail |
| Previews or analyzes formats like MXF, DV, or AC3 | FFmpeg can now only open formats in config.active_storage.ffmpeg_allowed_formats, and other files lose previews and metadata. Add them with config.active_storage.ffmpeg_allowed_formats += %w[ mxf ]
|
Uses strip_tags output outside HTML, like JSON or text templates |
Quotes now appear as " and '. CGI.unescapeHTML decodes them |
| Compares sanitized HTML as strings, including in tests |
< and > in attribute values are now escaped, because the release requires rails-html-sanitizer 1.7.2 and Nokogiri 1.19.5 |
Is on 8.1 behind proxies that report the client differently in Forwarded and X-Forwarded-For
|
Requests now raise IpSpoofAttackError
|
Is on 8.1 and stores unsafe SafeBuffers with MessagePack |
During a rolling deploy, processes not yet upgraded may fail to load those cookies or cache entries |
| Uses the Mailgun ingress with a clock over 2 minutes behind Mailgun's | Genuine webhooks get rejected, so sync the clock |
Shared caches can also store more variants than before of responses whose format depends on request headers, because Vary now lists more headers.
Aside: The One Thing CI Caught
CI went fine for one app's upgrade to these releases, with one exception. Reek, a tool that flags code smells, reported six warnings on a class that had no entry in the project's baseline of known warnings. Most of them shared one cause: the class was handling a job that belonged elsewhere. A small refactor cleared them. It was weird that this came up during the Rails upgrade and not earlier.
What to Do
Upgrade to 8.0.5.2 or 8.1.4.1. Run
bundle update rails --conservative, which limits what else changes inGemfile.lock. Then confirm the lockfile shows the new Rails version and Nokogiri 1.19.5 or later.If you use
:mini_magickandbundle info mini_magickshows a version below 5.1, runbundle update mini_magick.Rotate secrets if you were exposed. The critical advisory says to do this if you met its conditions and store attachments with the Disk service. The video advisory says to do it if you meet its AviSynth requirements. That covers
secret_key_base, the master key, everything inconfig/credentials.yml.enc, and storage, database, and third-party credentials, and the advisories say not to keep an exposed secret as a fallback. Changingsecret_key_baseexpires active sessions and invalidates signed and encrypted cookies, signed global IDs, and Active Storage URLs, so users will need to log in again.If you're on 8.1 behind a proxy, set it to remove or overwrite
Forwarded.If you're on 8.0, put the move to 8.1 on the calendar.
If You Can't Upgrade Yet
Each advisory links to patches for 8.0 and 8.1 where they apply, and many list workarounds. For the top five:
-
ImageMagick (critical): copy the rules from the policy Rails now ships,
activestorage/lib/active_storage/image_magick/policy.xml, into your system policy, such as/etc/ImageMagick-7/policy.xml. The advisory's minimum is below, and it blocks Ghostscript, so it also affects PDF and PostScript rendering.
<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}"/>
-
Video previews and analysis: remove
ActiveStorage::Previewer::VideoPreviewerfromconfig.active_storage.previewers, andActiveStorage::Analyzer::VideoAnalyzerandActiveStorage::Analyzer::AudioAnalyzerfromconfig.active_storage.analyzers. Switching to an FFmpeg without AviSynth closes that attack but not the decoders ImageMagick picks from the extension. -
each_key: don't use its return value. Pass the permittedParametersinstance to mass assignment. -
safe_constantize: if you don't use Action Cable, setconfig.action_cable.mount_path = nil. If you do, callreject_unauthorized_connectioninconnectfor unauthenticated clients, which limits exposure to logged-in users but doesn't remove it. -
remote_ip: if your proxy setsX-Forwarded-For, addRack::Request.forwarded_priority = [:x_forwarded]to an initializer. Rack will then also ignoreForwardedfor the request's scheme, host, and port.
If you're on 7.2 or older, there's no release for you in this batch. Most of the advisories list every version below 8.0.5.2 as affected, so moving to a supported series is the fix. The advisory patches may help in the meantime, though they target 8.0 and 8.1.
More Information
- Rails release announcement, with all 21 advisories and gem checksums
- Rails maintenance policy
- Active Storage changelog for 8.1.4.1
Top comments (1)
Really useful triage, especially the "affected if all three are true" lists. The point that the analyzer runs at attach time is the one people will miss, since many assume no variant means no ImageMagick. Flagging the 8.0 support end on November 7 alongside the patch is a kind touch for teams planning this week.