Cloudanix VulnDB

CVE-2025-61771

High · 7.5

Rack: Multipart parser buffers large non‑file fields entirely in memory, enabling DoS (memory exhaustion)

CVSS

7.5

EPSS

0.6%

Published

Oct 7, 2025

CISA due date

—

Cloudanix analysis

Next patch cycle SSVC: Track

A specially oversized web form submission can make affected Ruby web services run out of memory and stop responding.

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::Multipart::Parser keeps multipart/form-data parts that do not include a filename parameter fully in process memory as Ruby String objects. An unauthenticated remote client can send a multipart request containing a very large ordinary text field, causing the Rack-based application process to allocate memory roughly proportional to the field size. If request-size controls are absent or too permissive, one or more such requests can exhaust worker memory, trigger Ruby NoMemoryError conditions or operating-system OOM kills, and make the application unavailable. The flaw affects rack/rack from source builds or downstream packages that include the vulnerable parser behavior; the upstream Git fix is commit 4c4ea296fdfd115377912aa7dbcb55b83bf2888e.

Why it matters to the business

Successful exploitation can cause customer-facing Ruby web applications, APIs, or internal Rack-based services to slow down, restart repeatedly, or become unavailable, creating operational disruption without requiring account access. Although EPSS is currently low and the issue is not in CISA KEV, the CVSS 7.5 availability impact means internet-exposed upload or form endpoints should be prioritized, especially where Rack is widely embedded through Ruby frameworks and middleware stacks.

How an attack unfolds

An attacker first identifies a Rack-backed endpoint that accepts POST requests with multipart/form-data, such as upload, form submission, import, support, or profile endpoints. Instead of uploading a file part with a filename, the attacker submits a multipart body containing one or more very large non-file fields. The vulnerable parser treats those fields as normal form parameters and stores their entire contents in Ruby heap memory. As the request body is parsed, application worker memory rises sharply. If the request is large enough, or if several requests are sent concurrently, the Ruby process may raise memory allocation errors, the container or host may OOM-kill workers, upstream proxies may return 500/502/503/504 responses, and the service may degrade or go offline until workers are restarted and traffic is controlled.

How to fix it

Upgrade Rack to a version or source revision that includes the upstream fix for Rack::Multipart::Parser, specifically rack/rack commit 4c4ea296fdfd115377912aa7dbcb55b83bf2888e or a released package version that contains that commit. Rebuild and redeploy applications that vendor Rack or pin it through Gemfile.lock, package locks, containers, base images, or framework dependencies. In parallel, enforce defense-in-depth request limits at the earliest layer possible: CDN/WAF/load balancer maximum body size, reverse proxy client body limits, application server limits, Rack middleware limits, multipart part count limits, per-field size limits, and sane upload limits per endpoint. Return 413 Payload Too Large for oversized requests before they reach Rack parsing. For containerized deployments, set memory limits and autoscaling/restart policies, but do not rely on restarts as the primary mitigation.

How to confirm the fix worked

Confirm dependency resolution shows Rack built from, or upgraded to, a release containing commit 4c4ea296fdfd115377912aa7dbcb55b83bf2888e. Review Gemfile.lock, package manifests, vendored source, container image SBOMs, and framework transitive dependencies for vulnerable Rack copies. Validate edge and application limits by sending a controlled multipart/form-data request with an oversized non-file text field in a staging environment and confirming it is rejected with 413 or equivalent before application memory grows materially. Monitor process RSS/heap during the test and confirm no worker crash, NoMemoryError, OOM kill, or 5xx spike occurs. Verify production proxy, WAF, and application server configurations are actually enforcing the intended maximum request body and multipart field sizes.

Typical attack path

  1. Discover a Rack-based web application or API endpoint that accepts multipart/form-data requests.
  2. Send a crafted multipart/form-data POST request containing a very large text field without a filename attribute.
  3. Cause Rack::Multipart::Parser to allocate the full field contents as an in-memory Ruby String.
  4. Repeat or parallelize requests to drive worker, container, or host memory consumption upward.
  5. Trigger NoMemoryError, worker crashes, OOM kills, restarts, elevated latency, or upstream 5xx errors.
  6. Maintain denial of service by continuing to submit oversized multipart requests until request limits or patches are applied.

How to detect it

To determine whether this was already exploited, correlate web access logs, reverse-proxy logs, WAF/CDN logs, application logs, container runtime events, and host kernel logs. Look for large POST requests with Content-Type multipart/form-data, especially requests to form or upload endpoints that returned 500, 502, 503, 504, connection reset, timeout, or no response. Pay attention to requests with very large request_body_bytes, request_length, bytes_received, or upstream_request_time values, and repeated requests from the same source IP, ASN, user agent, or session shortly before worker crashes or memory spikes. In Ruby and application logs, search for Rack::Multipart::Parser exceptions, NoMemoryError, failed memory allocation, worker timeout, and process restart messages. In Linux, container, Kubernetes, and orchestration logs, search for OOMKilled, oom-kill, Killed process, exit code 137, and sudden restarts of Ruby, Puma, Unicorn, Passenger, Thin, or other Rack application workers. Absence of a unique exploit payload means detection should focus on the behavioral chain: oversized multipart request followed by rapid memory growth, process termination, and service errors.

  • Content-Type: multipart/form-data
  • Rack::Multipart::Parser
  • NoMemoryError
  • failed to allocate memory
  • Out of memory
  • oom-kill
  • OOMKilled
  • Killed process
  • exit code 137
  • signal SIGKILL
  • HTTP/1.1" 413
  • HTTP/1.1" 500
  • HTTP/1.1" 502
  • HTTP/1.1" 503
  • HTTP/1.1" 504
  • client intended to send too large body
  • request entity too large
  • Payload Too Large
  • multipart/form-data; boundary=
  • puma: cluster worker
  • unicorn worker
  • Passenger AppPreloader

What your security team should do

  • Inventory internet-exposed and business-critical Ruby/Rack applications, including applications that receive Rack transitively through Rails, Sinatra, Hanami, Grape, or custom Rack middleware stacks.
  • Patch Rack to a fixed release or source revision containing commit 4c4ea296fdfd115377912aa7dbcb55b83bf2888e, and rebuild all affected containers or deployment artifacts.
  • Immediately enforce maximum request body size and multipart field size controls at CDN, WAF, load balancer, reverse proxy, and application layers.
  • Prioritize endpoints that accept uploads, imports, web forms, large POST bodies, or unauthenticated multipart/form-data traffic.
  • Add monitoring and alerts for large multipart POST requests, sudden Ruby worker memory growth, OOM kills, NoMemoryError events, and correlated 5xx/latency spikes.
  • Create temporary WAF or reverse-proxy rules to reject multipart/form-data requests above approved endpoint-specific sizes until all affected applications are patched.
  • Review historical logs around availability incidents for unusually large multipart/form-data POST requests and repeated client sources causing memory pressure.
  • Document expected maximum upload and form sizes per application so future changes can be validated against abuse-resistant limits.

The record

`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).

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