Skip to content

fix(cookies): support valueless unparsed attributes in stringify - #5720

Open
koding88 wants to merge 2 commits into
nodejs:mainfrom
koding88:fix/cookie-valueless-unparsed
Open

fix(cookies): support valueless unparsed attributes in stringify#5720
koding88 wants to merge 2 commits into
nodejs:mainfrom
koding88:fix/cookie-valueless-unparsed

Conversation

@koding88

@koding88 koding88 commented Aug 25, 2026

Copy link
Copy Markdown

Summary

Allows setCookie() / stringify() to handle valueless (boolean) extension attributes in cookie.unparsed, such as Partitioned (CHIPS / RFC 6265bis) or other name-only extension flags, without throwing Invalid unparsed.

Motivation & Background

RFC 6265bis section 5.4 defines extension-av as containing either name=value or name-only attributes (e.g. Partitioned). Previously, stringify() in lib/web/cookies/util.js strictly required every entry in cookie.unparsed to include an = character, throwing new Error('Invalid unparsed') when passing valueless attributes.

const headers = new Headers()
setCookie(headers, {
  name: 'session',
  value: 'abc',
  secure: true,
  path: '/',
  unparsed: ['Partitioned']
})
// Before: throws Error: Invalid unparsed
// After: Set-Cookie: session=abc; Secure; Path=/; Partitioned

Changes

  • Update stringify() in lib/web/cookies/util.js to branch on part.includes('='):
    • If =, validate name & value and format as name=value.
    • If no =, validate name against cookie-name grammar and format as name.
  • Add regression test in test/cookie/cookies.js.

Verification

  • node --test test/cookie/*.js: 92/92 tests pass.
  • npm run test:unit: 1,517/1,517 tests pass (0 failures).
  • npm run lint: Clean (0 warnings, 0 errors).

Previously, stringify() required all items in cookie.unparsed to contain
an '=' character and threw an 'Invalid unparsed' error for valueless
attributes. RFC 6265bis allows extension attributes without a value (such
as 'Partitioned' for CHIPS or other custom flags).

This allows valueless attributes in unparsed while continuing to validate
their names against the cookie-name grammar.
Copilot AI lite review requested due to automatic review settings August 25, 2026 17:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This pull request updates Undici’s cookie header serialization to allow boolean/valueless extension attributes in cookie.unparsed (e.g. Partitioned) to be emitted by stringify() instead of throwing.

Changes:

  • Update lib/web/cookies/util.js stringify() to accept unparsed parts without = by validating and appending the trimmed attribute name as-is.
  • Add a regression test ensuring setCookie() can produce Partitioned in the Set-Cookie header when provided via unparsed.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
lib/web/cookies/util.js Allows valueless entries in cookie.unparsed to be serialized as bare attributes (no =).
test/cookie/cookies.js Adds coverage for setCookie() + valueless unparsed attribute (Partitioned).

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread lib/web/cookies/util.js
Comment on lines 326 to +330
for (const part of cookie.unparsed) {
if (!part.includes('=')) {
throw new Error('Invalid unparsed')
}

const [key, ...value] = part.split('=')
if (part.includes('=')) {
const [key, ...value] = part.split('=')

const trimmedKey = key.trim()
const joinedValue = value.join('=')
const trimmedKey = key.trim()

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Added check for empty trimmed attribute names and added negative test cases in cf530aa.

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.

2 participants