fix: reject dot segments in request paths by max-programming · Pull Request #1139 · resend/resend-node · GitHub
Skip to content

fix: reject dot segments in request paths - #1139

Merged
felipefreitag merged 1 commit into
resend:canaryfrom
max-programming:fix/reject-dot-segments
Oct 15, 2026
Merged

felipefreitag merged 1 commit into
resend:canaryfrom
max-programming:fix/reject-dot-segments

Conversation

@max-programming

@max-programming max-programming commented Oct 7, 2026 •

Copy link
Copy Markdown

follow up to #1113, split out as suggested in this comment. this only blocks . and .. path segments, no encoding changes.

what's happening

url paths work like folders, and .. means "go up one level". fetch resolves that before sending, so an id of . or .. (or one containing ../) takes the request to a different endpoint:

  • emails.cancel('..') sends POST /cancel
  • domains.remove('../api-keys/KEY_ID') sends DELETE /api-keys/KEY_ID, which is the delete api key endpoint

if an app passes user input as an id, that lets a call escape its own endpoint.

the fix

fetchRequest now checks the path and returns an invalid_parameter error without sending anything if any segment is . or ... it also catches the encoded forms like %2E%2E, since url parsing treats those as dot segments too. it returns the error instead of throwing, same as the other input checks in the sdk.

nothing that works today changes. a dot segment always ended up on the wrong endpoint, and ids are still sent exactly as passed, so values that are already encoded keep working. ids that just contain dots (..., john.doe@example.com) go through as normal.

tests

  • has-dot-segment.spec.ts: detects . / .. and the encoded forms, ignores the query string and fragment, allows ... and dotted emails
  • resend.spec.ts: ., .. and ../api-keys/key-id return invalid_parameter and no request is made, ... still goes through

verified

built the sdk from the current release and from this pr, pointed both at a local http server via baseUrl, and logged the request that actually arrived:

call request sent today request sent with this fix
emails.get('..') GET / not sent, returns invalid_parameter
emails.cancel('..') POST /cancel not sent, returns invalid_parameter
domains.remove('.') DELETE /domains/ not sent, returns invalid_parameter
domains.remove('../api-keys/KEY_ID') DELETE /api-keys/KEY_ID not sent, returns invalid_parameter
emails.get('...') GET /emails/... same
contacts.get({ email: 'team@resend.com' }) GET /contacts/team@resend.com same
contacts.get({ email: encodeURIComponent('team@resend.com') }) GET /contacts/team%40resend.com same

Summary by cubic

Rejects request paths containing . or .. segments so user-supplied IDs can no longer redirect a request to another endpoint. fetch resolves dot segments before sending, so emails.cancel('..') was hitting POST /cancel and domains.remove('../api-keys/KEY_ID') was hitting the delete API key endpoint.

fetchRequest now returns an invalid_parameter error without sending anything when any path segment is . or .., including percent-encoded forms like %2E%2E. IDs that merely contain dots (..., john.doe@example.com) are unchanged.

Written for commit 2fef573. Summary will update on new commits.

Review in cubic

@max-programming
max-programming requested a review from a team as a code owner October 7, 2026 04:57
@github-actions github-actions Bot added the linear-synced PR has been synced to Linear label Oct 7, 2026
@pkg-pr-new

pkg-pr-new Bot commented Oct 15, 2026

Copy link
Copy Markdown

@felipefreitag
felipefreitag merged commit f765894 into resend:canary Oct 15, 2026
8 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

linear-synced PR has been synced to Linear

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants