CVE-2026-33174 Overview
A memory exhaustion vulnerability exists in Ruby on Rails Active Storage that allows remote attackers to trigger a Denial of Service (DoS) condition. Active Storage allows users to attach cloud and local files in Rails applications. When serving files through Active Storage's proxy delivery mode, the proxy controller loads the entire requested byte range into memory before sending it. A request with a large or unbounded Range header (e.g., bytes=0-) could cause the server to allocate memory proportional to the file size, potentially exhausting available memory and crashing the application.
Critical Impact
Remote attackers can exhaust server memory by sending specially crafted HTTP Range requests to Active Storage endpoints, causing application-wide denial of service without authentication.
Affected Products
- Ruby on Rails versions prior to 8.1.2.1
- Ruby on Rails versions prior to 8.0.4.1
- Ruby on Rails versions prior to 7.2.3.1
Discovery Timeline
- 2026-03-24 - CVE CVE-2026-33174 published to NVD
- 2026-03-24 - Last updated in NVD database
Technical Details for CVE-2026-33174
Vulnerability Analysis
This vulnerability (CWE-789: Memory Allocation with Excessive Size Value) occurs in the Active Storage streaming module when handling HTTP Range requests. The send_blob_byte_range_data function in activestorage/app/controllers/concerns/active_storage/streaming.rb processes byte range requests without properly validating the size of the requested range.
When a client sends a Range header such as bytes=0- (requesting all bytes from the beginning), the proxy controller attempts to load the entire file into memory before streaming it to the client. For large files, this behavior can rapidly consume available server memory, leading to application instability or complete service outage.
The vulnerability is exploitable over the network without requiring authentication, making it particularly dangerous for publicly accessible Rails applications using Active Storage's proxy delivery mode.
Root Cause
The root cause lies in the inadequate validation of byte ranges in the send_blob_byte_range_data function. Prior to the patch, the function only checked if ranges were blank using ranges.blank? || ranges.all?(&:blank?), but did not validate whether the requested range size was within acceptable memory limits. This allowed attackers to request arbitrarily large byte ranges that would be fully loaded into memory.
Attack Vector
An attacker can exploit this vulnerability by sending HTTP requests with crafted Range headers to Active Storage proxy endpoints. The attack requires no authentication and can be performed remotely over the network. By requesting large or unbounded byte ranges for files stored through Active Storage, an attacker can force the server to allocate excessive memory, potentially exhausting system resources and causing a denial of service condition affecting all users of the application.
# Security patch in activestorage/app/controllers/concerns/active_storage/streaming.rb
# Source: https://github.com/rails/rails/commit/2cd933c366b777f873d4d590127da2f4a25e4ba5
def send_blob_byte_range_data(blob, range_header, disposition: nil)
ranges = Rack::Utils.get_byte_ranges(range_header, blob.byte_size)
- return head(:range_not_satisfiable) if ranges.blank? || ranges.all?(&:blank?)
+ return head(:range_not_satisfiable) unless ranges_valid?(ranges)
if ranges.length == 1
range = ranges.first
Detection Methods for CVE-2026-33174
Indicators of Compromise
- Unusual memory consumption spikes on Rails application servers
- High volume of HTTP requests with large or unbounded Range headers targeting Active Storage endpoints
- Application crashes or out-of-memory errors in Rails server logs
- Abnormal request patterns to /rails/active_storage/blobs/ or proxy delivery endpoints
Detection Strategies
- Monitor HTTP access logs for requests containing suspicious Range headers like bytes=0- or extremely large byte range values
- Implement application performance monitoring (APM) to detect sudden memory allocation anomalies
- Configure web application firewall (WAF) rules to flag or block requests with unbounded Range headers
- Set up alerts for memory threshold breaches on Rails application servers
Monitoring Recommendations
- Enable detailed logging for Active Storage proxy controller requests
- Implement real-time memory usage monitoring with alerting thresholds
- Track request patterns to Active Storage endpoints for anomaly detection
- Monitor application restart frequency as an indicator of memory exhaustion crashes
How to Mitigate CVE-2026-33174
Immediate Actions Required
- Upgrade Ruby on Rails to patched versions: 8.1.2.1, 8.0.4.1, or 7.2.3.1
- Review application logs for any signs of exploitation attempts
- Consider temporarily disabling Active Storage proxy delivery mode if immediate patching is not possible
- Implement Rate limiting on Active Storage endpoints to reduce DoS impact
Patch Information
Ruby on Rails has released security patches across all supported versions. Organizations should update to the following versions:
- Rails v8.1.2.1 for Rails 8.1.x users
- Rails v8.0.4.1 for Rails 8.0.x users
- Rails v7.2.3.1 for Rails 7.2.x users
The patch introduces a new ranges_valid? method that validates byte ranges before processing, and adds configurable maximum streaming chunk size functionality. For complete details, refer to the GitHub Security Advisory GHSA-r46p-8f7g-vvvg.
Workarounds
- Configure a reverse proxy (nginx, Apache) to validate and limit Range header values before requests reach the Rails application
- Switch from proxy delivery mode to direct delivery or redirect delivery modes for Active Storage if proxy mode is not strictly required
- Implement application-level middleware to reject requests with unbounded or excessively large Range headers
- Set memory limits on application containers to prevent complete host memory exhaustion
# Nginx configuration to limit Range header abuse
# Add to nginx server block for Rails application
# Limit the size of Range header requests
map $http_range $range_block {
default 0;
"~^bytes=0-$" 1;
"~^bytes=\d+-$" 1;
}
server {
# Block unbounded range requests to Active Storage
location /rails/active_storage/ {
if ($range_block = 1) {
return 416;
}
proxy_pass http://rails_app;
}
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


