# 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`

```ruby
# 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`

```ruby
# 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 `Set` at 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`:

```ruby
# 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

1. Confirm receipt and assign a GitHub Security Advisory or issue reference.
2. Validate the patch against your request handling test suite.
3. Assess CVE eligibility — both defects fire on every request.
4. Coordinate a disclosure date — we are targeting 90 days from first contact.

Contact: see cover email. This brief is confidential until coordinated disclosure.
