See how rack compares to other vendors in security performance
Rack::Session::Cookie incorrectly handles decryption failures when configured with secrets:. If cookie decryption fails, the implementation falls back to a default decoder instead of rejecting the cookie. This allows an unauthenticated attacker to supply a crafted session cookie that is accepted as valid session data without knowledge of any configured secret.
Because this mechanism is used to load session state, an attacker can manipulate session contents and potentially gain unauthorized access.
Details
When secrets: is configured, Rack::Session::Cookie attempts to decrypt incoming session cookies using one of the configured encryptors. If all decrypt attempts fail, the implementation does not reject the cookie. Instead, it falls back to decoding the cookie using a default coder.
This fallback path processes attacker-controlled cookie data as trusted session state. The behavior is implicit and occurs even when encrypted cookies are expected.
The fallback decoder is applied automatically and does not require the application to opt into a non-encrypted session format. As a result, a client can send a specially crafted cookie value that bypasses the intended integrity protections provided by secrets:.
This issue affects both default configurations and those using alternative serializers for encrypted payloads.
Impact
Any Rack application using Rack::Session::Cookie with secrets: may be affected.
[!NOTE] Rails applications are typically not affected — Rails uses ActionDispatch::Session::CookieStore, which is a separate implementation backed by ActiveSupport::MessageEncryptor and does not share the vulnerable code path.
An unauthenticated attacker can supply a crafted session cookie that is accepted as valid session data. This can lead to authentication bypass or privilege escalation in applications that rely on session values for identity or authorization decisions.
Depending on application behavior and available runtime components, processing of untrusted session data may also expose additional risks.
Mitigation
Update to a patched version ofrack-session that rejects cookies when decryption fails under the secrets: configuration. After updating, rotate session secrets to invalidate existing session cookies, since attacker-supplied session data may have been accepted and re-issued prior to the fix.
Possible Denial of Service Vulnerability in Rack Header Parsing
There is a possible denial of service vulnerability in the header parsing routines in Rack. This vulnerability has been assigned the CVE identifier CVE-2024-26146.
Versions Affected: All. Not affected: None Fixed Versions: 2.0.9.4, 2.1.4.4, 2.2.8.1, 3.0.9.1
Impact ------ Carefully crafted headers can cause header parsing in Rack to take longer than expected resulting in a possible denial of service issue. Accept and Forwarded headers are impacted.
Ruby 3.2 has mitigations for this problem, so Rack applications using Ruby 3.2 or newer are unaffected.
Releases -------- The fixed releases are available at the normal locations.
Workarounds ----------- There are no feasible workarounds for this issue.
Patches ------- To aid users who aren't able to upgrade immediately we have provided patches for the two supported release series. They are in git-am format and consist of a single changeset.
2-0-header-redos.patch - Patch for 2.0 series 2-1-header-redos.patch - Patch for 2.1 series 2-2-header-redos.patch - Patch for 2.2 series 3-0-header-redos.patch - Patch for 3.0 series
Credits -------
Thanks to svalkanov for reporting this and providing patches!
Possible DoS Vulnerability with Range Header in Rack
There is a possible DoS vulnerability relating to the Range request header in Rack. This vulnerability has been assigned the CVE identifier CVE-2024-26141.
Versions Affected: >= 1.3.0. Not affected: < 1.3.0 Fixed Versions: 3.0.9.1, 2.2.8.1
Impact ------ Carefully crafted Range headers can cause a server to respond with an unexpectedly large response. Responding with such large responses could lead to a denial of service issue.
Vulnerable applications will use the Rack::File middleware or the Rack::Utils.byteranges methods (this includes Rails applications).
Releases -------- The fixed releases are available at the normal locations.
Workarounds ----------- There are no feasible workarounds for this issue.
Patches ------- To aid users who aren't able to upgrade immediately we have provided patches for the two supported release series. They are in git-am format and consist of a single changeset.
3-0-range.patch - Patch for 3.0 series 2-2-range.patch - Patch for 2.2 series
Credits -------
Thank you oooooooq for the report and patch
Summary
ruby module Rack class MediaType SPLITPATTERN = %r{\s[;,]\s} The above regexp is subject to ReDos. 50K blank characters as a prefix to the header will take over 10s to split.
PoC
A simple HTTP request with lots of blank characters in the content-type header:
ruby request["Content-Type"] = (" " 50000) + "a,"
Impact
It's a very easy to craft ReDoS. Like all ReDoS the impact is debatable.
Summary
Rack::Static can serve files under the specified root: even if urls: are provided, which may expose other files under the specified root: unexpectedly.
Details
The vulnerability occurs because Rack::Static does not properly sanitize user-supplied paths before serving files. Specifically, encoded path traversal sequences are not correctly validated, allowing attackers to access files outside the designated static file directory.
Impact
By exploiting this vulnerability, an attacker can gain access to all files under the specified root: directory, provided they are able to determine then path of the file.
Mitigation
- Update to the latest version of Rack, or - Remove usage of Rack::Static, or - Ensure that root: points at a directory path which only contains files which should be accessed publicly.
It is likely that a CDN or similar static file server would also mitigate the issue.
Summary
Rack::QueryParser parses query strings and application/x-www-form-urlencoded bodies into Ruby data structures without imposing any limit on the number of parameters, allowing attackers to send requests with extremely large numbers of parameters.
Details
The vulnerability arises because Rack::QueryParser iterates over each &-separated key-value pair and adds it to a Hash without enforcing an upper bound on the total number of parameters. This allows an attacker to send a single request containing hundreds of thousands (or more) of parameters, which consumes excessive memory and CPU during parsing.
Impact
An attacker can trigger denial of service by sending specifically crafted HTTP requests, which can cause memory exhaustion or pin CPU resources, stalling or crashing the Rack server. This results in full service disruption until the affected worker is restarted.
Mitigation
- Update to a version of Rack that limits the number of parameters parsed, or - Use middleware to enforce a maximum query string size or parameter count, or - Employ a reverse proxy (such as Nginx) to limit request sizes and reject oversized query strings or bodies.
Limiting request body sizes and query string lengths at the web server or CDN level is an effective mitigation.
Summary
Rack::QueryParser in version < 2.2.18 enforces its paramslimit only for parameters separated by &, while still splitting on both & and ;. As a result, attackers could use ; separators to bypass the parameter count limit and submit more parameters than intended.
Details
The issue arises because Rack::QueryParser#checkquerystring counts only & characters when determining the number of parameters, but the default separator regex DEFAULTSEP = /[&;] /n splits on both & and ;. This mismatch means that queries using ; separators were not included in the parameter count, allowing paramslimit to be bypassed.
Other safeguards (bytesizelimit and keyspacelimit) still applied, but did not prevent this particular bypass.
Impact
Applications or middleware that directly invoke Rack::QueryParser with its default configuration (no explicit delimiter) could be exposed to increased CPU and memory consumption. This can be abused as a limited denial-of-service vector.
Rack::Request, the primary entry point for typical Rack applications, uses QueryParser in a safe way and does not appear vulnerable by default. As such, the severity is considered low, with the impact limited to edge cases where QueryParser is used directly.
Mitigation
Upgrade to a patched version of Rack where both & and ; are counted consistently toward paramslimit. If upgrading is not immediately possible, configure QueryParser with an explicit delimiter (e.g., &) to avoid the mismatch. As a general precaution, enforce query string and request size limits at the web server or proxy layer (e.g., Nginx, Apache, or a CDN) to mitigate excessive parsing overhead.
Summary
Rack::Multipart::Parser buffers the entire multipart preamble (bytes before the first boundary) in memory without any size limit. A client can send a large preamble followed by a valid boundary, causing significant memory use and potential process termination due to out-of-memory (OOM) conditions.
Details
While searching for the first boundary, the parser appends incoming data into a shared buffer (@sbuf.concat(content)) and scans for the boundary pattern:
ruby @sbuf.scanuntil(@bodyregex)
If the boundary is not yet found, the parser continues buffering data indefinitely. There is no trimming or size cap on the preamble, allowing attackers to send arbitrary amounts of data before the first boundary.
Impact
Remote attackers can trigger large transient memory spikes by including a long preamble in multipart/form-data requests. The impact scales with allowed request sizes and concurrency, potentially causing worker crashes or severe slowdown due to garbage collection.
Mitigation
Upgrade: Use a patched version of Rack that enforces a preamble size limit (e.g., 16 KiB) or discards preamble data entirely per RFC 2046 § 5.1.1. Workarounds: Limit total request body size at the proxy or web server level. Monitor memory and set per-process limits to prevent OOM conditions.
Summary
Rack::Multipart::Parser stores non-file form fields (parts without a filename) entirely in memory as Ruby String objects. A single large text field in a multipart/form-data request (hundreds of megabytes or more) can consume equivalent process memory, potentially leading to out-of-memory (OOM) conditions and denial of service (DoS).
Details
During multipart parsing, file parts are streamed to temporary files, but non-file parts are buffered into memory:
ruby body = String.new # non-file → in-RAM buffer @mimeparts[mimeindex].body << content
There is no size limit on these in-memory buffers. As a result, any large text field—while technically valid—will be loaded fully into process memory before being added to params.
Impact
Attackers can send large non-file fields to trigger excessive memory usage. Impact scales with request size and concurrency, potentially leading to worker crashes or severe garbage-collection overhead. All Rack applications processing multipart form submissions are affected.
Mitigation
Upgrade: Use a patched version of Rack that enforces a reasonable size cap for non-file fields (e.g., 2 MiB). Workarounds: Restrict maximum request body size at the web-server or proxy layer (e.g., Nginx clientmaxbodysize). Validate and reject unusually large form fields at the application level.
Summary
Rack::Multipart::Parser can accumulate unbounded data when a multipart part’s header block never terminates with the required blank line (CRLFCRLF). The parser keeps appending incoming bytes to memory without a size cap, allowing a remote attacker to exhaust memory and cause a denial of service (DoS).
Details
While reading multipart headers, the parser waits for CRLFCRLF using:
ruby @sbuf.scanuntil(/(.?\r\n)\r\n/m)
If the terminator never appears, it continues appending data (@sbuf.concat(content)) indefinitely. There is no limit on accumulated header bytes, so a single malformed part can consume memory proportional to the request body size.
Impact
Attackers can send incomplete multipart headers to trigger high memory use, leading to process termination (OOM) or severe slowdown. The effect scales with request size limits and concurrency. All applications handling multipart uploads may be affected.
Mitigation
Upgrade to a patched Rack version that caps per-part header size (e.g., 64 KiB). Until then, restrict maximum request sizes at the proxy or web server layer (e.g., Nginx clientmaxbodysize).
Summary
Rack::Request#POST reads the entire request body into memory for Content-Type: application/x-www-form-urlencoded, calling rack.input.read(nil) without enforcing a length or cap. Large request bodies can therefore be buffered completely into process memory before parsing, leading to denial of service (DoS) through memory exhaustion.
Details
When handling non-multipart form submissions, Rack’s request parser performs:
ruby formvars = getheader(RACKINPUT).read
Since read is called with no argument, the entire request body is loaded into a Ruby String. This occurs before query parameter parsing or enforcement of any paramslimit. As a result, Rack applications without an upstream body-size limit can experience unbounded memory allocation proportional to request size.
Impact
Attackers can send large application/x-www-form-urlencoded bodies to consume process memory, causing slowdowns or termination by the operating system (OOM). The effect scales linearly with request size and concurrency. Even with parsing limits configured, the issue occurs before those limits are enforced.
Mitigation
Update to a patched version of Rack that enforces form parameter limits using queryparser.bytesizelimit, preventing unbounded reads of application/x-www-form-urlencoded bodies. Enforce strict maximum body size at the proxy or web server layer (e.g., Nginx clientmaxbodysize, Apache LimitRequestBody).
Summary
Rack::Directory’s path check used a string prefix match on the expanded path. A request like /../rootexample/ can escape the configured root if the target path starts with the root string, allowing directory listing outside the intended root.
Details
In directory.rb, File.expandpath(File.join(root, pathinfo)).startwith?(root) does not enforce a path boundary. If the server root is /var/www/root, a path like /var/www/rootbackup passes the check because it shares the same prefix, so Rack::Directory will list that directory also.
Impact
Information disclosure via directory listing outside the configured root when Rack::Directory is exposed to untrusted clients and a directory shares the root prefix (e.g., public2, wwwbackup).
Mitigation
Update to a patched version of Rack that correctly checks the root prefix. Don't name directories with the same prefix as one which is exposed via Rack::Directory.
Summary
Rack::Utils.selectbestencoding 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.selectbestencoding 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 == "" (availableencodings - acceptencoding.map(&:first)).each do |m2| expandedacceptencoding << [m2, q, preference] end else expandedacceptencoding << [m, q, preference] end
Because acceptencoding.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 expandedacceptencoding, 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.selectbestencoding(ENCODINGS, Utils.parseencodings(acceptencoding))
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.
Summary
Rack::Sendfile#mapaccelpath 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#mapaccelpath processes header-supplied mappings using logic equivalent to:
ruby mapping.split(',').map(&:strip).each do |m| internal, external = m.split('=', 2).map(&:strip) newpath = path.sub(/\A#{internal}/i, external) return newpath unless path == newpath end
Here, internal comes from the HTTPXACCELMAPPING 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.
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#routefile performs static-route matching using logic equivalent to:
ruby @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.
Summary
Rack::Utils.getbyteranges 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.getbyteranges 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.
Summary
Rack::Multipart::Parser only wraps the request body in a BoundedIO when CONTENTLENGTH 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 contentlength is not nil:
ruby io = BoundedIO.new(io, contentlength) if contentlength
When CONTENTLENGTH is absent, the parser reads the multipart body until EOF without a global byte limit.
Although Rack enforces BUFFEREDUPLOADBYTESIZELIMIT 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 CONTENTLENGTH is absent.
Mitigation
Update to a patched version of Rack that enforces a total multipart upload size limit even when CONTENTLENGTH 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.
Summary
Rack::Multipart::Parser#handlemimehead 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#handlemimehead 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.
A DoS vulnerability exists in Rack <v3.0.4.2, <v2.2.6.3, <v2.1.4.3 and <v2.0.9.3 within in the Multipart MIME parsing code in which could allow an attacker to craft requests that can be abuse to cause multipart parsing to take longer than expected.
A denial of service vulnerability in the Range header parsing component of Rack >= 1.5.0. A Carefully crafted input can cause the Range header parsing component in Rack to take an unexpected amount of time, possibly resulting in a denial of service attack vector. Any applications that deal with Range requests (such as streaming applications, or applications that serve files) may be impacted.
A denial of service vulnerability in the multipart parsing component of Rack fixed in 2.0.9.2, 2.1.4.2, 2.2.4.1 and 3.0.0.1 could allow an attacker tocraft input that can cause RFC2183 multipart boundary parsing in Rack to take an unexpected amount of time, possibly resulting in a denial of service attack vector. Any applications that parse multipart posts using Rack (virtually all Rails applications) are impacted.
Carefully crafted input can cause Content-Disposition header parsing in Rack to take an unexpected amount of time, possibly resulting in a denial of service attack vector. This header is used typically used in multipart parsing. Any applications that parse multipart posts using Rack (virtually all Rails applications) are impacted.
Rack is a modular Ruby web server interface. In versions prior to 2.2.19, 3.1.17, and 3.2.2, Rack::Multipart::Parser buffers the entire multipart preamble (bytes before the first boundary) in memory without any size limit. A client can send a large preamble followed by a valid boundary, causing significant memory use and potential process termination due to out-of-memory (OOM) conditions. Remote attackers can trigger large transient memory spikes by including a long preamble in multipart/form-data requests. The impact scales with allowed request sizes and concurrency, potentially causing worker crashes or severe slowdown due to garbage collection. Versions 2.2.19, 3.1.17, and 3.2.2 enforce a preamble size limit (e.g., 16 KiB) or discard preamble data entirely. Workarounds include limiting total request body size at the proxy or web server level and monitoring memory and set per-process limits to prevent OOM conditions.
Rack is a modular Ruby web server interface. Prior to versions 2.2.20, 3.1.18, and 3.2.3, Rack::Request#POST reads the entire request body into memory for Content-Type: application/x-www-form-urlencoded, calling rack.input.read(nil) without enforcing a length or cap. Large request bodies can therefore be buffered completely into process memory before parsing, leading to denial of service (DoS) through memory exhaustion. Users should upgrade to Rack version 2.2.20, 3.1.18, or 3.2.3, anu of which enforces form parameter limits using queryparser.bytesizelimit, preventing unbounded reads of application/x-www-form-urlencoded bodies. Additionally, enforce strict maximum body size at the proxy or web server layer (e.g., Nginx clientmaxbodysize, Apache LimitRequestBody).
Rack is a modular Ruby web server interface. Prior to versions 2.2.22, 3.1.20, and 3.2.5, Rack::Directory’s path check used a string prefix match on the expanded path. A request like /../rootexample/ can escape the configured root if the target path starts with the root string, allowing directory listing outside the intended root. Versions 2.2.22, 3.1.20, and 3.2.5 fix the issue.
Rack is a modular Ruby web server interface. From versions 3.0.0.beta1 to before 3.1.21, and 3.2.0 to before 3.2.6, Rack::Multipart::Parser#handlemimehead 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. This issue has been patched in versions 3.1.21 and 3.2.6.
Rack is a modular Ruby web server interface. Prior to versions 2.2.23, 3.1.21, and 3.2.6, Rack::Multipart::Parser only wraps the request body in a BoundedIO when CONTENTLENGTH 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. This issue has been patched in versions 2.2.23, 3.1.21, and 3.2.6.
Rack is a modular Ruby web server interface. Prior to versions 2.2.23, 3.1.21, and 3.2.6, 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. This issue has been patched in versions 2.2.23, 3.1.21, and 3.2.6.
Summary
Rack::Sendfile can be exploited by crafting input that includes newline characters to manipulate log entries.
Details
The Rack::Sendfile middleware logs unsanitized header values from the X-Sendfile-Type header. An attacker can exploit this by injecting escape sequences (such as newline characters) into the header, resulting in log injection.
Impact
This vulnerability can distort log files, obscure attack traces, and complicate security auditing.
Mitigation
- Update to the latest version of Rack, or - Remove usage of Rack::Sendfile.
Summary There is a denial of service vulnerability in the Content-Disposition parsing component of Rack. This is very similar to the previous security issue CVE-2022-44571.
Details
Carefully crafted input can cause Content-Disposition header parsing in Rack to take an unexpected amount of time, possibly resulting in a denial of service attack vector. This header is used typically used in multipart parsing. Any applications that parse multipart posts using Rack (virtually all Rails applications) are impacted.
Credits
Thanks to scyoon for reporting this to the Rails security team