Skip to content

fix(api): refuse request endpoints that ids would reshape - #189

Open
Gabrielpanga wants to merge 2 commits into
masterfrom
fix/encode-path-and-query-params
Open

Gabrielpanga wants to merge 2 commits into
masterfrom
fix/encode-path-and-query-params

Conversation

@Gabrielpanga

@Gabrielpanga Gabrielpanga commented Oct 13, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Ids are interpolated into request paths (accounts/${id}, …). An id containing ?, #, .. or an empty value could change the request actually sent. Follow-up to fix(api): URL-encode query string values #184, which encoded query values.
  • One check in createGetRequest and createMutationRequest (assertSafeEndpoint): an endpoint must not contain a query/fragment delimiter, a % sequence, a backslash, whitespace/control characters, a dot segment, or an empty/leading/trailing slash segment. Query parameters always go through params, so no legitimate endpoint has these. Unsafe endpoints throw before any request is made.
  • No call site changes; valid ids are sent byte-for-byte as before. fetchIdentityByItemId now passes itemId through params instead of building identity?itemId=… by hand.
  • Not covered by design: a / inside an id still reads as a path separator (can't be told apart from the template's own slashes at this point).

Release note

  • Endpoints that an id would reshape (a ?, #, %, \, whitespace, a dot segment, or an empty id) now reject with Error("Refusing to request an unsafe endpoint: ...") before any request is sent. Previously those calls reached the API and failed with its error response (or silently sent a different query). Ids that work today are sent unchanged.

Test plan

  • build, tests (127): accepted/rejected endpoint table; plain UUID request unchanged; unsafe ids rejected with no request sent; identity itemId sent as an encoded query param

@Gabrielpanga Gabrielpanga changed the title fix(api): URL-encode path segments built from caller-provided ids fix(api): refuse request endpoints that ids would reshape Oct 13, 2026
Ids interpolated into request paths were sent as-is, so a value containing
"?", "&", "/" or "#" could change the request that was actually made. Path
values now go through a urlPath tagged template that applies
encodeURIComponent to each interpolated segment, and fetchIdentityByItemId
passes itemId as a query parameter instead of concatenating it into the path.
Plain UUIDs are unchanged on the wire.
…ry path

Replace the urlPath tagged template with one check in createGetRequest and
createMutationRequest: an endpoint built from caller-provided ids must not
contain a query or fragment delimiter, a percent sequence, a backslash,
whitespace or control characters, a dot segment, or an empty, leading or
trailing slash segment. Query parameters always go through params, so no
legitimate endpoint has any of these; the request is refused instead of
being sent with a different shape. Call sites are unchanged, and valid ids
are sent exactly as before. fetchIdentityByItemId passes itemId as a query
parameter.
@Gabrielpanga
Gabrielpanga force-pushed the fix/encode-path-and-query-params branch from 3f9adad to dad7185 Compare November 1, 2026 09:40
@Gabrielpanga

Copy link
Copy Markdown
Member Author

@codex review this

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.

1 participant