Overview
Unrestricted Resource Consumption vulnerabilities occur when an application processes user input or data without bounding the amount of work, memory, or I/O it can use. In Ruby on Rails apps, this often shows up as loading entire datasets into memory (for example, using Model.all or to_a on large tables), rendering massive JSON or CSV responses, or performing heavy file operations within a single request. Attackers can exploit these patterns to exhaust CPU and memory, degrade service performance, or crash processes, especially under peak load or multi-tenant environments.
In Rails, common manifestations include rendering a full ActiveRecord relation as JSON (render json: Model.all), iterating over large collections with to_a, or streaming/processing large files without enforcing size or processing limits. Unbounded processing can also arise from poorly constrained background tasks that still execute within the request cycle, or from unbounded iteration over user-supplied inputs. These scenarios increase memory pressure and can trigger database connection exhaustion.
Remediation emphasizes bounding resource use by design. Prefer pagination, limit the scope of queries, and batch-process large datasets (find_in_batches/find_each) instead of loading everything. For large responses, stream data or implement server-side pagination rather than rendering an entire collection at once. Offload heavy work to background jobs, add request timeouts and memory caps, and monitor resource usage to detect anomalies. Keep Rails and dependencies up to date with security patches and apply configuration hardening (max upload size, rate limits, and appropriate caching).
Code Fix Example
Ruby on Rails API Security Remediation
VULNERABLE:
# app/controllers/users_controller.rb
class UsersController < ApplicationController
def index
# Unrestricted resource consumption: loads all users into memory
render json: User.all
end
end
FIX:
# app/controllers/users_controller.rb
class UsersController < ApplicationController
include ActionController::Live
def index
response.headers['Content-Type'] = 'application/json'
begin
first = true
response.stream.write '['
User.find_in_batches(batch_size: 1000) do |batch|
batch.each do |u|
response.stream.write ',' unless first
first = false
response.stream.write({ id: u.id, email: u.email }.to_json)
end
end
response.stream.write ']'
ensure
response.stream.close
end
end
end