Skip to content

chore(deps): update dependency actionpack to v8.1.4.1 [security] - #1378

Open
renovate-bot wants to merge 1 commit into
googleapis:mainfrom
renovate-bot:renovate/rubygems-actionpack-vulnerability
Open

renovate-bot wants to merge 1 commit into
googleapis:mainfrom
renovate-bot:renovate/rubygems-actionpack-vulnerability

Conversation

@renovate-bot

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Change Age Confidence
actionpack (source, changelog) 8.1.4 → 8.1.4.1 age confidence

Action Pack: Possible restoration of destroyed sessions in Action Dispatch CacheStore

CVE-2026-126076 / GHSA-2586-8ghr-69fj

More information

Details

Impact

ActionDispatch::Session::CacheStore writes a session back to the cache at the end of each request that loaded it, without checking that the session's cache entry still exists. When a concurrent request destroys the session, through reset_session on logout or by deleting its cache entry on the server, a request that loaded the session earlier and finishes later restores it under its original session ID. Logout and server-side revocation could therefore fail to end a session, and an attacker who holds a stolen session cookie could keep that session valid across the victim's logout.

Applications that use config.session_store :cache_store are affected, with any cache backend. ActionDispatch::Session::CookieStore is not affected, nor is ActionDispatch::Session::MemCacheStore with Dalli 4.0.0 or later, whose session store does not write back a session that was deleted.

Details

The fixed releases record which session a request loaded and skip the write when that session's cache entry no longer exists. Changes that such a request makes to the destroyed session are discarded, and Rack logs a warning that the session could not be saved. Each request that writes back a session it loaded makes one additional cache read.

Releases

The fixed releases are available at the normal locations.

Patches for those who cannot upgrade at once:

Credit

Found by the team during internal code review.

Severity

  • CVSS Score: 4.2 / 10 (Medium)
  • Vector String: CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Action Pack: Possible IP spoofing in Action Dispatch RemoteIp

CVE-2026-126083 / GHSA-2gff-2mmg-m73p

More information

Details

Impact

Since Rails 8.1.0, ActionDispatch::RemoteIp derives request.remote_ip from Rack::Request#forwarded_for, which under Rack 3 reads the RFC 7239 Forwarded header in preference to X-Forwarded-For. When a reverse proxy appends the client address to X-Forwarded-For but passes a client-supplied Forwarded header through unchanged, request.remote_ip returns an address chosen by the client, and the IP spoofing check does not raise, because it compares only Client-Ip with the forwarded addresses. An unauthenticated attacker could therefore spoof request.remote_ip, possibly bypassing IP-based access controls and rate limits keyed on the client address (including the default by: of rate_limit), and falsifying the client address in logs.

Details

The 8.1.0 change (2d084af8) switched ActionDispatch::RemoteIp from reading X-Forwarded-For directly to Rack's forwarded_for, in order to reuse Rack's port handling. Rails continues to honor Forwarded, the standard header.

In the fixed releases, when config.action_dispatch.ip_spoofing_check is enabled (the default), ActionDispatch::RemoteIp also compares the first untrusted client address in Forwarded with the first untrusted client address in X-Forwarded-For, as exact strings, and raises ActionDispatch::RemoteIp::IpSpoofAttackError when both headers are present and the addresses differ. Deployments whose proxies report the client address inconsistently between the two headers will receive this error after upgrading. See the actionpack CHANGELOG.

Affected applications

An application is affected if it meets all of these requirements:

  • Runs Rails 8.1.0 through 8.1.4 with Rack 3. Under Rack 2.2, forwarded_for reads only X-Forwarded-For.
  • Is served behind a proxy that does not remove or overwrite a client-supplied Forwarded header.
  • Relies on request.remote_ip for access control, rate limiting, or auditing.

The fix detects a spoofed Forwarded header only when the proxy also sets X-Forwarded-For. An application whose proxy passes a client-supplied Forwarded header through and sets no X-Forwarded-For remains exposed after upgrading, and should configure the proxy to remove or overwrite Forwarded, or apply the workaround below.

Mitigation
  • Upgrade to a fixed version of actionpack.
  • Configure reverse proxies to remove or overwrite any client-supplied Forwarded header.
Workarounds

Applications whose proxies set X-Forwarded-For can make Rack ignore the Forwarded header, restoring the client address resolution of Rails 8.0, by setting Rack::Request.forwarded_priority = [:x_forwarded] in an initializer. This setting is available in Rack 3.0.0 and later, and it also causes Rack to ignore Forwarded when determining the request scheme, host, and port.

Releases

The fixed releases are available at the normal locations.

Patches for those who cannot upgrade at once:

Versions affected
  • actionpack >= 8.1, < 8.1.4.1
Credit

