Fix cookie set without its protective attributes in SvelteKit

A cookie is written without `httpOnly`, `secure`, or `sameSite`. Missing `httpOnly` turns any cross-site scripting bug into session theft; missing `secure` sends the cookie over plain HTTP; missing `sameSite` attaches it to cross-site requests. A cookie holding no sensitive value may not need all three, which is why the finding names the ones it did not find rather than assuming the worst.

medium likely SvelteKit CWE-614 / OWASP A05:2021

The vulnerable pattern in SvelteKit

MEDIUM possible Cookie set without its protective attributes A05:2021 src/routes/login/+server.ts:22:3 20 │ 21 │ // insecure-cookie: no httpOnly, no secure, no sameSite. 22 │ cookies.set('session', String(rows.rows[0]?.id ?? 'anon')) │ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cookie written without httpOnly/secure/sameSite 23 │ setSessionCookie(cookies)

This finding comes from the SvelteKit fixture in the owlwarden test suite, in /login. This cookie is missing protections: httpOnly keeps the cookie out of reach of JavaScript, so a cross-site scripting bug cannot read the session; secure stops the cookie being sent over plain HTTP; sameSite stops the browser attaching the cookie to cross-site requests.

The corrected handler

Pass the attributes to `cookies.set`. SvelteKit requires `path`, so the only thing to add is the protection.

cookies.set('session', token, {
  httpOnly: true,
  secure: process.env.NODE_ENV === 'production',
  sameSite: 'lax',
  path: '/',
})

On a different runtime

The fix above is written for the runtime SvelteKit usually runs on. These are the runtimes where it would not run at all - an import that does not exist, or an API the host does not have - and what to write instead.

Workers and other fetch-API runtimes

Build the Set-Cookie header yourself: there is no process.env here, and Headers.set replaces rather than appends - use append, or a second cookie silently disappears.

const attributes = ['HttpOnly', 'Secure', 'SameSite=Lax', 'Path=/'].join('; ')
const headers = new Headers()
headers.append('Set-Cookie', `session=${token}; ${attributes}`)
return new Response(body, { headers })

If you are not using SvelteKit

Set httpOnly, secure, and sameSite when writing a cookie that carries anything the user would not want read or replayed.

Check your own repository

npx owlwarden scan
npx owlwarden explain insecure-cookie

Runs on your machine. No account, no telemetry, no network unless you ask. In CI, SARIF uploads to code scanning and the exit code is the gate.

Other SvelteKit checks

Rules with a tested SvelteKit example.

insecure-cookie for every framework / All rules / owlwarden