2.5 KiB
Sinatra — CWE-407 Disclosure Brief
2026-03-27 · Patch available — awaiting upstream merge
Finding
Two O(n²) defects in Sinatra's request processing pipeline. Both use list/array scans on per-request hot paths — one for charset detection, one for content-type matching in provides(). Patches ready for upstream review.
The Defects
sinatra-0001 (PATCHED — HIGH): sinatra/base.rb:1002
# add_charset: array
# Per content_type() response call:
add_charset.all? { |p| !(p === mime_type) } # O(K) scan per response
add_charset is an array. The all? block performs an O(K) scan over K charset patterns on every content_type() call. For R requests and K charset entries: O(R × K) total.
sinatra-0002 (PATCHED — MEDIUM): sinatra/base.rb:1770
# types: array
# Per request in provides() condition:
types.include?(response_content_type) # O(T) scan per request
types is an array. O(T) scan per request in the provides() route condition. For R requests and T types: O(R × T) total.
Complexity Proof
sinatra-0001: For K=8 charset entries per request:
- Each
content_type()call: O(K) scan - Fixed: freeze a
Setat load time, O(1) per call - Measured ratio: 8×.
sinatra-0002: For T=34 content types:
- Per request: O(T) vs O(1) set lookup
- Measured ratio: 34×.
Impact
sinatra-0001 affects every Sinatra application that sets content types — virtually all applications. The charset check runs on every response.
sinatra-0002 affects every route using provides() content negotiation, which is a core Sinatra routing feature for REST APIs. Both defects scale linearly with request rate, making them amplified under load.
The Fix
sinatra-0001: Freeze add_charset as a Set:
# Before
add_charset.all? { |p| !(p === mime_type) }
# After
# CWE-407 fix: freeze Set at load time for O(1) member? instead of O(K) array scan.
ADD_CHARSET_SET = Set.new(add_charset).freeze
!ADD_CHARSET_SET.any? { |p| p === mime_type }
sinatra-0002: Convert types to a Set before the provides() check.
Patch
defects/sinatra/patch/sinatra-0001-0002-set-charset-types.patch
What We Ask
- Confirm receipt and assign a GitHub Security Advisory or issue reference.
- Validate the patch against your request handling test suite.
- Assess CVE eligibility — both defects fire on every request.
- Coordinate a disclosure date — we are targeting 90 days from first contact.
Contact: see cover email. This brief is confidential until coordinated disclosure.