Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

external fetch calls: ensure serialized cookie values are url-encoded #7736

Merged
merged 3 commits into from Nov 22, 2022

Conversation

ximus
Copy link
Contributor

@ximus ximus commented Nov 21, 2022

TLDR

before: external fetch cookie was sent plain

browser
     |
(request with url-encoded cookie) (cookie=foo%2Bbar)
     |
     v
sveltekit node app
     |
(external fetch request made with url-DEcoded cookie) (cookie=foo+bar)
     |
     v
backend service

after: external fetch cookie is url-encoded

browser
     |
(request with url-encoded cookie) (cookie=foo%2Bbar)
     |
     v
sveltekit node app
     |
(external fetch request made with url-ENcoded cookie) (cookie=foo%2Bbar)
     |
     v
backend service

Description

My kit app was making external fetch requests with cookies that were different from the the cookies that were part of the original request to the app.

My request coming from the browser had a session cookie that was url-encoded. My sveltekit server code would then use the kit-fetch to make a request to a backend api server that uses that same session token in the cookie. But when the request to the api left the kit app, the cookie was not url-encoded anymore. This caused problems in my api server because it would parse the
cookies by doing a url-decode on the values. Given my session token could contain characters that could further url-decode, it would get garbled when it was url-decoded by the api, because it was not url-encoded anymore.

From my superficial web readings, there seems to be no hard standard on the encoding of cookies. But the industry trend seems to be to url-encode cookie values.

Conclusion

Given that:

  1. The industry trend seems to be to url-encode cookie values.
  2. This cookie.js code already url-decodes cookies on the way in.
  3. "Forwarded" input cookies are different on the way out than on the way in

I assumed the attached fix is reasonable, that cookies should just always be url-encoded.

Please don't delete this checklist! Before submitting the PR, please make sure you do the following:

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.

Tests

  • Run the tests with pnpm test and lint the project with pnpm lint and pnpm check

Changesets

  • If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running pnpm changeset and following the prompts. All changesets should be patch until SvelteKit 1.0

TLDR

before:

```
browser
     |
(request with url-encoded cookie) (cookie=foo%2Bbar)
     |
     v
sveltekit node app
     |
(external fetch request made with url-DEcoded cookie) (cookie=foo+bar)
     |
     v
backend service
```

after:

```
browser
     |
(request with url-encoded cookie) (cookie=foo%2Bbar)
     |
     v
sveltekit node app
     |
(external fetch request made with url-ENcoded cookie) (cookie=foo%2Bbar)
     |
     v
backend service
```

My kit app was making external `fetch` requests with cookies that were different
from the the cookies that were part of the original request to the app.

My request coming from the browser had a session cookie that was
url-encoded. My sveltekit server code would then use the kit-`fetch` to
make a request to a backend api server that uses that same session token
in the cookie. But when the request to the api left the kit app, the
cookie was not url-encoded anymore. This caused problems in my api
server because it would parse the
cookies by doing a url-decode on the values. Given my session token
could contain characters that could further url-decode, it would get
garbled when it was url-decoded by the api, because it was not
url-encoded anymore.

From my superficial web readings, there seems to be no hard standard
on the encoding of cookies. But the industry trend seems to be to
url-encode cookie values.

Given that:

a) The industry trend seems to be to url-encode cookie values.
b) This cookie.js code already url-decodes cookies on the way in.
c) "Forwarded" input cookies are different on the way out than on the
way in

I assumed the attached fix is reasonable, that cookies should just
always be url-encoded.
@changeset-bot
Copy link

changeset-bot bot commented Nov 21, 2022

🦋 Changeset detected

Latest commit: 519a24f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@sveltejs/kit Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@ximus ximus changed the title ensure serialized cookie values are url-encoded external fetch calls: ensure serialized cookie values are url-encoded Nov 21, 2022
@ximus
Copy link
Contributor Author

ximus commented Nov 21, 2022

if this change makes sense, then I assume there needs to be a changeset as this is a change in behavior.

Copy link
Member

@dummdidumm dummdidumm left a comment

Choose a reason for hiding this comment

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

I think the change makes sense - so yes, please add a changeset 👍 We need to move the encoding step into the previous for loops though. Theoretically, someone could have invoked cookies.set with a different encoding option, which we need to use (line 177 something like .. = (cookie.options.encode || encodeURIComponent)(cookie.value);)

@benmccann
Copy link
Member

lgtm. stackoverflow suggests this is the right solution: https://stackoverflow.com/questions/1969232/what-are-allowed-characters-in-cookies

@ximus
Copy link
Contributor Author

ximus commented Nov 21, 2022

Thanks @dummdidumm, refactored to honour any encode option passed to set().

Also created two top level encode/decode constants to make more consistent and clear the default encoding functions, and referenced them wherever there is a parse or serialisation.

Added a changeset.

kept as separate commits for ease of PR review but you can squash on merge or I can squash myself, let me know.

Copy link
Member

@dummdidumm dummdidumm left a comment

Choose a reason for hiding this comment

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

Thank you!

@dummdidumm dummdidumm merged commit 93712f0 into sveltejs:master Nov 22, 2022
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.

None yet

3 participants