Skip to content

fix: normalize path before rate-limit bucket keying#27273

Merged
BobbyHo merged 2 commits into
mainfrom
coder-plat-376-cdm-02-003
Jul 16, 2026
Merged

fix: normalize path before rate-limit bucket keying#27273
BobbyHo merged 2 commits into
mainfrom
coder-plat-376-cdm-02-003

Conversation

@BobbyHo

@BobbyHo BobbyHo commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Coder's rate limiter keyed its bucket on the raw, un-normalized request path (httprate.KeyByEndpoint reads r.URL.Path directly). The router's singleSlashMW already collapses redundant slashes so a request like /api/v2/users//validate-password reaches the same handler as the canonical path, but it never touched r.URL.Path, so the rate limiter saw a different key and let a client bypass a limit it had already hit just by respelling the URL.

keyByNormalizedEndpoint replaces KeyByEndpoint and runs path.Clean on r.URL.Path before using it as the key, so equivalent paths share one bucket. Includes a unit test at the key-function level and an integration test (TestRateLimitPathNormalization) that reproduces the bypass against a real server.

Fixes CDM-02-003 (Cure53). Refs https://github.com/coder/security-disclosures/issues/166.

BobbyHo added 2 commits July 15, 2026 10:32
The rate limiter keyed buckets on the raw, un-normalized request path
(httprate.KeyByEndpoint reads r.URL.Path directly). Coder's existing
singleSlashMW collapses redundant slashes for chi's routing but leaves
r.URL.Path untouched, so a request like
/api/v2/users//validate-password reached the same handler as the
canonical path while landing in a different rate-limit bucket, letting
a client bypass the limit by respelling the URL.

keyByNormalizedEndpoint replaces KeyByEndpoint and runs path.Clean on
r.URL.Path before using it as the key.

Fixes CDM-02-003 (Cure53). Refs PLAT-376, SEC-265.
Adds TestRateLimitPathNormalization, a regression test for CDM-02-003
(Cure53) that exercises the real coderd router rather than an isolated
key function. It exhausts the rate limit against
/api/v2/users/validate-password, then confirms redundant-slash variants
of the same path share the exhausted bucket instead of getting a fresh
one, complementing the existing httpmw-level unit test.
@linear-code

linear-code Bot commented Jul 15, 2026

Copy link
Copy Markdown

PLAT-376

@BobbyHo BobbyHo changed the title fix(coderd/httpmw): normalize path before rate-limit bucket keying fix: normalize path before rate-limit bucket keying Jul 15, 2026
@BobbyHo
BobbyHo marked this pull request as ready for review July 15, 2026 18:26

@geokat geokat left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm 👍

@BobbyHo
BobbyHo merged commit de716f8 into main Jul 16, 2026
58 of 60 checks passed
@BobbyHo
BobbyHo deleted the coder-plat-376-cdm-02-003 branch July 16, 2026 00:07
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 16, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants