CVE-2026-34786 Overview
CVE-2026-34786 is a security header bypass vulnerability in Rack, the modular Ruby web server interface used by Rails and many other Ruby frameworks. The flaw exists in Rack::Static#applicable_rules, which evaluates several header_rules types against the raw URL-encoded PATH_INFO. The underlying file-serving logic, however, decodes the path before serving the file. Attackers can request a URL-encoded variant of a static path to retrieve the same file without the security-relevant response headers that header_rules was configured to apply. The issue is fixed in Rack versions 2.2.23, 3.1.21, and 3.2.6.
Critical Impact
Remote, unauthenticated attackers can strip security headers (such as Content-Security-Policy, X-Frame-Options, or Strict-Transport-Security) from static asset responses by requesting URL-encoded path variants.
Affected Products
- Rack versions prior to 2.2.23
- Rack versions 3.0.x through 3.1.20
- Rack versions 3.2.0 through 3.2.5
Discovery Timeline
- 2026-04-02 - CVE-2026-34786 published to the National Vulnerability Database
- 2026-04-16 - Last updated in NVD database
Technical Details for CVE-2026-34786
Vulnerability Analysis
The vulnerability stems from inconsistent path handling between two stages of Rack::Static request processing. When a static request arrives, Rack::Static#applicable_rules inspects PATH_INFO to determine which configured header_rules apply to the response. This inspection occurs against the raw, URL-encoded path string. The file lookup stage then performs URL decoding before resolving the static asset on disk.
This decoding mismatch is classified as [CWE-180] Incorrect Behavior Order: Validate Before Canonicalize. An attacker who requests /%61ssets/app.js instead of /assets/app.js receives the same file because the file server canonicalizes the path. The rule matcher, operating on the encoded string, fails to match the /assets prefix and therefore omits any headers tied to that rule.
Root Cause
The root cause is that applicable_rules matches header-rule patterns against an un-normalized path representation. Path canonicalization must occur before, not after, security policy evaluation. Any rule that depends on prefix matching, suffix matching, or path equality can be evaded by substituting URL-encoded equivalents for ASCII characters.
Attack Vector
An attacker sends an HTTP request to a Rack-served static asset using percent-encoded characters in the path. The encoded path bypasses the header_rules match logic but still resolves to the intended file. The response returns the asset content without the protective headers. Downstream attacks become possible when the missing headers were the primary defense, such as Content-Security-Policy blocking script execution or X-Frame-Options preventing clickjacking on framed static HTML.
No authentication or user interaction is required. Exploitation requires only the ability to send HTTP requests to the affected application.
Detection Methods for CVE-2026-34786
Indicators of Compromise
- HTTP access logs containing percent-encoded characters in paths to static asset directories, such as %61, %2F, or mixed-case encodings of normal ASCII characters
- Responses to static asset requests that lack expected security headers like Content-Security-Policy, X-Frame-Options, or Strict-Transport-Security
- Repeated requests to the same asset path with varying encoding patterns from a single source
Detection Strategies
- Compare response headers between canonical and percent-encoded variants of the same static path during security testing
- Parse web server access logs for static asset URIs containing % sequences that decode to standard ASCII letters
- Audit Rack application configurations that use Rack::Static with header_rules to identify exposed deployments
Monitoring Recommendations
- Forward Rack and reverse-proxy access logs to a centralized analytics platform and alert on anomalous encoding in static paths
- Implement automated header-presence checks in CI pipelines that probe both encoded and decoded variants of protected paths
- Track the installed Rack gem version across application inventories and flag any host running a vulnerable release
How to Mitigate CVE-2026-34786
Immediate Actions Required
- Upgrade Rack to version 2.2.23, 3.1.21, or 3.2.6 depending on the major version branch in use
- Inventory all Ruby applications and bundled gems to identify deployments running affected Rack versions
- Validate that security headers are returned for both encoded and decoded variants of protected static paths after patching
Patch Information
The Rack maintainers released fixes in versions 2.2.23, 3.1.21, and 3.2.6. The patched releases normalize PATH_INFO before evaluating header_rules, ensuring that encoded and decoded paths produce identical header sets. Details are available in the Rack GitHub Security Advisory GHSA-q4qf-9j86-f5mh.
Workarounds
- Move security header enforcement to a reverse proxy such as nginx or a CDN edge layer that applies headers uniformly regardless of path encoding
- Replace Rack::Static for security-sensitive deployments with middleware that canonicalizes paths before rule evaluation
- Configure a Web Application Firewall rule to reject or canonicalize requests containing percent-encoded ASCII alphanumerics in static asset paths
# Update Rack via Bundler
bundle update rack
# Verify installed version
bundle show rack
# Pin a fixed version in Gemfile
# gem 'rack', '>= 3.2.6'
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


