Skip to content

Same-origin server fetch missing credentials for absolute paths #1777

@GrygrFlzr

Description

@GrygrFlzr

Describe the bug

if (/^[a-zA-Z]+:/.test(url)) {
// external fetch
const request = new Request(url, /** @type {RequestInit} */ (opts));
response = await options.hooks.serverFetch.call(null, request);

Currently, all absolute fetch requests are treated as cross-origin, and cookies are not passed through. This does not adequately cover the three main cases of same-origin sites where cookies are shared:

  • Different port on the same domain, e.g. localhost:3000 and localhost:5000
  • Subdomains, e.g. api.domain.com and domain.com
  • The same domain and port, but specified as an absolute path to satisfy some library (e.g. Apollo, which sucks)

However, this is not a trivial fix:

  • Passing in cookies for all external requests would lead to indiscriminately sending cookies to cross-origin domains, which is wasted bandwidth at best and a security violation at worst.
  • Browsers do not send the domain associated with cookies. A SvelteKit server hosted at sub.domain.com can receive cookies from domain.com OR sub.domain.com and cannot distinguish the two.

The lack of domain information presents various issues and limitations for potential solutions.

[Loose] If we assume that received cookies all belong to the second-level domain:

  • We must identify what a "second-level domain" actually is (e.g. domain.co.uk exists, so we cannot blindly assume the level of the domain based on the number of separators)
  • This is a security issue for subdomains that are shared with others, as is common in shared hosting (e.g. vercel, github pages, js.org) as it can happily send all vercel.app cookies to malicious.vercel.app
  • This assumption is invalid for any pages hosted on direct IP addresses (eg. https://1.1.1.1 from Cloudflare)

[Strict] If we pick the strictest domain and assume received cookies belong to the current domain of the application:

  • A SvelteKit app hosted at sub.domain.com would have to assume domain.com cookies as sub.domain.com cookies, and so api.domain.com would not be eligible to receive the cookies from server-side fetch using this algorithm, despite the fact that they would normally be passed by the browser clientside.
  • The above behavior would require extensive documentation, as it would be a difference between the client and the server fetch.

The above also assumes we can adequately identify the current host. The Host HTTP header can be manipulated by the client, which seems questionable. A configurable setting may lead unaware devs to emulate the loose mode to "make things work" and turn the feature into a footgun.

To Reproduce
https://github.com/GrygrFlzr/sk-cookie-issue

Expected behavior
Cookies passed through to the API endpoint for the "Same Domain and Port" and "Same Domain, Different Port" cases.

Information about your SvelteKit Installation:

Diagnostics
  System:
    OS: Windows 10 10.0.22000
    CPU: (16) x64 AMD Ryzen 7 3700X 8-Core Processor
    Memory: 15.96 GB / 31.93 GB
  Binaries:
    Node: 14.16.0 - C:\program files\nodejs\node.EXE
    Yarn: 1.22.10 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 6.14.13 - C:\program files\nodejs\npm.CMD
  Browsers:
    Chrome: 91.0.4472.124
    Edge: Spartan (44.22000.1.0), Chromium (91.0.864.59)
    Internet Explorer: 11.0.22000.1
  npmPackages:
    @sveltejs/kit: next => 1.0.0-next.119
    svelte: ^3.34.0 => 3.38.3

Severity
Depends:

  • Annoyance for situations where proxying the API in SvelteKit is possible - it's an extra network trip.
  • Blocking for situations involving third party libraries.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions