CVE-2025-61770
High · 7.5Rack's unbounded multipart preamble buffering enables DoS (memory exhaustion)
CVSS
7.5
EPSS
0.9%
Published
Oct 7, 2025
CISA due date
—
Cloudanix analysis
Attackers can send specially oversized form-upload requests that may cause affected web applications to run out of memory and become unavailable.
- Exploitation
- Remote Unauthenticated
- Attacker needs
- None
- Complexity
- Low
- Impact
- Denial Of Service
- Component
- Library
- Class
- Denial of service
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
Rack's multipart parser buffers all bytes that appear before the first multipart boundary, known as the multipart preamble, into process memory without enforcing a size limit. An unauthenticated client can send an HTTP request with Content-Type: multipart/form-data, include a very large preamble, and then eventually provide a valid boundary so the request remains syntactically acceptable. Because the preamble is accumulated in memory, each malicious request can drive excessive heap growth in the Ruby/Rack application process, causing garbage-collection pressure, latency spikes, worker crashes, or operating-system out-of-memory termination. The impact is denial of service rather than code execution or data compromise.
Why it matters to the business
Public-facing applications that accept multipart form uploads through affected Rack code can be made slow or unavailable with comparatively simple HTTP traffic. The likely consequences are service disruption, failed uploads or form submissions, elevated infrastructure costs from memory exhaustion and autoscaling, increased error rates, and possible cascading outages if application workers are repeatedly killed and restarted. The issue is not listed in CISA KEV, is not known to be used in ransomware campaigns, and has low EPSS, but it has been public for a long period, so internet-facing services should still be patched as part of normal vulnerability management.
How an attack unfolds
An attacker identifies a Ruby/Rack-backed endpoint that accepts multipart/form-data, such as a file upload or form submission path. The attacker opens one or more HTTP connections and sends a multipart request whose body starts with a very large preamble before the first declared boundary. Vulnerable Rack::Multipart::Parser behavior stores that preamble in memory while waiting for the boundary. Once the boundary is sent, the request can continue to be parsed, but by then the worker may have consumed substantial memory. Repeating this across concurrent requests or connections can exhaust available memory, trigger Ruby NoMemoryError conditions, cause application server workers to be killed by the operating system or container runtime, and make the application unavailable to legitimate users.
How to fix it
Upgrade Rack to a release or source revision that includes the fix for Rack::Multipart::Parser preamble size handling. For rack/rack from Git, ensure the deployed code includes commit 4c4ea296fdfd115377912aa7dbcb55b83bf2888e or a later trusted version containing that change. Rebuild and redeploy all applications that vendor, bundle, or indirectly depend on affected Rack code. As compensating controls, enforce maximum request body sizes at the reverse proxy, load balancer, CDN, web server, and application server; set strict upload size limits; reduce request read timeouts; limit concurrent requests per client; and ensure containers or services have memory limits plus healthy restart policies. Do not rely only on application-level validation, because the vulnerable buffering occurs during multipart parsing before application handlers may run.
How to confirm the fix worked
Confirm the deployed Rack dependency or vendored source includes commit 4c4ea296fdfd115377912aa7dbcb55b83bf2888e or a release that incorporates it. Review lockfiles, dependency manifests, container images, and runtime package inventories to ensure no vulnerable Rack copy remains. Exercise upload and multipart endpoints in a staging environment with oversized multipart preambles and verify the request is rejected, bounded, or handled without unbounded memory growth. Confirm reverse proxies and application servers enforce request size limits before traffic reaches Rack. Monitor memory usage, worker restarts, HTTP 5xx rates, and request rejection logs during validation to ensure controls are effective and do not break legitimate uploads.
Typical attack path
- Discover an application endpoint that accepts multipart/form-data requests.
- Send an HTTP request with a valid multipart Content-Type header and boundary value.
- Place an unusually large amount of data before the first multipart boundary in the request body.
- Optionally complete the request with the expected boundary so parsing proceeds far enough to trigger the vulnerable buffering behavior.
- Repeat the request or run multiple concurrent requests to increase memory pressure.
- Cause application workers, containers, or hosts to slow down, restart, or terminate from out-of-memory conditions.
How to detect it
Look for evidence of denial-of-service activity rather than data theft. Useful sources include reverse proxy and load balancer access logs, web application firewall logs, application server logs, Ruby/Rack exception logs, container runtime events, kernel or host OOM logs, APM traces, and infrastructure metrics. Focus on multipart/form-data requests with unusually large request bodies, long request durations, incomplete uploads, repeated requests from the same source, spikes in HTTP 499/500/502/503/504 responses, and time-correlated increases in application memory usage. On containerized platforms, search for OOMKilled events or restarts of Ruby application containers around bursts of multipart traffic. In host logs, search for operating-system out-of-memory messages that reference Ruby, Puma, Unicorn, Passenger, or other Rack-hosting processes. Because exploitation may leave no unique payload marker after the request body is discarded, correlation between large multipart requests and memory exhaustion is the strongest indicator.
- Content-Type: multipart/form-data; boundary=
- Rack::Multipart::Parser
- NoMemoryError
- failed to allocate memory
- Cannot allocate memory
- Out of memory
- out of memory: Kill process
- Killed process
- OOMKilled
- SIGKILL
- worker timeout
- PumaWorkerKiller
- puma: cluster worker
- unicorn worker
- passenger-status
- HTTP 503
- HTTP 502
- HTTP 504
What your security team should do
- Prioritize patching internet-facing Ruby/Rack applications that accept file uploads or multipart forms.
- Update Rack to a fixed release or ensure source deployments include commit 4c4ea296fdfd115377912aa7dbcb55b83bf2888e or later.
- Inventory transitive Rack usage across Ruby applications, containers, and vendored dependencies; do not assume only directly declared Rack packages are affected.
- Enforce maximum request body size and upload size limits at the edge before requests reach the Rack application.
- Add rate limiting and connection concurrency controls for multipart/form-data endpoints, especially unauthenticated paths.
- Tune container, process manager, and application server memory limits so individual worker failures do not destabilize the full service.
- Review historical logs and runtime telemetry for unexplained memory spikes, OOM kills, worker restarts, and large multipart requests.
- Create SIEM or observability alerts for multipart requests with unusually large request bodies, high request duration, client disconnects, and correlated application memory growth.
The record
`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.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|---|---|---|
| RubyGems | rack | 0 | 2.2.19 |
| RubyGems | rack | 3.1 | 3.1.17 |
| RubyGems | rack | 3.2 | 3.2.2 |
| AlmaLinux:10 | cockpit-ha-cluster | 0 | 0.12.1-1.el10_1.1 |
| AlmaLinux:10 | pcs | 0 | 0.12.1-1.el10_1.1 |
| AlmaLinux:10 | pcs-snmp | 0 | 0.12.1-1.el10_1.1 |
| AlmaLinux:8 | pcs | 0 | 0.10.18-2.el8_10.7.alma.1 |
| AlmaLinux:8 | pcs-snmp | 0 | 0.10.18-2.el8_10.7.alma.1 |
| AlmaLinux:9 | pcs | 0 | 0.11.10-1.el9_7.1 |
| AlmaLinux:9 | pcs-snmp | 0 | 0.11.10-1.el9_7.1 |
| Chainguard | gitaly-config-18.2 | 0 | 18.2.8-r0 |
| Chainguard | gitaly-config-18.3 | 0 | 18.3.4-r0 |
| Chainguard | gitaly-config-18.4 | 0 | 18.4.2-r0 |
| Chainguard | gitlab-base-18.2 | 0 | 18.2.8-r0 |
| Chainguard | gitlab-base-18.3 | 0 | 18.3.4-r0 |
| Chainguard | gitlab-base-18.4 | 0 | 18.4.2-r0 |
| Chainguard | gitlab-certificates-18.2 | 0 | 18.2.8-r0 |
| Chainguard | gitlab-certificates-18.3 | 0 | 18.3.4-r0 |
| Chainguard | gitlab-certificates-18.4 | 0 | 18.4.2-r0 |
| Chainguard | gitlab-cfssl-self-sign-scripts-18.2 | 0 | 18.2.8-r0 |
| Chainguard | gitlab-cfssl-self-sign-scripts-18.3 | 0 | 18.3.4-r0 |
| Chainguard | gitlab-cfssl-self-sign-scripts-18.4 | 0 | 18.4.2-r0 |
| Chainguard | gitlab-cng-18.2 | 0 | 18.2.8-r0 |
| Chainguard | gitlab-cng-18.3 | 0 | 18.3.4-r0 |
| Chainguard | gitlab-cng-18.4 | 0 | 18.4.2-r0 |
| Chainguard | gitlab-container-registry-18.2 | 0 | 18.2.8-r0 |
| Chainguard | gitlab-container-registry-18.3 | 0 | 18.3.4-r0 |
| Chainguard | gitlab-container-registry-18.4 | 0 | 18.4.2-r0 |
| Chainguard | gitlab-container-registry-scripts-18.2 | 0 | 18.2.8-r0 |
| Chainguard | gitlab-container-registry-scripts-18.3 | 0 | 18.3.4-r0 |
| Chainguard | gitlab-container-registry-scripts-18.4 | 0 | 18.4.2-r0 |
| Chainguard | gitlab-exporter-18.2 | 0 | 18.2.8-r0 |
| Chainguard | gitlab-exporter-18.3 | 0 | 18.3.4-r0 |
| Chainguard | gitlab-exporter-18.4 | 0 | 18.4.2-r0 |
| Chainguard | gitlab-exporter-scripts-18.2 | 0 | 18.2.8-r0 |
| Chainguard | gitlab-exporter-scripts-18.3 | 0 | 18.3.4-r0 |
| Chainguard | gitlab-exporter-scripts-18.4 | 0 | 18.4.2-r0 |
| Chainguard | gitlab-gitaly-scripts-18.2 | 0 | 18.2.8-r0 |
| Chainguard | gitlab-gitaly-scripts-18.3 | 0 | 18.3.4-r0 |
| Chainguard | gitlab-gitaly-scripts-18.4 | 0 | 18.4.2-r0 |
| Chainguard | gitlab-logger-18.2 | 0 | 18.2.8-r0 |
| Chainguard | gitlab-logger-18.3 | 0 | 18.3.4-r0 |
| Chainguard | gitlab-logger-18.4 | 0 | 18.4.2-r0 |
| Chainguard | gitlab-logger-compat-18.2 | 0 | 18.2.8-r0 |
| Chainguard | gitlab-logger-compat-18.3 | 0 | 18.3.4-r0 |
| Chainguard | gitlab-pages-scripts-18.2 | 0 | 18.2.8-r0 |
| Chainguard | gitlab-pages-scripts-18.3 | 0 | 18.3.4-r0 |
| Chainguard | gitlab-pages-scripts-18.4 | 0 | 18.4.2-r0 |
| Chainguard | gitlab-rails-ce-18.1 | 0 | 18.1.6-r3 |
| Chainguard | gitlab-rails-ce-18.2 | 0 | 18.2.8-r3 |
| Chainguard | gitlab-rails-ce-18.3 | 0 | 18.3.6-r0 |
| Chainguard | gitlab-rails-ce-18.4 | 0 | 18.4.4-r0 |
| Chainguard | gitlab-rails-ce-18.5 | 0 | 18.5.2-r0 |
| Chainguard | gitlab-rails-ce-assets-18.1 | 0 | 18.1.6-r1 |
| Chainguard | gitlab-rails-ce-assets-18.2 | 0 | 18.2.8-r1 |
| Chainguard | gitlab-rails-ce-assets-18.3 | 0 | 18.3.5-r0 |
| Chainguard | gitlab-rails-ce-assets-18.4 | 0 | 18.4.3-r0 |
| Chainguard | gitlab-rails-ce-assets-18.5 | 0 | 18.5.1-r0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.1 | 0 | 18.1.6-r2 |
| Chainguard | gitlab-rails-ce-assets-fips-18.2 | 0 | 18.2.8-r2 |
| Chainguard | gitlab-rails-ce-assets-fips-18.3 | 0 | 18.3.5-r2 |
| Chainguard | gitlab-rails-ce-assets-fips-18.4 | 0 | 18.4.3-r3 |
| Chainguard | gitlab-rails-ce-assets-fips-18.5 | 0 | 18.5.1-r2 |
| Chainguard | gitlab-rails-ce-doc-18.1 | 0 | 18.1.6-r1 |
| Chainguard | gitlab-rails-ce-doc-18.2 | 0 | 18.2.8-r1 |
| Chainguard | gitlab-rails-ce-doc-18.3 | 0 | 18.3.5-r0 |
| Chainguard | gitlab-rails-ce-doc-18.4 | 0 | 18.4.3-r0 |
| Chainguard | gitlab-rails-ce-doc-18.5 | 0 | 18.5.1-r0 |
| Chainguard | gitlab-rails-ce-doc-fips-18.1 | 0 | 18.1.6-r2 |
| Chainguard | gitlab-rails-ce-doc-fips-18.2 | 0 | 18.2.8-r2 |
| Chainguard | gitlab-rails-ce-doc-fips-18.3 | 0 | 18.3.5-r2 |
| Chainguard | gitlab-rails-ce-doc-fips-18.4 | 0 | 18.4.3-r3 |
| Chainguard | gitlab-rails-ce-doc-fips-18.5 | 0 | 18.5.1-r2 |
| Chainguard | gitlab-rails-ce-fips-18.1 | 0 | 18.1.6-r4 |
| Chainguard | gitlab-rails-ce-fips-18.2 | 0 | 18.2.8-r4 |
| Chainguard | gitlab-rails-ce-fips-18.3 | 0 | 18.3.6-r0 |
| Chainguard | gitlab-rails-ce-fips-18.4 | 0 | 18.4.4-r0 |
| Chainguard | gitlab-rails-ce-fips-18.5 | 0 | 18.5.2-r0 |
| Chainguard | gitlab-rails-scripts-18.2 | 0 | 18.2.8-r0 |
| Chainguard | gitlab-rails-scripts-18.3 | 0 | 18.3.4-r0 |
| Chainguard | gitlab-rails-scripts-18.4 | 0 | 18.4.2-r0 |
| Chainguard | gitlab-shell-18.2 | 0 | 18.2.8-r0 |
| Chainguard | gitlab-shell-18.3 | 0 | 18.3.4-r0 |
| Chainguard | gitlab-shell-18.4 | 0 | 18.4.2-r0 |
| Chainguard | gitlab-shell-scripts-18.2 | 0 | 18.2.8-r0 |
| Chainguard | gitlab-shell-scripts-18.3 | 0 | 18.3.4-r0 |
| Chainguard | gitlab-shell-scripts-18.4 | 0 | 18.4.2-r0 |
| Chainguard | gitlab-shell-scripts-compat-18.2 | 0 | 18.2.8-r0 |
| Chainguard | gitlab-shell-scripts-compat-18.3 | 0 | 18.3.4-r0 |
| Chainguard | gitlab-sidekiq-ce-18.2 | 0 | 18.2.8-r0 |
| Chainguard | gitlab-sidekiq-ce-18.3 | 0 | 18.3.4-r0 |
| Chainguard | gitlab-sidekiq-ce-18.4 | 0 | 18.4.2-r0 |
| Chainguard | gitlab-toolbox-ce-18.2 | 0 | 18.2.8-r0 |
| Chainguard | gitlab-toolbox-ce-18.3 | 0 | 18.3.4-r0 |
| Chainguard | gitlab-toolbox-ce-18.4 | 0 | 18.4.2-r0 |
| Chainguard | gitlab-webservice-ce-18.2 | 0 | 18.2.8-r0 |
| Chainguard | gitlab-webservice-ce-18.3 | 0 | 18.3.4-r0 |
| Chainguard | gitlab-webservice-ce-18.4 | 0 | 18.4.2-r0 |
| Chainguard | gitlab-workhorse-scripts-18.2 | 0 | 18.2.8-r0 |
| Chainguard | gitlab-workhorse-scripts-18.3 | 0 | 18.3.4-r0 |
| Chainguard | gitlab-workhorse-scripts-18.4 | 0 | 18.4.2-r0 |
| Chainguard | logstash-8.17 | 0 | 8.17.10-r3 |
| Chainguard | logstash-8.17-bitnami-compat | 0 | 8.17.10-r3 |
| Chainguard | logstash-8.17-compat | 0 | 8.17.10-r3 |
| Chainguard | logstash-8.17-env2yaml | 0 | 8.17.10-r3 |
| Chainguard | logstash-8.17-iamguarded-compat | 0 | 8.17.10-r3 |
| Chainguard | logstash-8.17-with-output-opensearch | 0 | 8.17.10-r3 |
| Chainguard | logstash-8.18 | 0 | 8.18.8-r1 |
| Chainguard | logstash-8.18-bitnami-compat | 0 | 8.18.8-r1 |
| Chainguard | logstash-8.18-compat | 0 | 8.18.8-r1 |
| Chainguard | logstash-8.18-env2yaml | 0 | 8.18.8-r1 |
| Chainguard | logstash-8.18-iamguarded-compat | 0 | 8.18.8-r1 |
| Chainguard | logstash-8.18-with-output-opensearch | 0 | 8.18.8-r1 |
| Chainguard | logstash-8.19 | 0 | 8.19.5-r1 |
| Chainguard | logstash-8.19-compat | 0 | 8.19.5-r1 |
| Chainguard | logstash-8.19-env2yaml | 0 | 8.19.5-r1 |
| Chainguard | logstash-8.19-iamguarded-compat | 0 | 8.19.5-r1 |
| Chainguard | logstash-8.19-with-output-opensearch | 0 | 8.19.5-r1 |
| Chainguard | logstash-9.0 | 0 | 9.0.8-r1 |
| Chainguard | logstash-9.0-bitnami-compat | 0 | 9.0.8-r1 |
| Chainguard | logstash-9.0-compat | 0 | 9.0.8-r1 |
| Chainguard | logstash-9.0-env2yaml | 0 | 9.0.8-r1 |
| Chainguard | logstash-9.0-iamguarded-compat | 0 | 9.0.8-r1 |
| Chainguard | logstash-9.0-with-output-opensearch | 0 | 9.0.8-r1 |
| Chainguard | logstash-9.1 | 0 | 9.1.5-r1 |
| Chainguard | logstash-9.1-bitnami-compat | 0 | 9.1.5-r1 |
| Chainguard | logstash-9.1-compat | 0 | 9.1.5-r1 |
| Chainguard | logstash-9.1-env2yaml | 0 | 9.1.5-r1 |
| Chainguard | logstash-9.1-iamguarded-compat | 0 | 9.1.5-r1 |
| Chainguard | logstash-9.1-with-output-opensearch | 0 | 9.1.5-r1 |
| Chainguard | ruby3.2-rails-7.1 | 0 | 7.1.6-r0 |
| Chainguard | ruby3.2-rails-7.1-compat | 0 | 7.1.6-r0 |
| Chainguard | ruby3.2-rails-7.2 | 0 | 7.2.2.2-r1 |
| Chainguard | ruby3.2-rails-7.2-compat | 0 | 7.2.2.2-r1 |
| Chainguard | ruby3.2-rails-8.0 | 0 | 8.0.3-r1 |
| Chainguard | ruby3.2-rails-8.0-compat | 0 | 8.0.3-r1 |
| Chainguard | ruby3.3-rack-2.2 | 0 | 2.2.22-r0 |
| Chainguard | ruby3.3-rails-7.1 | 0 | 7.1.6-r0 |
| Chainguard | ruby3.3-rails-7.1-compat | 0 | 7.1.6-r0 |
| Chainguard | ruby3.3-rails-7.2 | 0 | 7.2.2.2-r1 |
| Chainguard | ruby3.3-rails-7.2-compat | 0 | 7.2.2.2-r1 |
| Chainguard | ruby3.3-rails-8.0 | 0 | 8.0.3-r1 |
| Chainguard | ruby3.3-rails-8.0-compat | 0 | 8.0.3-r1 |
| Chainguard | ruby3.4-rails-7.1 | 0 | 7.1.6-r0 |
| Chainguard | ruby3.4-rails-7.1-compat | 0 | 7.1.6-r0 |
| Chainguard | ruby3.4-rails-7.2 | 0 | 7.2.2.2-r1 |
| Chainguard | ruby3.4-rails-7.2-compat | 0 | 7.2.2.2-r1 |
| Chainguard | ruby3.4-rails-8.0 | 0 | 8.0.3-r1 |
| Chainguard | ruby3.4-rails-8.0-compat | 0 | 8.0.3-r1 |
| Mageia:9 | ruby-rack | 0 | 2.2.21-1.mga9 |
| Wolfi | gitaly-config-18.2 | 0 | 18.2.8-r0 |
| Wolfi | gitlab-base-18.2 | 0 | 18.2.8-r0 |
| Wolfi | gitlab-certificates-18.2 | 0 | 18.2.8-r0 |
| Wolfi | gitlab-cfssl-self-sign-scripts-18.2 | 0 | 18.2.8-r0 |
| Wolfi | gitlab-cng-18.2 | 0 | 18.2.8-r0 |
| Wolfi | gitlab-container-registry-18.2 | 0 | 18.2.8-r0 |
| Wolfi | gitlab-container-registry-scripts-18.2 | 0 | 18.2.8-r0 |
| Wolfi | gitlab-exporter-18.2 | 0 | 18.2.8-r0 |
| Wolfi | gitlab-exporter-scripts-18.2 | 0 | 18.2.8-r0 |
| Wolfi | gitlab-gitaly-scripts-18.2 | 0 | 18.2.8-r0 |
| Wolfi | gitlab-logger-18.2 | 0 | 18.2.8-r0 |
| Wolfi | gitlab-logger-compat-18.2 | 0 | 18.2.8-r0 |
| Wolfi | gitlab-pages-scripts-18.2 | 0 | 18.2.8-r0 |
| Wolfi | gitlab-shell-18.2 | 0 | 18.2.8-r0 |
| Wolfi | gitlab-shell-scripts-18.2 | 0 | 18.2.8-r0 |
| Wolfi | gitlab-shell-scripts-compat-18.2 | 0 | 18.2.8-r0 |
| Wolfi | logstash-9.1 | 0 | 9.1.5-r1 |
| Wolfi | logstash-9.1-bitnami-compat | 0 | 9.1.5-r1 |
| Wolfi | logstash-9.1-compat | 0 | 9.1.5-r1 |
| Wolfi | logstash-9.1-env2yaml | 0 | 9.1.5-r1 |
| Wolfi | logstash-9.1-iamguarded-compat | 0 | 9.1.5-r1 |
| Wolfi | logstash-9.1-with-output-opensearch | 0 | 9.1.5-r1 |
| Wolfi | ruby3.2-rails-8.0 | 0 | 8.0.3-r1 |
| Wolfi | ruby3.2-rails-8.0-compat | 0 | 8.0.3-r1 |
| Wolfi | ruby3.3-rack-2.2 | 0 | 2.2.22-r0 |
| Wolfi | ruby3.3-rails-8.0 | 0 | 8.0.3-r1 |
| Wolfi | ruby3.3-rails-8.0-compat | 0 | 8.0.3-r1 |
| Wolfi | ruby3.4-rails-8.0 | 0 | 8.0.3-r1 |
| Wolfi | ruby3.4-rails-8.0-compat | 0 | 8.0.3-r1 |
| gem | rack | 3.1 | 3.1.17 |
| gem | rack | 3.2 | 3.2.2 |
| openSUSE:Tumbleweed | rubygem-rack-2.2 | 0 | 2.2.19-1.1 |
| openSUSE:Tumbleweed | rubygem-rack-2.2 | 0 | 2.2.22-1.1 |
Related vulnerabilities
- CVE-2026-25500 Rack is a modular Ruby web server interface. Also affects rack
- CVE-2026-22860 Rack is a modular Ruby web server interface. Also affects rack
- CVE-2025-61919 Rack is vulnerable to a memory-exhaustion DoS through unbounded URL-encoded body parsing Also affects rack
- CVE-2025-61780 Rack has a Possible Information Disclosure Vulnerability Also affects rack
- CVE-2025-61771 Rack: Multipart parser buffers large non‑file fields entirely in memory, enabling DoS… Also affects rack
- CVE-2025-61772 Rack's multipart parser buffers unbounded per-part headers, enabling DoS (memory… Also affects rack
- CVE-2025-59830 Rack has an unsafe default in Rack::QueryParser allows params_limit bypass via… Also affects rack
- CVE-2025-46336 Rack::Session is a session management implementation for Rack. Also affects rack