On this page · 5 sections
TL;DR
Rails 8.1.4.1 and 8.0.5.2 are security releases that address 21 issues, including a Critical Active Storage flaw for arbitrary file write and read in image analysis, according to the Rails release post. Security support for the 8.0 series ends on November 7, 2026. Teams using Active Storage with ImageMagick, video previews, Google Cloud Storage direct uploads, session stores, or Action Mailbox's Mailgun ingress should review the changes below before rolling out.
Key changes #
| Change | Who is affected | Action |
|---|---|---|
| Arbitrary file write and read in Active Storage image analysis (GHSA-f3w6-w445-fwh9) | Applications that attach images through Active Storage, especially those using the :mini_magick variant processor | Security fix (Critical): upgrade; with :mini_magick, use mini_magick 5.1 or later; re-allow the gs delegate if PostScript or PDF is rendered through ImageMagick. |
| Arbitrary file read and remote code execution in Active Storage video previews, analysis and image processing (GHSA-v924-7rp8-4mxh) | Applications that preview or analyze video and audio | Security fix (High): upgrade, then test previews for uploads whose filename extension does not match the media type. |
| Strong Parameters bypass in Parameters#each_key (GHSA-wm3x-v3qw-4jh3) | Applications that pass the result of each_key on ActionController::Parameters to mass assignment | Security fix (High): upgrade and search the codebase for each_key calls on params. |
| IP spoofing in RemoteIp through the Forwarded header (GHSA-2gff-2mmg-m73p) | Rails 8.1 applications with ip_spoofing_check enabled (the default) | Security fix (High, 8.1 only): identify proxies that send both Forwarded and X-Forwarded-For headers. |
| DoS vulnerability in Active Support safe_constantize (GHSA-8474-xrp6-wh69) | Applications that pass user input, such as Action Cable channel identifiers, to safe_constantize | Security fix (High): upgrade. |
| Missing SameSite attribute on session cookies (GHSA-gmj8-hvj3-49mw) | Applications using session stores other than CookieStore, such as CacheStore or MemCacheStore | Security fix (Low): check config.action_dispatch.cookies_same_site_protection. |
| Restoration of destroyed sessions in CacheStore (GHSA-2586-8ghr-69fj) | Applications using CacheStore sessions with reset_session or server-side session deletes | Security fix (Medium): test session reset and deletion flows. |
| Sensitive session information leak in Active Storage proxy mode (GHSA-x6mj-8jx9-qhqv) | Applications using Active Storage proxy mode or skipping the session on some requests | Security fix (Medium): inspect Set-Cookie on proxy and cached responses after upgrading. |
| Possible cache poisoning in content negotiation (GHSA-r9jg-fmfx-2gv6) | Applications whose responses pass through shared caches | Security fix (Medium): check Vary on responses and the value of config.action_dispatch.ignore_accept_header. |
| XSS in Action View helpers and in the Active Support MessagePack serializer (GHSA-rq8q-p985-fjq7, GHSA-v6rj-xm57-3p59, GHSA-68p9-83h6-5wpj, GHSA-2p2f-4rq4-gjwc) | Applications using strip_tags, highlight, tag or text helpers, or sending their output outside HTML | Security fix (Medium): review strip_tags output used in text templates or JSON; require rails-html-sanitizer 1.7.2 or later. |
| Circumvention of file size limits and unsigned Content-Type in GCS direct uploads (GHSA-hfr4-8rjc-97m2, GHSA-3w93-6hmw-whh4) | Applications using Active Storage direct uploads to Google Cloud Storage | Security fix (Medium): add x-goog-content-length-range to the bucket's CORS responseHeader. |
| Unsafe SafeBuffer deserialized as html_safe in ActiveSupport::MessagePack (GHSA-2w9f-fxwj-w2qf) | Rails 8.1 applications using the MessagePack serializer | Security fix (Medium, 8.1 only): roll out in stages, because earlier versions of Rails cannot read an unsafe buffer serialized this way. |
| Demuxer selection in ffmpeg and ffprobe (GHSA-3f4q-8x5m-76v8) | Applications previewing or analyzing MXF, DV, AC3, WavPack, AU, W64 or raw H.264 and MPEG-1/2 files | Security fix (Low): add needed formats to config.active_storage.ffmpeg_allowed_formats. |
| Signature replay in Action Mailbox Mailgun ingress (GHSA-5957-c7qm-m469) | Applications receiving inbound email through Mailgun | Security fix (Low): test that legitimate Mailgun messages are still accepted. |
Rails 8.1.4.1: An ImageMagick Security Policy for Active Storage #
The 8.1.4.1 release notes describe the Critical change: Active Storage now ships an ImageMagick security policy. ImageMagick chooses a coder from the content of the file it receives, and some coders act on files named inside the image. Active Storage constrained none of them, so an upload could reach any coder the host's policy allowed through the analyzer at attach time, with no variant or analyze call in the application.
Image analysis and the shipped ImageMagick policy #
Active Storage now ships a policy.xml in ActiveStorage::ImageMagick::POLICY_DIRECTORY and prepends that directory to MAGICK_CONFIGURE_PATH through MiniMagick.cli_env. ImageMagick applies every policy file on its search path, so the shipped policy adds to the host's policy rather than replacing it. A MAGICK_CONFIGURE_PATH set in the environment or in MiniMagick.cli_env, including by an initializer or dotenv, is kept after the shipped directory. The policy applies to every ImageMagick command MiniMagick runs, not only Active Storage's.
The shipped policy denies the following:
- the coders that script ImageMagick (MSL);
- the coders that read or delete files other than the image (TEXT, EPHEMERAL);
- the coders that fetch remote references (URL, HTTP, HTTPS, FTP);
- the coders that display to a screen (SHOW, WIN, PLT);
- the coders that hand the file to Ghostscript (PS, EPS, EPT and PDF, every alias of them, and the gs delegate);
- the coders that reach a file directly (FILE, MPC, XPS, PCL), and @filename indirection.
Applications whose variant processor is :mini_magick must use mini_magick 5.1 or later, because applying the policy requires it; with an older mini_magick, the application raises at boot. The constraint belongs in the Gemfile:
gem "mini_magick", ">= 5.1"Applications that render PostScript or PDF through ImageMagick must re-allow the gs delegate and the coders they use in the host's policy.xml, since a host policy that allows a coder overrides the shipped deny. Applications that replace MiniMagick.cli_env after boot, clear the environment with MiniMagick.cli_prefix, install their own MiniMagick::Shell, or use GraphicsMagick never receive the shipped policy, so their rules must live in ImageMagick's system policy. Every other application needs no change.
Video and audio previews: tempfile extensions and ffmpeg formats #
GHSA-v924-7rp8-4mxh is rated High. ActiveStorage::Blob#open named its tempfile after the uploaded filename, extension included, and tools that select a decoder from the extension alone took their instructions from the uploader. The extension is now kept only when it denotes the blob's recorded media type, and dropped otherwise. Previews that depended on a mismatched extension need testing after the upgrade.
GHSA-3f4q-8x5m-76v8 is rated Low. Active Storage now passes -format_whitelist before the input at every ffmpeg and ffprobe call, which limits demuxer selection to common audio and video container formats. Files in other formats, such as MXF, DV, AC3, WavPack, AU, W64, and raw H.264 or MPEG-1/2 video streams, now fail to preview with ActiveStorage::PreviewError, and their analysis stores no media metadata and logs a warning. To keep one of these formats, add its demuxer to the list:
config.active_storage.ffmpeg_allowed_formats += %w[ mxf ]Setting config.active_storage.ffmpeg_allowed_formats to nil lets ffmpeg choose any demuxer it was built with, which is the option to use only when the uploaded formats are trusted.
Google Cloud Storage direct uploads #
GHSA-hfr4-8rjc-97m2 is rated Medium. The signed URL now requires an x-goog-content-length-range header matching the blob's byte_size, so Cloud Storage rejects a body of any other size. Browsers send the new header, so the bucket's CORS configuration must list x-goog-content-length-range in responseHeader, or direct uploads from the browser fail.
GHSA-3w93-6hmw-whh4 is rated Medium. V4 signatures did not bind the Content-Type or Content-MD5 headers, so the uploader could choose the stored Content-Type. With cache_control set, direct uploads are now signed with V2, direct-upload URLs with cache_control are no longer limited to 7 days, and the client sends Cache-Control unsigned. Applications that set cache_control on direct uploads should check their signed URL behaviour after the update.
Proxy mode, filenames and streaming #
GHSA-4v2w-w6g6-f8f8 (Medium) preserves committed proxy responses when a storage error interrupts a streamed download. GHSA-p2pm-g2h6-7j5j (Medium) derives ActiveStorage::Filename#base and #extension from the sanitized filename, so null bytes and invalid byte sequences in stored filename metadata no longer raise when a blob is opened or represented. Existing blob records are handled without a data migration, so no migration step is needed for this fix.
Strong Parameters and Parameters#each_key #
GHSA-wm3x-v3qw-4jh3 is rated High. ActionController::Parameters#each_key returned the internal ActiveSupport::HashWithIndifferentAccess when given a block. That object does not respond to permitted?, so passing the return value to mass assignment skipped the Strong Parameters check. each_key now returns self, as each, each_pair and each_value already did. Code that chains each_key into mass assignment should be found and its filtered output confirmed.
Sessions: SameSite, CacheStore restores and cookie upgrades #
GHSA-gmj8-hvj3-49mw is rated Low. config.action_dispatch.cookies_same_site_protection now applies to every session store. The notes say that ActionDispatch::Session::CacheStore, MemCacheStore and third-party stores built on AbstractStore sent session cookies with no SameSite attribute, and that only CookieStore applied the configured default. Check the configured value in the environment files that apply to your deployment.
GHSA-2586-8ghr-69fj is rated Medium. A request that loaded a session from ActionDispatch::Session::CacheStore wrote it back when it finished, even after a concurrent reset_session or server-side delete had removed it, so the old session ID worked again. Rails now skips that write. GHSA-x6mj-8jx9-qhqv (Medium) covers cookie upgrades: a response that skips the session, such as the Active Storage proxy's public, cacheable response, no longer carries an upgraded session cookie in Set-Cookie. A later request that does not skip the session performs the upgrade, and cookies the application sets are still written.
Vary headers and content negotiation #
GHSA-r9jg-fmfx-2gv6 is rated Medium. Vary: Accept was only added when the request carried a usable Accept header, so a response to a request without one, negotiated to HTML or JavaScript, could be stored by a shared cache and served to clients asking for a different representation. Responses now vary on Accept and X-Requested-With whenever the URL does not give the format. XHR requests without Accept also vary on Content-Type, which Rails uses as a legacy format fallback.
When config.action_dispatch.ignore_accept_header is enabled, responses vary only on X-Requested-With. Vary: * remains unchanged. If a shared cache sits in front of Rails, check the Vary value on responses to requests without an Accept header after the update.
HTML helpers and the sanitizer dependency #
GHSA-rq8q-p985-fjq7 is rated Medium. strip_tags returns an html_safe string but did not encode quotation marks. It now encodes all five HTML-significant characters, so output used outside HTML, such as in a text template or JSON, contains " and ' where it contained the raw characters. CGI.unescapeHTML decodes them. Search templates and JSON builders for strip_tags output that is not rendered as HTML.
GHSA-v6rj-xm57-3p59 is rated Medium. highlight copied each match into the :highlighter template as it appeared in the sanitized text, so a quote in a match could end a quoted attribute value and add attributes. Each substituted group is now escaped with ERB::Util.html_escape_once, and only the placeholders \0 to \9 are expanded. GHSA-68p9-83h6-5wpj is rated Medium: tag helpers skip attribute names that are blank once converted to a string, so a Symbol such as :" " no longer produces an attribute with no name.
GHSA-2p2f-4rq4-gjwc is rated Medium. With the HTML5 sanitizer, Nokogiri before 1.19.5 left < and > unescaped in attribute values, so highlight and simple_format could turn markup inside an attribute value into live elements. rails-html-sanitizer 1.7.2 requires Loofah 2.25.3, which requires Nokogiri 1.19.5. Require the sanitizer version in the Gemfile:
gem "rails-html-sanitizer", ">= 1.7.2"Forwarded and X-Forwarded-For conflicts in RemoteIp #
GHSA-2gff-2mmg-m73p is rated High and applies to 8.1 only. When ip_spoofing_check is enabled, which is the default, a request carrying both the Forwarded and X-Forwarded-For headers with conflicting client addresses now raises ActionDispatch::RemoteIp::IpSpoofAttackError. Check which proxies in front of the application send both headers, because those requests now raise instead of passing through.
MessagePack, safe_constantize and Action Controller Live #
GHSA-2w9f-fxwj-w2qf is rated Medium and applies to 8.1 only. ActiveSupport::MessagePack no longer deserializes an unsafe SafeBuffer as html_safe. An unsafe buffer is now serialized with an unsafe marker and deserialized as a String, and earlier versions of Rails cannot read an unsafe buffer serialized this way. Services that share MessagePack data across Rails versions therefore need a staged rollout, and this suggests that the two sides of such a channel must be upgraded in an order that keeps them compatible.
GHSA-8474-xrp6-wh69 is rated High. safe_constantize built a Regexp from the constant name in a LoadError message without escaping its segments, so input reaching it, such as the channel identifier in an Action Cable subscribe command, could choose the regexp source. The name is now matched as a literal string. GHSA-rwvh-fw6r-pwvp is rated Medium: ActionController::Live streams no longer block when a full buffer is closed or aborted.
Action Mailbox Mailgun timestamps #
GHSA-5957-c7qm-m469 is rated Low. Action Mailbox now rejects Mailgun inbound emails whose timestamp is more than 2 minutes ahead of local time. Inbound mail from a sender whose clock runs ahead of the application's will be rejected, so test that legitimate Mailgun messages are still accepted after the upgrade.
Also in this release #
- Action Pack: documents that ActionController::Parameters#as_json returns every parameter, permitted or not, in a hash that mass assignment does not check (alongside GHSA-wm3x-v3qw-4jh3).
Rails 8.0.5.2: Security Support Ends on November 7, 2026 #
Security support for the 8.0 series ends on November 7, 2026, and the release post states that older versions of Rails are unsupported. It recommends upgrading to at least the 8.0 series, so applications on 8.0 have a dated decision to make about the line they move to. The post recommends the upgrade as follows:
"We strongly recommend upgrading as soon as possible." (Rails release post)
Advisories the 8.0 series receives #
The release post lists the 21 issues for both releases and marks only two as 8.1 only: GHSA-2gff-2mmg-m73p (RemoteIp) and GHSA-2w9f-fxwj-w2qf (MessagePack). The remaining entries carry no such marker, including the Critical GHSA-f3w6-w445-fwh9 for Active Storage image analysis, so the list presents them as addressed by 8.0.5.2 as well.
Confirming how each 8.0 fix works #
The per-change descriptions in the 8.1.4.1 release notes cover 8.1.4.1 only, and the cited sources do not describe how 8.0.5.2 implements each fix. 8.0 readers should follow the GHSA links in the release post to confirm the detail of each change before relying on it.
Upgrade checklist #
- Before upgrading, check whether the variant processor is :mini_magick, and note the mini_magick version in Gemfile.lock.
- Before upgrading, search for PostScript or PDF rendering through ImageMagick, and read the host policy.xml for the gs delegate and the coders it uses.
- Before upgrading, check the Google Cloud Storage bucket's CORS configuration for responseHeader and add x-goog-content-length-range.
- Before upgrading, list the video and audio formats your application previews, such as MXF or DV, and prepare config.active_storage.ffmpeg_allowed_formats.
- Before upgrading, find code that calls each_key on params and passes the result to mass assignment, and identify proxies that send both Forwarded and X-Forwarded-For headers to Rails 8.1 applications.
- Upgrade to 8.1.4.1 or 8.0.5.2, and verify each gem against the SHA-256 hashes in the release post, for example pkg/activestorage-8.1.4.1.gem: 0f4e2f114f3584723a80a2c089aacc6170e765a0b2c385c9782e26ed78f05c66.
- Upgrade mini_magick to 5.1 or later in the Gemfile if the variant processor is :mini_magick.
- After upgrading, confirm previews and analysis results for each uploaded video, audio and image format, and check the logs for files analysed without media metadata.
- After upgrading, inspect Set-Cookie and Vary headers on session, Active Storage proxy and cached responses, and confirm config.action_dispatch.cookies_same_site_protection is set.
- After upgrading, verify that Mailgun inbound messages are accepted and that direct uploads from the browser still succeed.
Sources
- Rails Versions 8.0.5.2 and 8.1.4.1 have been released! rubyonrails.org · Nov 4, 2026
- Release 8.1.4.1 · rails/rails · GitHub github.com · Nov 4, 2026
Edited and approved by Jarosław Krzemiński. Spotted a mistake? Report a correction or read the corrections policy.




Comments