IT SBIT Services
Schneeberger
DEEN
CVE tracker

Rails Action Pack: Cache poisoning via missing Vary header in content negotiation

CVE-2026-126073Medium 4.8

← All vulnerabilities

Summary

Action Pack does not always add the Vary header for negotiated responses, for example when a request has no Accept header or is an XHR request. A shared cache that honours Vary may store such a response and serve it to other clients who request a different format, such as HTML instead of JSON, until the cache entry expires. The attacker cannot choose the content of the response, and the issue only applies to applications that render negotiated responses from actions marked public behind such a cache.

Affected

  • Rails Action Pack 8.1.0 up to 8.1.4.0
  • Rails Action Pack before 8.0.5.2

Fixed in

  • Rails 8.1.4.1
  • Rails 8.0.5.2

Workaround

  • If patching is not possible, set Vary: Accept, X-Requested-With on negotiated responses in the application (for example in an after_action callback), or do not mark negotiated responses as public.
  • The workaround does not replace the upgrade.

Exploitation

  • Not known to be exploited in the wild.
  • Not listed in the CISA KEV catalogue.
  • No public proof-of-concept found in our research; this is not a complete check.

Our recommendation

  • Upgrade to Rails 8.1.4.1 or 8.0.5.2. Rails 8.0 is out of security support after 7 November 2026, so plan a move to 8.1.4.1.
  • Check whether a CDN, reverse proxy, Thruster or Rack::Cache caches public responses of your Rails application that honour Vary.
  • Apply the workaround if you cannot patch promptly.
  • Monitor for unexpected HTML or JSON responses from cached pages.

Public exploits

PoC-in-GitHub, Metasploit and Exploit-DB list nothing for this CVE.

Research sources

Researched and written up in English and German by an AI (Claude by Anthropic) based on NVD, CISA, EPSS and the sources listed. The vendor information is authoritative. Researched on 11 Nov 2026, 19:46.

Original description (NVD)

Action Pack is a framework for handling and responding to web requests. Prior to 8.1.4.1 and 8.0.5.2, 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. This issue is fixed in versions 8.1.4.1 and 8.0.5.2.

NVD references (5)

Sources

The tracker combines official, freely usable data sources – updated continuously:

This product uses data from the NVD API but is not endorsed or certified by the NVD. EPSS data © FIRST.org.

Affected? We can help.

We check whether your systems are affected, install updates and close the gap – continuously with the System Health Checker if you wish.