Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/tame-cookies-relax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': minor
---

fix: default cookies to `secure` to `false` during development
6 changes: 3 additions & 3 deletions packages/kit/src/exports/public.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ export interface Cookies {
/**
* Sets a cookie. This will add a `set-cookie` header to the response, but also make the cookie available via `cookies.get` or `cookies.getAll` during the current request.
*
* The `httpOnly` and `secure` options are `true` by default (except on http://localhost, where `secure` is `false`), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP.
* The `httpOnly` is `true` by default, as is `secure`, except during development, when it defaults to `false`. These must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP.
*
* The `path` option is `'/'` by default. You can use relative paths, or set `path: ''` to make the cookie only available on the current path and its children.
* @param name the name of the cookie
Expand All @@ -288,7 +288,7 @@ export interface Cookies {
/**
* Deletes a cookie by setting its value to an empty string and setting the expiry date in the past.
*
* The `httpOnly` and `secure` options are `true` by default (except on http://localhost, where `secure` is `false`), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP.
* The `httpOnly` is `true` by default, as is `secure`, except during development, when it defaults to `false`. These must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP.
*
* The `path` option is `'/'` by default. You can use relative paths, or set `path: ''` to make the cookie only available on the current path and its children.
* @param name the name of the cookie
Expand All @@ -299,7 +299,7 @@ export interface Cookies {
/**
* Serialize a cookie name-value pair into a `Set-Cookie` header string, but don't apply it to the response.
*
* The `httpOnly` and `secure` options are `true` by default (except on http://localhost, where `secure` is `false`), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP.
* The `httpOnly` is `true` by default, as is `secure`, except during development, when it defaults to `false`. These must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP.
*
* The `path` option is `'/'` by default. You can use relative paths, or set `path: ''` to make the cookie only available on the current path and its children.
* @param name the name of the cookie
Expand Down
2 changes: 1 addition & 1 deletion packages/kit/src/runtime/server/cookie.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export function get_cookies(request, url) {
httpOnly: true,
path: '/',
sameSite: 'lax',
secure: url.hostname === 'localhost' && url.protocol === 'http:' ? false : true
secure: !__SVELTEKIT_DEV__ && !(url.hostname === 'localhost' && url.protocol === 'http:')
};

/** @type {import('@sveltejs/kit').Cookies} */
Expand Down
31 changes: 26 additions & 5 deletions packages/kit/src/runtime/server/cookie.spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import process from 'node:process';
import { assert, expect, test, describe, beforeAll } from 'vitest';
import { assert, expect, test, describe, beforeAll, vi } from 'vitest';
import { domain_matches, path_matches, get_cookies } from './cookie.js';

vi.stubGlobal('__SVELTEKIT_DEV__', undefined);

const domains = {
positive: [
['localhost'],
Expand Down Expand Up @@ -37,8 +39,7 @@ const cookies_setup = ({ href, headers } = {}) => {

describe.skipIf(process.env.NODE_ENV === 'production')('cookies in dev', () => {
beforeAll(() => {
// @ts-expect-error
globalThis.__SVELTEKIT_DEV__ = true;
vi.stubGlobal('__SVELTEKIT_DEV__', true);
});

test('warns if cookie exceeds 4,129 bytes', () => {
Expand All @@ -51,12 +52,25 @@ describe.skipIf(process.env.NODE_ENV === 'production')('cookies in dev', () => {
assert.equal(error.message, 'Cookie "a" is too large, and will be discarded by the browser');
}
});

test('secure defaults to false when served over http (e.g. --host)', () => {
const { cookies, new_cookies } = cookies_setup({ href: 'http://192.168.0.1:5173' });
cookies.set('a', 'b', { path: '/' });
const opts = new_cookies.get('/?a')?.options;
assert.equal(opts?.secure, false);
});

test('secure defaults to false even when served over https', () => {
const { cookies, new_cookies } = cookies_setup({ href: 'https://192.168.0.1:5173' });
cookies.set('a', 'b', { path: '/' });
const opts = new_cookies.get('/?a')?.options;
assert.equal(opts?.secure, false);
});
});

describe.skipIf(process.env.NODE_ENV !== 'production')('cookies in prod', () => {
beforeAll(() => {
// @ts-expect-error
globalThis.__SVELTEKIT_DEV__ = false;
vi.stubGlobal('__SVELTEKIT_DEV__', false);
});

domains.positive.forEach(([hostname, constraint]) => {
Expand Down Expand Up @@ -112,6 +126,13 @@ describe.skipIf(process.env.NODE_ENV !== 'production')('cookies in prod', () =>
assert.equal(opts?.secure, false);
});

test('secure defaults to true on http on a non-localhost host', () => {
const { cookies, new_cookies } = cookies_setup({ href: 'http://192.168.0.1:5173' });
cookies.set('a', 'b', { path: '/' });
const opts = new_cookies.get('/?a')?.options;
assert.equal(opts?.secure, true);
});

test('overridden defaults when set is called', () => {
const { cookies, new_cookies } = cookies_setup();
cookies.set('a', 'b', { secure: false, httpOnly: false, sameSite: 'strict', path: '/a/b/c' });
Expand Down
6 changes: 3 additions & 3 deletions packages/kit/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ declare module '@sveltejs/kit' {
/**
* Sets a cookie. This will add a `set-cookie` header to the response, but also make the cookie available via `cookies.get` or `cookies.getAll` during the current request.
*
* The `httpOnly` and `secure` options are `true` by default (except on http://localhost, where `secure` is `false`), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP.
* The `httpOnly` is `true` by default, as is `secure`, except during development, when it defaults to `false`. These must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP.
*
* The `path` option is `'/'` by default. You can use relative paths, or set `path: ''` to make the cookie only available on the current path and its children.
* @param name the name of the cookie
Expand All @@ -262,7 +262,7 @@ declare module '@sveltejs/kit' {
/**
* Deletes a cookie by setting its value to an empty string and setting the expiry date in the past.
*
* The `httpOnly` and `secure` options are `true` by default (except on http://localhost, where `secure` is `false`), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP.
* The `httpOnly` is `true` by default, as is `secure`, except during development, when it defaults to `false`. These must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP.
*
* The `path` option is `'/'` by default. You can use relative paths, or set `path: ''` to make the cookie only available on the current path and its children.
* @param name the name of the cookie
Expand All @@ -273,7 +273,7 @@ declare module '@sveltejs/kit' {
/**
* Serialize a cookie name-value pair into a `Set-Cookie` header string, but don't apply it to the response.
*
* The `httpOnly` and `secure` options are `true` by default (except on http://localhost, where `secure` is `false`), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP.
* The `httpOnly` is `true` by default, as is `secure`, except during development, when it defaults to `false`. These must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP.
*
* The `path` option is `'/'` by default. You can use relative paths, or set `path: ''` to make the cookie only available on the current path and its children.
* @param name the name of the cookie
Expand Down
Loading