This issue was responsibly reported by HackerOne researcher luryus.

Severity

  • CVSS Score: 7.4 / 10 (High)
  • Vector String: CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Action Pack: Possible cache poisoning in Action Pack content negotiation

CVE-2026-126073 / GHSA-r9jg-fmfx-2gv6

More information

Details

Impact

Action Pack negotiates the format of a rendered response from the Accept, X-Requested-With and, for XHR requests without Accept, Content-Type request headers, but ActionController::Rendering#_set_vary_header adds Vary: Accept only when the request carries a usable Accept header and the response has no Vary header yet. A response to a request without Accept, or to an XHR request, therefore omits the headers that selected its representation, and a response whose Vary the application set before rendering (for example Vary: Accept-Language) never gains Accept. A shared cache that honours Vary could store such a response and serve it to later clients that request a different representation, possibly leading to cache poisoning in which visitors receive, until the entry expires, a page without its layout or HTML in place of JSON. The attacker cannot choose the content of the response.

Applications that render negotiated responses from actions marked public (for example with expires_in ..., public: true) behind a shared cache that honours Vary, such as Thruster or Rack::Cache, are affected.

Details

In the fixed releases, a rendered response whose format is not given by the URL lists Accept and X-Requested-With in Vary, and also Content-Type for an XHR request without Accept; when config.action_dispatch.ignore_accept_header is enabled, it lists only X-Requested-With. These fields are appended to an existing Vary value rather than skipped, and Vary: * is left unchanged. Shared caches can store more variants of such responses than before. See the Action Pack CHANGELOG for details.

Workarounds

Set Vary: Accept, X-Requested-With on negotiated responses in the application, for example in an after_action, or do not mark negotiated responses public.

Releases

The fixed releases are available at the normal locations.

Patches for those who cannot upgrade at once:

Credit

This issue was found by the Anthropic OSS Scanner (ANT-2026-7GHGLQGO, ANT-2026-5MT6C2R3).

Severity

  • CVSS Score: 4.8 / 10 (Medium)
  • Vector String: CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:L

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Action Pack: Missing SameSite attribute on session cookies from Action Pack session stores

CVE-2026-126067 / GHSA-gmj8-hvj3-49mw

More information

Details

Impact

Action Pack session stores other than ActionDispatch::Session::CookieStore (CacheStore, MemCacheStore, and third-party stores built on AbstractStore, AbstractSecureStore or the session mixins) write the session cookie without a SameSite attribute, regardless of config.action_dispatch.cookies_same_site_protection, which defaults to :lax. Only CookieStore applies the configured policy. In browsers that do not treat a cookie without the attribute as SameSite=Lax, a cross-site request could carry the session cookie, possibly leading to cross-site request forgery against actions that do not verify an authenticity token, such as those of API-only applications.

Applications are affected when they use a session store other than CookieStore and do not pass same_site: to config.session_store.

Details

In the fixed releases, every session store sets the session cookie's SameSite attribute from cookies_same_site_protection when its options have no :same_site key. An explicit same_site: option, including same_site: nil, and a :same_site value in a store's DEFAULT_OPTIONS still take precedence.

Workarounds

Pass same_site: when configuring the session store, for example config.session_store :cache_store, same_site: :lax.

Releases

The fixed releases are available at the normal locations.

Patches for those who cannot upgrade at once:

Credit

This issue was responsibly reported by HackerOne researcher tjvc.

Severity

  • CVSS Score: 3.1 / 10 (Low)
  • Vector String: CVSS:3.0/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:L/A:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Release Notes

rails/rails (actionpack)

v8.1.4.1: 8.1.4.1

Compare Source

Active Support

  • ActiveSupport::MessagePack no longer deserializes an unsafe
    ActiveSupport::SafeBuffer as html_safe.

    A SafeBuffer that was no longer html_safe?, for example after an
    in-place gsub!, was deserialized as an html_safe SafeBuffer. It is now
    serialized with an unsafe marker and deserialized as a String. Earlier
    versions of Rails cannot read an unsafe buffer serialized this way.

    [GHSA-2w9f-fxwj-w2qf]

    Jean Boussier

  • ActiveSupport::Inflector#safe_constantize matches the constant name in a
    LoadError message as a literal string instead of building a Regexp
    from it.

    The name's segments were interpolated unescaped into the pattern, so input
    that reaches safe_constantize, such as the channel identifier in an Action
    Cable subscribe command, chose the source passed to the regexp compiler.

    [GHSA-8474-xrp6-wh69]

    Jeremy Daer

Active Model

  • No changes.

Active Record

  • No changes.

