Skip to content

fix: support multiple cookies with the same name across different paths #14056

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

Closed
wants to merge 3 commits into from

Conversation

yuki0418
Copy link

@yuki0418 yuki0418 commented Jul 26, 2025

fix #13947

Support handling multiple cookies with the same name across different paths.
Previously key of new_cookies object is name. It causes the issue when set same cookie name.
Use unique key from combination of domain, path and name.

Adding a third parameter to cookies.get function to get specific cookie by domain and path name.

New format of a unique key for new_cookies is based on its domain, path, and name liek new_cookies["<domain>/<path>?<name>"]
For example, cookies["/?name"], cookies["example.com/foo?name"]

image

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. Changesets that add features should be minor and those that fix bugs should be patch. Please prefix changeset messages with feat:, fix:, or chore:.

Edits

  • Please ensure that 'Allow edits from maintainers' is checked. PRs without this option may be closed.

@Copilot Copilot AI review requested due to automatic review settings July 26, 2025 11:32
Copy link

changeset-bot bot commented Jul 26, 2025

🦋 Changeset detected

Latest commit: 86f0bfb

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

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes the issue where multiple cookies with the same name but different paths would overwrite each other in the internal cookie storage. The fix changes the internal cookie key structure from using just the cookie name to a unique key combining domain, path, and name.

  • Modified cookie key generation to use domain/path?name format instead of just name
  • Added a third parameter to cookies.get() to retrieve cookies by specific domain and path
  • Updated all tests to use the new cookie key format

Reviewed Changes

Copilot reviewed 3 out of 5 changed files in this pull request and generated 2 comments.

File Description
packages/kit/src/runtime/server/cookie.js Implements the new cookie key generation logic and updates the get/set methods
packages/kit/src/runtime/server/cookie.spec.js Updates test assertions to use new cookie key format and adds new test cases
.changeset/shiny-spoons-stick.md Adds changeset entry for the bug fix

@svelte-docs-bot
Copy link

@yuki0418 yuki0418 force-pushed the fix/same-cookie-names branch from 3c8d117 to 52a674e Compare July 26, 2025 11:36
get: (
name: string,
opts?: import('cookie').CookieParseOptions,
target?: { domain?: string; path?: string }
Copy link
Author

Choose a reason for hiding this comment

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

I'm not sure if target is appropriate name.

Copy link
Member

@PatrickG PatrickG Jul 26, 2025

Choose a reason for hiding this comment

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

I would suggest to put the domain&path options into the opts object.
Having to specify the decode parse option is probably even less likely than having to specify the domain or path option. Having a third argument would mean you have to do cookies.get('my-cookie', undefined, { domain: 'xyz.com' }).

Copy link
Author

Choose a reason for hiding this comment

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

Thank you so much!!
That looks much better.

I changed it!!

@yuki0418 yuki0418 requested a review from PatrickG July 27, 2025 13:56
@Rich-Harris
Copy link
Member

Thank you. This isn't quite right though — it only affects cookies that were created during the current request; the options are ignored for existing cookies. This leads to chaotic outcomes. Consider a case like this:

// src/routes/+layout.server.ts
export function load({ cookies }) {
  cookies.set('foo', 'bar', {
    path: '/'
  });
}
// src/routes/x/y/z/+page.server.ts
export function load({ cookies }) {
  return {
    foo: cookies.get('foo')
  };
}

When you visit /x/y/z for the first time, the cookies.set happens first followed by the cookies.get, which because of the defaults is equivalent to this...

cookies.get('foo', { path: '/x/y/z' });

...which returns undefined, incorrectly. When you reload the page, cookies.get instead reads from the cookie header.

My understanding (double-check me on this) is that the most specific cookie wins, which is to say that if you set all these (order doesn't matter)...

n=1; Path=/; HttpOnly; SameSite=Lax
n=2; Path=/x; HttpOnly; SameSite=Lax
n=3; Path=/x/y; HttpOnly; SameSite=Lax
n=4 Path=/x/y/z; HttpOnly; SameSite=Lax

...then on /x/y/z the Cookie header will be x=4; x=3; x=2; x=1 (which means cookies.get('x') === '4'), while on /x/y it will be x=3; x=2; x=1 (therefore 3) and so on.

So this PR is correct to ensure that cookies.set(name, ...) doesn't clobber existing name cookies, but the cookies.get logic isn't quite right. cookies.get(name) should not take an additional option, but it should look at all the matching cookies in new_cookies and select the most specific value.

Copilot AI added a commit that referenced this pull request Aug 6, 2025
- Add generate_cookie_key function to create unique keys from domain/path/name
- Extend cookies.get() to accept optional domain and path options in opts parameter
- Store cookies with unique keys to prevent overwrites
- Maintain backward compatibility with existing API usage
- Add comprehensive tests for new functionality
- Address review feedback from PR #14056

Co-authored-by: Rich-Harris <[email protected]>
Copilot AI added a commit that referenced this pull request Aug 6, 2025
- Fix formatting issues with prettier
- Verify all tests pass including edge cases
- Confirm TypeScript type checking passes
- Complete implementation addresses all review feedback from PR #14056

Co-authored-by: Rich-Harris <[email protected]>
@yuki0418
Copy link
Author

yuki0418 commented Aug 7, 2025

@Rich-Harris
Thank you for reviewing!!
Now I understand about the get method's problem.

And seen #14131, will you close this PR?

@Rich-Harris
Copy link
Member

I will, yes, since it also fixes getAll and has a drive-by fix for cookies.delete('foo', ...); cookies.get('foo'); which currently returns '' but should return undefined. Thank you!

@Rich-Harris Rich-Harris closed this Aug 7, 2025
@yuki0418
Copy link
Author

yuki0418 commented Aug 7, 2025

Thank you so much!!

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.

Adding or deleting multiple cookies with the same name only modifies the last one
3 participants