Skip to content

tree: refuse to let a regexp placeholder match a slash across segments - #1224

Open
piyush295 wants to merge 1 commit into
go-chi:masterfrom
piyush295:fix/regexp-placeholder-no-slash
Open

piyush295 wants to merge 1 commit into
go-chi:masterfrom
piyush295:fix/regexp-placeholder-no-slash

Conversation

@piyush295

Copy link
Copy Markdown

Bug (fixes #1188)

A regexp placeholder with a non-slash tail could span path segments. For a pattern like /re/{name:[^.]+}.json, the segment-end delimiter chi uses is the first byte of the suffix (.), not /. If the user's regexp did not itself exclude /, the capture could include one:

GET /re/a.json      -> 200 name="a"
GET /re/a/b.json    -> 200 name="a/b"   # bug: regexp matched across segments
GET /bare/a/b       -> 404
GET /plain/a/b.json -> 404

The "URL patterns" documentation in chi.go says of a regexp placeholder that / will never match. The ntParam branch already enforces this with a strings.IndexByte(xsearch[:p], '/') != -1 check. The ntRegexp branch didn't.

Fix

After a successful regexp match in the ntRegexp branch, apply the same cross-segment guard: if the matched substring contains a /, skip the node. This holds the public contract regardless of what the user regexp allows.

Test

TestMuxRegexpPlaceholderWithSuffixDoesNotMatchSlash registers both /re/{name:[^.]+}.json and /plain/{name}.json and asserts:

  • Single-segment inputs still match (/re/a.json → name="a", /plain/a.json → name="a").
  • Slash inside the placeholder value is 404 for both forms (/re/a/b.json, /plain/a/b.json).

go test ./... passes (both chi and chi/middleware).

A regexp placeholder with a non-slash tail could span path segments. For a
pattern like /re/{name:[^.]+}.json the segment-end delimiter chi uses is
the first byte of the suffix ('.'), not '/'. If the user's regexp did not
itself exclude '/', the capture could include one: /re/a/b.json matched
with name="a/b". The URL-patterns contract says a placeholder value will
never contain '/', so chi must enforce that regardless of what the user
regexp allows. The ntParam path already does this check.

Apply the same cross-segment guard to the ntRegexp branch after a
successful regexp match: skip the node if xsearch[:p] contains a '/'.

Regression test TestMuxRegexpPlaceholderWithSuffixDoesNotMatchSlash
confirms /re/a.json still matches (name="a") while /re/a/b.json 404s,
and a plain placeholder with suffix 404s on the same input for parity.

Fixes go-chi#1188.
@piyush295
piyush295 force-pushed the fix/regexp-placeholder-no-slash branch from 9600d50 to 99ea9fd Compare October 16, 2026 09:26

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A regexp placeholder followed by a suffix matches a value containing /

1 participant