Skip to content

Commit 93a9102

Browse files
Update dependency rack to v3.2.6 [SECURITY] (#788)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [rack](https://redirect.github.com/rack/rack) ([changelog](https://redirect.github.com/rack/rack/blob/main/CHANGELOG.md)) | `3.2.5` → `3.2.6` | ![age](https://developer.mend.io/api/mc/badges/age/rubygems/rack/3.2.6?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/rubygems/rack/3.2.5/3.2.6?slim=true) | ### GitHub Vulnerability Alerts #### [CVE-2026-34786](https://redirect.github.com/rack/rack/security/advisories/GHSA-q4qf-9j86-f5mh) ## Summary `Rack::Static#applicable_rules` evaluates several `header_rules` types against the raw URL-encoded `PATH_INFO`, while the underlying file-serving path is decoded before the file is served. As a result, a request for a URL-encoded variant of a static path can serve the same file without the headers that `header_rules` were intended to apply. In deployments that rely on `Rack::Static` to attach security-relevant response headers to static content, this can allow an attacker to bypass those headers by requesting an encoded form of the path. ## Details `Rack::Static#applicable_rules` matches rule types such as `:fonts`, `Array`, and `Regexp` directly against the incoming `PATH_INFO`. For example: ```ruby when :fonts /\.(?:ttf|otf|eot|woff2|woff|svg)\z/.match?(path) when Array /\.(#{rule.join('|')})\z/.match?(path) when Regexp rule.match?(path) ``` These checks operate on the raw request path. If the request contains encoded characters such as `%2E` in place of `.`, the rule may fail to match even though the file path is later decoded and served successfully by the static file server. For example, both of the following requests may resolve to the same file on disk: ```text /fonts/test.woff /fonts/test%2Ewoff ``` but only the unencoded form may receive the headers configured through `header_rules`. This creates a canonicalization mismatch between the path used for header policy decisions and the path ultimately used for file serving. ## Impact Applications that rely on `Rack::Static` `header_rules` to apply security-relevant headers to static files may be affected. In affected deployments, an attacker can request an encoded variant of a static file path and receive the same file without the intended headers. Depending on how `header_rules` are used, this may bypass protections such as clickjacking defenses, content restrictions, or other response policies applied to static content. The practical impact depends on the configured rules and the types of files being served. If `header_rules` are only used for non-security purposes such as caching, the issue may have limited security significance. ## Mitigation * Update to a patched version of Rack that applies `header_rules` to a decoded path consistently with static file resolution. * Do not rely solely on `Rack::Static` `header_rules` for security-critical headers where encoded path variants may reach the application. * Prefer setting security headers at the reverse proxy or web server layer so they apply consistently to both encoded and unencoded path forms. * Normalize or reject encoded path variants for static content at the edge, where feasible. #### [CVE-2026-34785](https://redirect.github.com/rack/rack/security/advisories/GHSA-h2jq-g4cq-5ppq) ## Summary `Rack::Static` determines whether a request should be served as a static file using a simple string prefix check. When configured with URL prefixes such as `"/css"`, it matches any request path that begins with that string, including unrelated paths such as `"/css-config.env"` or `"/css-backup.sql"`. As a result, files under the static root whose names merely share the configured prefix may be served unintentionally, leading to information disclosure. ## Details `Rack::Static#route_file` performs static-route matching using logic equivalent to: ```ruby @&#8203;urls.any? { |url| path.index(url) == 0 } ``` This checks only whether the request path starts with the configured prefix string. It does not require a path segment boundary after the prefix. For example, with: ```ruby use Rack::Static, urls: ["/css", "/js"], root: "public" ``` the following path is matched as intended: ```text /css/style.css ``` but these paths are also matched: ```text /css-config.env /css-backup.sql /csssecrets.yml ``` If such files exist under the configured static root, Rack forwards the request to the file server and serves them as static content. This means a configuration intended to expose only directory trees such as `/css/...` and `/js/...` may also expose sibling files whose names begin with those same strings. ## Impact An attacker can request files under the configured static root whose names share a configured URL prefix and obtain their contents. In affected deployments, this may expose configuration files, secrets, backups, environment files, or other unintended static content located under the same root directory. ## Mitigation * Update to a patched version of Rack that enforces a path boundary when matching configured static URL prefixes. * Match only paths that are either exactly equal to the configured prefix or begin with `prefix + "/"`. * Avoid placing sensitive files under the `Rack::Static` root directory. * Prefer static URL mappings that cannot overlap with sensitive filenames. #### [CVE-2026-34826](https://redirect.github.com/rack/rack/security/advisories/GHSA-x8cg-fq8g-mxfx) ## Summary `Rack::Utils.get_byte_ranges` parses the HTTP `Range` header without limiting the number of individual byte ranges. Although the existing fix for CVE-2024-26141 rejects ranges whose total byte coverage exceeds the file size, it does not restrict the count of ranges. An attacker can supply many small overlapping ranges such as `0-0,0-0,0-0,...` to trigger disproportionate CPU, memory, I/O, and bandwidth consumption per request. This results in a denial of service condition in Rack file-serving paths that process multipart byte range responses. ## Details `Rack::Utils.get_byte_ranges` accepts a comma-separated list of byte ranges and validates them based on their aggregate size, but does not impose a limit on how many individual ranges may be supplied. As a result, a request such as: ```http Range: bytes=0-0,0-0,0-0,0-0,... ``` can contain thousands of overlapping one-byte ranges while still satisfying the total-size check added for CVE-2024-26141. When such a header is processed by Rack’s file-serving code, each range causes additional work, including multipart response generation, per-range iteration, file seek and read operations, and temporary string allocation for response size calculation and output. This allows a relatively small request header to trigger disproportionately expensive processing and a much larger multipart response. The issue is distinct from CVE-2024-26141. That fix prevents range sets whose total byte coverage exceeds the file size, but does not prevent a large number of overlapping ranges whose summed size remains within that limit. ## Impact Applications that expose file-serving paths with byte range support may be vulnerable to denial of service. An unauthenticated attacker can send crafted `Range` headers containing many small overlapping ranges to consume excessive CPU time, memory, file I/O, and bandwidth. Repeated requests may reduce application availability and increase pressure on workers and garbage collection. ## Mitigation * Update to a patched version of Rack that limits the number of accepted byte ranges. * Reject or normalize multipart byte range requests containing excessive range counts. * Consider disabling multipart range support where it is not required. * Apply request filtering or header restrictions at the reverse proxy or application boundary to limit abusive `Range` headers. #### [CVE-2026-34827](https://redirect.github.com/rack/rack/security/advisories/GHSA-v6x5-cg8r-vv6x) ## Summary `Rack::Multipart::Parser#handle_mime_head` parses quoted multipart parameters such as `Content-Disposition: form-data; name="..."` using repeated `String#index` searches combined with `String#slice!` prefix deletion. For escape-heavy quoted values, this causes super-linear processing. An unauthenticated attacker can send a crafted `multipart/form-data` request containing many parts with long backslash-escaped parameter values to trigger excessive CPU usage during multipart parsing. This results in a denial of service condition in Rack applications that accept multipart form data. ## Details `Rack::Multipart::Parser#handle_mime_head` parses quoted parameter values by repeatedly: 1. Searching for the next quote or backslash, 2. Copying the preceding substring into a new buffer, and 3. Removing the processed prefix from the original string with `slice!`. An attacker can exploit this by sending a multipart request with many parts whose `name` parameters contain long escape-heavy values such as: ```text name="a\\a\\a\\a\\a\\..." ``` Under default Rack limits, a request can contain up to 4095 parts. If many of those parts use long quoted values with dense escape characters, the parser performs disproportionately expensive CPU work while remaining within normal request size and part-count limits. ## Impact Any Rack application that accepts `multipart/form-data` requests may be affected, including file upload endpoints and standard HTML form handlers. An unauthenticated attacker can send crafted multipart requests that consume excessive CPU time during request parsing. Repeated requests can tie up application workers, reduce throughput, and degrade or deny service availability. ## Mitigation * Update to a patched version of Rack that parses quoted multipart parameters without repeated rescanning and destructive prefix deletion. * Apply request throttling or rate limiting to multipart upload endpoints. * Where operationally feasible, restrict or isolate multipart parsing on untrusted high-volume endpoints. #### [CVE-2026-26961](https://redirect.github.com/rack/rack/security/advisories/GHSA-vgpv-f759-9wx3) ## Summary `Rack::Multipart::Parser` extracts the `boundary` parameter from `multipart/form-data` using a greedy regular expression. When a `Content-Type` header contains multiple `boundary` parameters, Rack selects the last one rather than the first. In deployments where an upstream proxy, WAF, or intermediary interprets the first `boundary` parameter, this mismatch can allow an attacker to smuggle multipart content past upstream inspection and have Rack parse a different body structure than the intermediary validated. ## Details Rack identifies the multipart boundary using logic equivalent to: ```ruby MULTIPART = %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|ni ``` Because the expression is greedy, it matches the last `boundary=` parameter in a header such as: ```http Content-Type: multipart/form-data; boundary=safe; boundary=malicious ``` As a result, Rack parses the request body using `malicious`, while another component may interpret the same header using `safe`. This creates an interpretation conflict. If an upstream WAF or proxy inspects multipart parts using the first boundary and Rack later parses the body using the last boundary, a client may be able to place malicious form fields or uploaded content in parts that Rack accepts but the upstream component did not inspect as intended. This issue is most relevant in layered deployments where security decisions are made before the request reaches Rack. ## Impact Applications that accept `multipart/form-data` uploads behind an inspecting proxy or WAF may be affected. In such deployments, an attacker may be able to bypass upstream filtering of uploaded files or form fields by sending a request with multiple `boundary` parameters and relying on the intermediary and Rack to parse the request differently. The practical impact depends on deployment architecture. If no upstream component relies on a different multipart interpretation, this behavior may not provide meaningful additional attacker capability. ## Mitigation * Update to a patched version of Rack that rejects ambiguous multipart `Content-Type` headers or parses duplicate `boundary` parameters consistently. * Reject requests containing multiple `boundary` parameters. * Normalize or regenerate multipart metadata at the trusted edge before forwarding requests to Rack. * Avoid relying on upstream inspection of malformed multipart requests unless duplicate parameter handling is explicitly consistent across components. #### [CVE-2026-26962](https://redirect.github.com/rack/rack/security/advisories/GHSA-rx22-g9mx-qrhv) ## Summary `Rack::Multipart::Parser` unfolds folded multipart part headers incorrectly. When a multipart header contains an obs-fold sequence, Rack preserves the embedded CRLF in parsed parameter values such as `filename` or `name` instead of removing the folded line break during unfolding. As a result, applications that later reuse those parsed values in HTTP response headers may be vulnerable to downstream header injection or response splitting. ## Details `Rack::Multipart::Parser` accepts folded multipart header values and unfolds them during parsing. However, the unfolding behavior does not fully remove the embedded line break sequence from the parsed value. This means a multipart part header such as: ```http Content-Disposition: form-data; name="file"; filename="test\r\n foo.txt" ``` can result in a parsed parameter value that still contains CRLF characters. The issue is not that Rack creates a second multipart header field. Rather, the problem is that CRLF remains embedded in the parsed metadata value after unfolding. If an application later uses that value in a security-sensitive context, such as constructing an HTTP response header, the preserved CRLF may alter downstream header parsing. Affected values may include multipart parameters such as `filename`, `name`, or similar parsed header attributes. ## Impact Applications that accept multipart form uploads may be affected if they later reuse parsed multipart metadata in HTTP headers or other header-sensitive contexts. In affected deployments, an attacker may be able to supply a multipart parameter value containing folded line breaks and cause downstream header injection, response splitting, cache poisoning, or related response parsing issues. The practical impact depends on application behavior. If parsed multipart metadata is not reused in HTTP headers, the issue may be limited to incorrect parsing behavior rather than a direct exploit path. ## Mitigation * Update to a patched version of Rack that removes CRLF correctly when unfolding folded multipart header values. * Avoid copying upload metadata such as `filename` directly into HTTP response headers without sanitization. * Sanitize or reject carriage return and line feed characters in multipart-derived values before reusing them in response headers, logs, or downstream protocol contexts. * Where feasible, normalize uploaded filenames before storing or reflecting them. #### [CVE-2026-32762](https://redirect.github.com/rack/rack/security/advisories/GHSA-qfgr-crr9-7r49) ## Summary `Rack::Utils.forwarded_values` parses the RFC 7239 `Forwarded` header by splitting on semicolons before handling quoted-string values. Because quoted values may legally contain semicolons, a header such as: ```http Forwarded: for="127.0.0.1;host=evil.com;proto=https" ``` can be interpreted by Rack as multiple `Forwarded` directives rather than as a single quoted `for` value. In deployments where an upstream proxy, WAF, or intermediary validates or preserves quoted `Forwarded` values differently, this discrepancy can allow an attacker to smuggle `host`, `proto`, `for`, or `by` parameters through a single header value. ## Details `Rack::Utils.forwarded_values` processes the header using logic equivalent to: ```ruby forwarded_header.split(';').each_with_object({}) do |field, values| field.split(',').each do |pair| pair = pair.split('=').map(&:strip).join('=') return nil unless pair =~ /\A(by|for|host|proto)="?([^"]+)"?\Z/i (values[$1.downcase.to_sym] ||= []) << $2 end end ``` The method splits on `;` before it parses individual `name=value` pairs. This is inconsistent with RFC 7239, which permits quoted-string values, and quoted strings may contain semicolons as literal content. As a result, a header value such as: ```http Forwarded: for="127.0.0.1;host=evil.com;proto=https" ``` is not treated as a single `for` value. Instead, Rack may interpret it as if the client had supplied separate `for`, `host`, and `proto` directives. This creates an interpretation conflict when another component in front of Rack treats the quoted value as valid literal content, while Rack reparses it as multiple forwarding parameters. ## Impact Applications that rely on `Forwarded` to derive request metadata may observe attacker-controlled values for `host`, `proto`, `for`, or related URL components. In affected deployments, this can lead to host or scheme spoofing in derived values such as `req.host`, `req.scheme`, `req.base_url`, or `req.url`. Applications that use those values for password reset links, redirects, absolute URL generation, logging, IP-based decisions, or backend requests may be vulnerable to downstream security impact. The practical security impact depends on deployment architecture. If clients can already supply arbitrary trusted `Forwarded` parameters directly, this bug may not add meaningful attacker capability. The issue is most relevant where an upstream component and Rack interpret the same `Forwarded` header differently. ## Mitigation * Update to a patched version of Rack that parses `Forwarded` quoted-string values before splitting on parameter delimiters. * Avoid trusting client-supplied `Forwarded` headers unless they are normalized or regenerated by a trusted reverse proxy. * Prefer stripping inbound `Forwarded` headers at the edge and reconstructing them from trusted proxy metadata. * Avoid using `req.host`, `req.scheme`, `req.base_url`, or `req.url` for security-sensitive operations unless the forwarding chain is explicitly trusted and validated. #### [CVE-2026-34230](https://redirect.github.com/rack/rack/security/advisories/GHSA-v569-hp3g-36wr) ## Summary `Rack::Utils.select_best_encoding` processes `Accept-Encoding` values with quadratic time complexity when the header contains many wildcard (`*`) entries. Because this method is used by `Rack::Deflater` to choose a response encoding, an unauthenticated attacker can send a single request with a crafted `Accept-Encoding` header and cause disproportionate CPU consumption on the compression middleware path. This results in a denial of service condition for applications using `Rack::Deflater`. ## Details `Rack::Utils.select_best_encoding` expands parsed `Accept-Encoding` values into a list of candidate encodings. When an entry is `*`, the method computes the set of concrete encodings by subtracting the encodings already present in the request: ```ruby if m == "*" (available_encodings - accept_encoding.map(&:first)).each do |m2| expanded_accept_encoding << [m2, q, preference] end else expanded_accept_encoding << [m, q, preference] end ``` Because `accept_encoding.map(&:first)` is evaluated inside the loop, it is recomputed for each wildcard entry. If the request contains `N` wildcard entries, this produces repeated scans over the full parsed header and causes quadratic behavior. After expansion, the method also performs additional work over `expanded_accept_encoding`, including per-entry deletion, which further increases the cost for large inputs. `Rack::Deflater` invokes this method for each request when the middleware is enabled: ```ruby Utils.select_best_encoding(ENCODINGS, Utils.parse_encodings(accept_encoding)) ``` As a result, a client can trigger this expensive code path simply by sending a large `Accept-Encoding` header containing many repeated wildcard values. For example, a request with an approximately 8 KB `Accept-Encoding` header containing about 1,000 `*;q=0.5` entries can cause roughly 170 ms of CPU time in a single request on the `Rack::Deflater` path, compared to a negligible baseline for a normal header. This issue is distinct from CVE-2024-26146. That issue concerned regular expression denial of service during `Accept` header parsing, whereas this issue arises later during encoding selection after the header has already been parsed. ## Impact Any Rack application using `Rack::Deflater` may be affected. An unauthenticated attacker can send requests with crafted `Accept-Encoding` headers to trigger excessive CPU usage in the encoding selection logic. Repeated requests can consume worker time disproportionately and reduce application availability. The attack does not require invalid HTTP syntax or large payload bodies. A single header-sized request is sufficient to reach the vulnerable code path. ## Mitigation * Update to a patched version of Rack in which encoding selection does not repeatedly rescan the parsed header for wildcard entries. * Avoid enabling `Rack::Deflater` on untrusted traffic. * Apply request filtering or header size / format restrictions at the reverse proxy or application boundary to limit abusive `Accept-Encoding` values. #### [CVE-2026-34763](https://redirect.github.com/rack/rack/security/advisories/GHSA-7mqq-6cf9-v2qp) ## Summary `Rack::Directory` interpolates the configured `root` path directly into a regular expression when deriving the displayed directory path. If `root` contains regex metacharacters such as `+`, `*`, or `.`, the prefix stripping can fail and the generated directory listing may expose the full filesystem path in the HTML output. ## Details `Rack::Directory::DirectoryBody#each` computes the visible path using code equivalent to: ```ruby show_path = Utils.escape_html(path.sub(/\A#{root}/, '')) ``` Here, `root` is a developer-configured filesystem path. It is normalized earlier with `File.expand_path(root)` and then inserted directly into a regular expression without escaping. Because the value is treated as regex syntax rather than as a literal string, metacharacters in the configured path can change how the prefix match behaves. When that happens, the expected root prefix is not removed from `path`, and the absolute filesystem path is rendered into the HTML directory listing. ## Impact If `Rack::Directory` is configured to serve a directory whose absolute path contains regex metacharacters, the generated directory listing may disclose the full server filesystem path instead of only the request-relative path. This can expose internal deployment details such as directory layout, usernames, mount points, or naming conventions that would otherwise not be visible to clients. ## Mitigation * Update to a patched version of Rack in which the root prefix is removed using an escaped regular expression. * Avoid using `Rack::Directory` with a root path that contains regular expression metacharacters. #### [CVE-2026-34829](https://redirect.github.com/rack/rack/security/advisories/GHSA-8vqr-qjwx-82mw) ## Summary `Rack::Multipart::Parser` only wraps the request body in a `BoundedIO` when `CONTENT_LENGTH` is present. When a `multipart/form-data` request is sent without a `Content-Length` header, such as with HTTP chunked transfer encoding, multipart parsing continues until end-of-stream with no total size limit. For file parts, the uploaded body is written directly to a temporary file on disk rather than being constrained by the buffered in-memory upload limit. An unauthenticated attacker can therefore stream an arbitrarily large multipart file upload and consume unbounded disk space. This results in a denial of service condition for Rack applications that accept multipart form data. ## Details `Rack::Multipart::Parser.parse` applies `BoundedIO` only when `content_length` is not `nil`: ```ruby io = BoundedIO.new(io, content_length) if content_length ``` When `CONTENT_LENGTH` is absent, the parser reads the multipart body until EOF without a global byte limit. Although Rack enforces `BUFFERED_UPLOAD_BYTESIZE_LIMIT` for retained non-file parts, file uploads are handled differently. When a multipart part includes a filename, the body is streamed to a `Tempfile`, and the retained-size accounting is not applied to that file content. As a result, file parts are not subject to the same upload size bound. An attacker can exploit this by sending a chunked `multipart/form-data` request containing a file part and continuously streaming data without declaring a `Content-Length`. Rack will continue writing the uploaded data to disk until the client stops or the server exhausts available storage. ## Impact Any Rack application that accepts `multipart/form-data` uploads may be affected if no upstream component enforces a request body size limit. An unauthenticated attacker can send a large chunked file upload to consume disk space on the application host. This may cause request failures, application instability, or broader service disruption if the host runs out of available storage. The practical impact depends on deployment architecture. Reverse proxies or application servers that enforce upload limits may reduce or eliminate exploitability, but Rack itself does not impose a total multipart upload limit in this code path when `CONTENT_LENGTH` is absent. ## Mitigation * Update to a patched version of Rack that enforces a total multipart upload size limit even when `CONTENT_LENGTH` is absent. * Enforce request body size limits at the reverse proxy or application server. * Isolate temporary upload storage and monitor disk consumption for multipart endpoints. #### [CVE-2026-34830](https://redirect.github.com/rack/rack/security/advisories/GHSA-qv7j-4883-hwh7) ## Summary `Rack::Sendfile#map_accel_path` interpolates the value of the `X-Accel-Mapping` request header directly into a regular expression when rewriting file paths for `X-Accel-Redirect`. Because the header value is not escaped, an attacker who can supply `X-Accel-Mapping` to the backend can inject regex metacharacters and control the generated `X-Accel-Redirect` response header. In deployments using `Rack::Sendfile` with `x-accel-redirect`, this can allow an attacker to cause nginx to serve unintended files from configured internal locations. ## Details `Rack::Sendfile#map_accel_path` processes header-supplied mappings using logic equivalent to: ```ruby mapping.split(',').map(&:strip).each do |m| internal, external = m.split('=', 2).map(&:strip) new_path = path.sub(/\A#{internal}/i, external) return new_path unless path == new_path end ``` Here, `internal` comes from the `HTTP_X_ACCEL_MAPPING` request header and is inserted directly into a regular expression without escaping. This gives the header value regex semantics rather than treating it as a literal prefix. As a result, an attacker can supply metacharacters such as `.*` or capture groups to alter how the path substitution is performed. For example, a mapping such as: ```http X-Accel-Mapping: .*=/protected/secret.txt ``` causes the entire source path to match and rewrites the redirect target to a clean attacker-chosen internal path. This differs from the documented behavior of the header-based mapping path, which is described as a simple substitution. While application-supplied mappings may intentionally support regular expressions, header-supplied mappings should be treated as literal path prefixes. The issue is only exploitable when untrusted `X-Accel-Mapping` headers can reach Rack. One realistic case is a reverse proxy configuration that intends to set `X-Accel-Mapping` itself, but fails to do so on some routes, allowing a client-supplied header to pass through unchanged. ## Impact Applications using `Rack::Sendfile` with `x-accel-redirect` may be affected if the backend accepts attacker-controlled `X-Accel-Mapping` headers. In affected deployments, an attacker may be able to control the `X-Accel-Redirect` response header and cause nginx to serve files from internal locations that were not intended to be reachable through the application. This can lead to unauthorized file disclosure. The practical impact depends on deployment architecture. If the proxy always strips or overwrites `X-Accel-Mapping`, or if the application uses explicit configured mappings instead of the request header, exploitability may be eliminated. ## Mitigation * Update to a patched version of Rack that treats header-supplied `X-Accel-Mapping` values as literal strings rather than regular expressions. * Strip or overwrite inbound `X-Accel-Mapping` headers at the reverse proxy so client-supplied values never reach Rack. * Prefer explicit application-configured sendfile mappings instead of relying on request-header mappings. * Review proxy sub-locations and inherited header settings to ensure `X-Accel-Mapping` is consistently set on all backend routes. #### [CVE-2026-34831](https://redirect.github.com/rack/rack/security/advisories/GHSA-q2ww-5357-x388) ## Summary `Rack::Files#fail` sets the `Content-Length` response header using `String#size` instead of `String#bytesize`. When the response body contains multibyte UTF-8 characters, the declared `Content-Length` is smaller than the number of bytes actually sent on the wire. Because `Rack::Files` reflects the requested path in 404 responses, an attacker can trigger this mismatch by requesting a non-existent path containing percent-encoded UTF-8 characters. This results in incorrect HTTP response framing and may cause response desynchronization in deployments that rely on the incorrect `Content-Length` value. ## Details `Rack::Files#fail` constructs error responses using logic equivalent to: ```ruby def fail(status, body, headers = {}) body += "\n" [ status, { "content-type" => "text/plain", "content-length" => body.size.to_s, "x-cascade" => "pass" }.merge!(headers), [body] ] end ``` Here, `body.size` returns the number of characters, not the number of bytes. For multibyte UTF-8 strings, this produces an incorrect `Content-Length` value. `Rack::Files` includes the decoded request path in 404 responses. A request containing percent-encoded UTF-8 path components therefore causes the response body to contain multibyte characters, while the `Content-Length` header still reflects character count rather than byte count. As a result, the server can send more bytes than declared in the response headers. This violates HTTP message framing requirements, which define `Content-Length` as the number of octets in the message body. ## Impact Applications using `Rack::Files` may emit incorrectly framed error responses when handling requests for non-existent paths containing multibyte characters. In some deployment topologies, particularly with keep-alive connections and intermediaries that rely on `Content-Length`, this mismatch may lead to response parsing inconsistencies or response desynchronization. The practical exploitability depends on the behavior of downstream proxies, clients, and connection reuse. Even where no secondary exploitation is possible, the response is malformed and may trigger protocol errors in strict components. ## Mitigation * Update to a patched version of Rack that computes `Content-Length` using `String#bytesize`. * Avoid exposing `Rack::Files` directly to untrusted traffic until a fix is available, if operationally feasible. * Where possible, place Rack behind a proxy or server that normalizes or rejects malformed backend responses. * Prefer closing backend connections on error paths if response framing anomalies are a concern. #### [CVE-2026-34835](https://redirect.github.com/rack/rack/security/advisories/GHSA-g2pf-xv49-m2h5) ## Summary `Rack::Request` parses the `Host` header using an `AUTHORITY` regular expression that accepts characters not permitted in RFC-compliant hostnames, including `/`, `?`, `#`, and `@`. Because `req.host` returns the full parsed value, applications that validate hosts using naive prefix or suffix checks can be bypassed. For example, a check such as `req.host.start_with?("myapp.com")` can be bypassed with `Host: myapp.com@evil.com`, and a check such as `req.host.end_with?("myapp.com")` can be bypassed with `Host: evil.com/myapp.com`. This can lead to host header poisoning in applications that use `req.host`, `req.url`, or `req.base_url` for link generation, redirects, or origin validation. ## Details `Rack::Request` parses the authority component using logic equivalent to: ```ruby AUTHORITY = / \A (?<host> \[(?<address>#{ipv6})\] | (?<address>[[[:graph:]&&[^\[\]]]]*?) ) (:(?<port>\d+))? \z /x ``` The character class used for non-IPv6 hosts accepts nearly all printable characters except `[` and `]`. This includes reserved URI delimiters such as `@`, `/`, `?`, and `#`, which are not valid hostname characters under RFC 3986 host syntax. As a result, values such as the following are accepted and returned through `req.host`: ```text myapp.com@evil.com evil.com/myapp.com evil.com#myapp.com ``` Applications that attempt to allowlist hosts using string prefix or suffix checks may therefore treat attacker-controlled hosts as trusted. For example: ```ruby req.host.start_with?("myapp.com") ``` accepts: ```text myapp.com@evil.com ``` and: ```ruby req.host.end_with?("myapp.com") ``` accepts: ```text evil.com/myapp.com ``` When those values are later used to build absolute URLs or enforce origin restrictions, the application may produce attacker-controlled results. ## Impact Applications that rely on `req.host`, `req.url`, or `req.base_url` may be affected if they perform naive host validation or assume Rack only returns RFC-valid hostnames. In affected deployments, an attacker may be able to bypass host allowlists and poison generated links, redirects, or origin-dependent security decisions. This can enable attacks such as password reset link poisoning or other host header injection issues. The practical impact depends on application behavior. If the application or reverse proxy already enforces strict host validation, exploitability may be reduced or eliminated. ## Mitigation * Update to a patched version of Rack that rejects invalid authority characters in `Host`. * Enforce strict `Host` header validation at the reverse proxy or load balancer. * Do not rely on prefix or suffix string checks such as `start_with?` or `end_with?` for host allowlisting. * Use exact host allowlists, or exact subdomain boundary checks, after validating that the host is syntactically valid. --- ### Release Notes <details> <summary>rack/rack (rack)</summary> ### [`v3.2.6`](https://redirect.github.com/rack/rack/blob/HEAD/CHANGELOG.md#326---2026-04-01) [Compare Source](https://redirect.github.com/rack/rack/compare/v3.2.5...v3.2.6) ##### Security - [CVE-2026-34763](https://redirect.github.com/advisories/GHSA-7mqq-6cf9-v2qp) Root directory disclosure via unescaped regex interpolation in `Rack::Directory`. - [CVE-2026-34230](https://redirect.github.com/advisories/GHSA-v569-hp3g-36wr) Avoid O(n^2) algorithm in `Rack::Utils.select_best_encoding` which could lead to denial of service. - [CVE-2026-32762](https://redirect.github.com/advisories/GHSA-qfgr-crr9-7r49) Forwarded header semicolon injection enables Host and Scheme spoofing. - [CVE-2026-26961](https://redirect.github.com/advisories/GHSA-vgpv-f759-9wx3) Raise error for multipart requests with multiple boundary parameters. - [CVE-2026-34786](https://redirect.github.com/advisories/GHSA-q4qf-9j86-f5mh) `Rack::Static` `header_rules` bypass via URL-encoded path mismatch. - [CVE-2026-34831](https://redirect.github.com/advisories/GHSA-q2ww-5357-x388) `Content-Length` mismatch in `Rack::Files` error responses. - [CVE-2026-34826](https://redirect.github.com/advisories/GHSA-x8cg-fq8g-mxfx) Multipart byte range processing allows denial of service via excessive overlapping ranges. - [CVE-2026-34835](https://redirect.github.com/advisories/GHSA-g2pf-xv49-m2h5) `Rack::Request` accepts invalid Host characters, enabling host allowlist bypass. - [CVE-2026-34830](https://redirect.github.com/advisories/GHSA-qv7j-4883-hwh7) `Rack::Sendfile` header-based `X-Accel-Mapping` regex injection enables unauthorized `X-Accel-Redirect`. - [CVE-2026-34785](https://redirect.github.com/advisories/GHSA-h2jq-g4cq-5ppq) `Rack::Static` prefix matching can expose unintended files under the static root. - [CVE-2026-34829](https://redirect.github.com/advisories/GHSA-8vqr-qjwx-82mw) Multipart parsing without `Content-Length` header allows unbounded chunked file uploads. - [CVE-2026-34827](https://redirect.github.com/advisories/GHSA-v6x5-cg8r-vv6x) Multipart header parsing allows denial of service via escape-heavy quoted parameters. - [CVE-2026-26962](https://redirect.github.com/advisories/GHSA-rx22-g9mx-qrhv) Improper unfolding of folded multipart headers preserves CRLF in parsed parameter values. </details> --- ### Configuration 📅 **Schedule**: Branch creation - "" in timezone Asia/Tokyo, Automerge - At any time (no schedule defined). 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/line/line-bot-sdk-ruby). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDIuMTEiLCJ1cGRhdGVkSW5WZXIiOiI0My4xMDIuMTEiLCJ0YXJnZXRCcmFuY2giOiJtYXN0ZXIiLCJsYWJlbHMiOlsiZGVwZW5kZW5jeSB1cGdyYWRlIl19--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
1 parent d49a4c0 commit 93a9102

File tree

1 file changed

+1
-1
lines changed

1 file changed

+1
-1
lines changed

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ GEM
7171
stringio
7272
public_suffix (6.0.2)
7373
racc (1.8.1)
74-
rack (3.2.5)
74+
rack (3.2.6)
7575
rackup (2.3.1)
7676
rack (>= 3)
7777
rainbow (3.1.1)

0 commit comments

Comments
 (0)