Action View

  • Skip attribute names in tag helpers that are blank once converted to a
    string.

    A Symbol such as :" " is not blank, because Symbol#blank? is
    Symbol#empty?, so it reached the escaping step and produced an attribute
    with no name. The asset helpers symbolize their keys, so an ordinary String
    key reached the same place.

    [GHSA-68p9-83h6-5wpj]

    Mike Dalessio

  • Fix strip_tags to encode " and ' in its output.

    strip_tags returns an html_safe string, but was not encoding quotation
    marks. The method now encodes all five HTML-significant characters (&,
    <, >, ", '), consistent with the existing html_safe convention.

    Output used outside HTML, such as in a text template or JSON, now contains
    &quot; and &#&#8203;39; where it contained " and '. CGI.unescapeHTML
    decodes them.

    [GHSA-rq8q-p985-fjq7]

    Mike Dalessio

  • Escape the matched phrase before substituting it into highlight's
    :highlighter.

    A match was copied into each \1 of the highlighter as it appeared in
    the sanitized text, which keeps " and ' as they are, so a match
    containing a quote ended a quoted attribute value such as the
    documented '<a href="search?q=\1">\1</a>' and added attributes of
    its own. Each substituted group now goes through
    ERB::Util.html_escape_once, so quotes in a match render as &quot;
    and &#&#8203;39;. Only the numbered placeholders \0 to \9 are expanded,
    and a match never replaces the > that closes a tag.

    [GHSA-v6rj-xm57-3p59]

    Jeremy Daer

  • Require rails-html-sanitizer 1.7.2 or later.

    With the HTML5 sanitizer, Nokogiri before 1.19.5 left < and >
    unescaped in attribute values. highlight and simple_format, which
    edit the sanitized HTML as a string, could then 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.

    [GHSA-2p2f-4rq4-gjwc]

    Mike Dalessio

Action Pack

  • Apply config.action_dispatch.cookies_same_site_protection to every session
    store.

    ActionDispatch::Session::CacheStore, MemCacheStore and third-party
    stores built on AbstractStore or the session mixins sent session cookies
    with no SameSite attribute. Only CookieStore applied the configured
    default.

    [GHSA-gmj8-hvj3-49mw]

    Jean Boussier

  • Prevent ActionController::Live streams from blocking when a full buffer is
    closed or aborted.

    [GHSA-rwvh-fw6r-pwvp]

    Jeremy Daer

  • Set and extend the Vary header for rendered responses according to the
    request headers used in format negotiation.

    Vary: Accept was only added when the request carried a usable Accept
    header. A response to a request without one, negotiated to HTML or
    JavaScript, could be stored by a shared cache and served to later clients
    that requested a different representation.

    Responses now vary on Accept and X-Requested-With whenever the format is
    not given by the URL. 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.

    These fields are appended to an existing Vary value without duplicating
    fields case-insensitively. Vary: * remains unchanged.

    [GHSA-r9jg-fmfx-2gv6]

    Jeremy Daer

  • Skip writing a CacheStore session that another request deleted while this
    one ran.

    A request that loaded a session from ActionDispatch::Session::CacheStore
    wrote it back when it finished, even after a concurrent reset_session or a
    server-side delete had removed it, so the old session ID worked again.

    [GHSA-2586-8ghr-69fj]

    Mike Dalessio

  • Don't write upgraded cookies to a response that skips the session.

    Reading a signed or encrypted cookie written under a rotated secret, or in
    the format a :hybrid serializer migrates from, writes it back in the
    current format. That write ignored request.session_options[:skip], so a
    response that skips the session, such as the Active Storage proxy's
    public, cacheable response, could still carry the session cookie in
    Set-Cookie. Such a response now leaves the cookie unchanged, and a later
    request that does not skip the session upgrades it. An application that
    skips the session on every request no longer upgrades its signed or
    encrypted cookies. Cookies the application sets are still written.

    [GHSA-x6mj-8jx9-qhqv]

    Mike Dalessio

  • Detect conflicts between the Forwarded and X-Forwarded-For headers in
    ActionDispatch::RemoteIp.

    When ip_spoofing_check is enabled (the default), requests carrying both
    headers with conflicting client addresses now raise
    ActionDispatch::RemoteIp::IpSpoofAttackError.

    [GHSA-2gff-2mmg-m73p]

    Gannon McGibbon, Mike Dalessio

  • ActionController::Parameters#each_key returns self when given a block.

    It returned the internal ActiveSupport::HashWithIndifferentAccess, which
    does not respond to permitted?, so passing that return value to mass
    assignment skipped the Strong Parameters check. each, each_pair and
    each_value already return self.

    Document that ActionController::Parameters#as_json returns every
    parameter, permitted or not, in a hash that mass assignment does not check.

    [GHSA-wm3x-v3qw-4jh3]

    Mike Dalessio

Active Job

  • No changes.

Action Mailer

  • No changes.

Action Cable

  • No changes.

Active Storage

  • Preserve committed proxy responses when a storage error interrupts a
    streamed download.

    [GHSA-4v2w-w6g6-f8f8]

    Jeremy Daer

  • Derive ActiveStorage::Filename#base and #extension from the sanitized
    filename.

    This prevents null bytes and invalid byte sequences in stored filename
    metadata from raising when a blob is opened or represented. Existing blob
    records are handled without a data migration.

    [GHSA-p2pm-g2h6-7j5j]

    Jeremy Daer

  • Ship an ImageMagick security policy and apply it to every ImageMagick
    process MiniMagick spawns.

    ImageMagick chooses a coder from the content of the file it is given, and
    some coders act on files named inside the image rather than on the image
    itself. Active Storage constrained none of them, so an uploaded file could
    reach any coder the host's policy allowed, through the ImageMagick analyzer
    at attach time, with no variant or analyze call in the application.

    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 shipped policy denies the coders that script ImageMagick (MSL), read
    or delete files other than the image (TEXT, EPHEMERAL), fetch remote
    references (URL, HTTP, HTTPS, FTP), display to a screen (SHOW,
    WIN, PLT), or hand the file to Ghostscript (the PS, EPS, EPT and
    PDF coders, every alias of them, and the gs delegate), or reach a file
    directly (FILE, MPC, XPS, PCL), and it refuses @filename
    indirection. The policy applies to every ImageMagick command MiniMagick
    runs, not only Active Storage's.

    These applications must act:

    • One whose variant processor is :mini_magick has to use mini_magick 5.1
      or later, which applying the policy requires. With an older mini_magick,
      it raises at boot.
    • One that renders PostScript or PDF through ImageMagick has to re-allow
      the gs delegate and the coders it uses in the host's policy.xml. A
      host policy that allows a coder overrides the shipped deny.
    • One that replaces MiniMagick.cli_env after it boots, clears the
      environment with MiniMagick.cli_prefix, or installs its own
      MiniMagick::Shell never receives the shipped policy and has to carry
      its rules in ImageMagick's system policy. So does one that uses
      GraphicsMagick, which does not read ImageMagick policies.

    Every other application needs no change. See "ImageMagick Security Policy"
    in the Active Storage guide.

    [GHSA-f3w6-w445-fwh9]

    Mike Dalessio

  • Enforce the declared content length on Google Cloud Storage direct uploads.

    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 a bucket's CORS configuration must list
    x-goog-content-length-range in responseHeader, or direct uploads from the browser fail.

    [GHSA-hfr4-8rjc-97m2]

    Mike Dalessio

  • Sign GCS direct uploads with V2 when cache_control is set.

    V4 signatures did not bind the Content-Type or Content-MD5 headers, so the uploader could
    choose the stored Content-Type. Direct-upload URLs with cache_control are no longer limited
    to 7 days, and the client sends Cache-Control unsigned.

    [GHSA-3w93-6hmw-whh4]

    Mike Dalessio

  • Stop an uploaded filename choosing the extension of the tempfile Active
    Storage hands to an external tool.

    ActiveStorage::Blob#open named its tempfile after the uploaded filename,
    extension and all. Tools that select a decoder from the extension alone,
    such as FFmpeg's AviSynth demuxer on .avs, therefore took their
    instructions from the uploader. The extension is now kept only when it
    denotes the blob's recorded media type, and dropped otherwise.

    [GHSA-v924-7rp8-4mxh]

    Mike Dalessio

  • Restrict the formats ffmpeg and ffprobe will open when previewing and
    analyzing video and audio.

    Active Storage now passes -format_whitelist before the input at every
    ffmpeg and ffprobe call site, limiting demuxer selection to common audio and
    video container formats. Configure the list with
    config.active_storage.ffmpeg_allowed_formats, or set it to nil to let
    ffmpeg choose any demuxer it was built with.

    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. Add their demuxers to the list to keep them.

    config.active_storage.ffmpeg_allowed_formats += %w[ mxf ]

    [GHSA-3f4q-8x5m-76v8]

    Mike Dalessio

Action Mailbox

  • Reject Mailgun inbound emails whose timestamp is more than 2 minutes ahead
    of local time.

    [GHSA-5957-c7qm-m469]

    Mike Dalessio

Action Text

  • No changes.

Railties

  • No changes.

Guides

  • No changes.

Configuration

📅 Schedule: (in timezone America/Los_Angeles)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate-bot
renovate-bot requested a review from a team as a code owner November 11, 2026 20:37
@trusted-contributions-gcf trusted-contributions-gcf Bot added the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Nov 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kokoro:force-run Add this label to force Kokoro to re-run the tests.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant