Skip to content

Double-check: case-insensitive rate-limit header parsing #3882

Description

@philipphofmann

Why you're getting this issue

This is a double-check request, not a confirmed bug report — feel free to close it if it doesn't apply here.

We hit a bug in the Sentry Cocoa SDK that caused an incident: the SDK read the rate-limit HTTP response headers X-Sentry-Rate-Limits and Retry-After case-sensitively. Because HTTP/2 (RFC 9113 §8.2.1) and HTTP/3 (RFC 9114 §4.2) send header field names lowercased on the wire, the lookup missed the header and the SDK fell back to rate-limiting all data categories — silently over-dropping telemetry when only one category was actually rate-limited.

As part of that action item we audited every SDK for the same pattern (using Claude Code, see below). This SDK was flagged as potentially affected. Please double-check the finding below.

What the audit flagged

The transport reads the two headers with case-sensitive, mixed-case map keys:

package:http exposes Response.headers as a plain Map<String, String> whose keys are always lowercase, so these mixed-case lookups appear to return null. On a 429 that leads to an all-category rate limit:

Suspected behaviour to verify: under the web BrowserClient the lookup would miss on every response; under the native dart:io client (HTTP/1.1) it works today only because Relay sends canonical casing; any HTTP/2 client would miss. The existing transport tests build http.Response with mixed-case keys, so they wouldn't catch this.

If confirmed

Read the headers with lowercase keys (or a case-insensitive lookup) and add a test feeding a lowercased x-sentry-rate-limits:

final retryAfterHeader = response.headers['retry-after'];
final sentryRateLimitHeader = response.headers['x-sentry-rate-limits'];

This issue was generated with Claude Code while auditing all SDKs for incident INC-2357. It is a flag to be verified, not a confirmed defect. Cited lines were checked against source at commit c239c957.

How to double-check this yourself with Claude Code

This is the audit we ran. It checks whether an SDK reads X-Sentry-Rate-Limits / Retry-After case-insensitively.

1. Clone the repo and open Claude Code in it:

git clone --depth 1 https://github.com/getsentry/sentry-dart
cd sentry-dart
claude

2. Give Claude Code this prompt:

Audit how this SDK reads the HTTP response headers X-Sentry-Rate-Limits and Retry-After (these two only). The bug we are hunting: HTTP/2 (RFC 9113 §8.2.1) and HTTP/3 (RFC 9114 §4.2) lowercase header field names on the wire, so a case-sensitive lookup can miss the header. When X-Sentry-Rate-Limits is missed on a 429, many SDKs fall back to rate-limiting all categories, silently over-dropping all telemetry.

Do not judge by the string casing alone — trace the lookup to the HTTP client's header container and determine whether the read is genuinely case-sensitive. Use these lenses: (1) follow the response header names forward from the wire to the string comparison, noting any normalization; (2) treat it as guilty until you can prove the lookup is case-insensitive; (3) check whether the rate-limit tests ever feed a lowercased header name; (4) grep comments/CHANGELOG for prior awareness. Report a verdict of confirmed-bug / fragile / safe with exact file:line evidence, and whether a missed header degrades to an all-category rate limit.

3. (Optional) higher confidence: ask Claude Code to run the audit a second time "with a different method and without looking at the first result," then diff the two verdicts.

Reference (the correct, case-insensitive implementation): getsentry/sentry-cocoa#8324

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions