Conversation
gijs-martens
approved these changes
Sep 17, 2026
metcoder95
reviewed
Sep 17, 2026
| ? cookie.expires.getTime() | ||
| : cookie.expires | ||
|
|
||
| if (typeof expiresMs === 'number' && Number.isFinite(expiresMs) && Math.abs(expiresMs) <= 8640000000000000) { |
Member
There was a problem hiding this comment.
Let's just add a comment of why that harcoded number
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #5832 +/- ##
=======================================
Coverage 93.54% 93.54%
=======================================
Files 110 110
Lines 39596 39607 +11
=======================================
+ Hits 37040 37051 +11
Misses 2556 2556 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
stringify guarded expires with a string comparison that only works for the
Date form:
if (cookie.expires != null && cookie.expires.toString() !== 'Invalid Date')
A Date whose time value is NaN stringifies to "Invalid Date" and is skipped,
but a number never does: NaN.toString() is "NaN" and 1e16.toString() is
"10000000000000000". The guard therefore always passes for a number outside
the range representable by Date, and toIMFDate reads NaN/undefined from every
getter and splices those tokens into the header value:
setCookie(headers, { name: 'Space', value: 'Cat', expires: 1e16 })
// Space=Cat; Expires=undefined, undefined undefined NaN undefined:undefined:undefined GMT
The emitted value is not a valid IMF-fixdate. The Max-Age branch a few lines
above already tests the type rather than a stringified value.
Treat a number as absent only when it is not a valid time value, keeping the
existing Date behaviour. Name the upper bound so it is clear it is the largest
time value a Date can represent rather than a magic number.
Non-finite numbers reach stringify already coerced to 0 by the unsigned long
long converter in lib/web/cookies/index.js, so they keep serializing as the
epoch; that coercion is a separate concern.
Signed-off-by: Xia Chao <236466140+bun-unsafe@users.noreply.github.com>
xia-chao
force-pushed
the
fix/cookies-numeric-expires-out-of-range
branch
from
September 17, 2026 09:24
cd66bb8 to
2bbba02
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this fixes
setCookieproduced a brokenExpiresattribute whenexpireswas a number outside the range aDatecan hold:Fixes #5831.
Why
expirescan be aDateor a number, but the check instringifyonly understood theDateform:A bad
Datebecomes the text"Invalid Date", so it gets skipped. A number never does -NaN.toString()is"NaN"and(1e16).toString()is"10000000000000000"- so the check always passed and the value reachedtoIMFDate, which pastedundefined/NaNstraight into the header.The change
Check the number itself, and leave the
Datebehaviour exactly as it was:8640000000000000is the largest value aDatecan hold, so anything passing the check is safe to format. This is the same approach theMax-Agebranch a few lines above already uses.Infinity,-InfinityandNaNare turned into0by the converter inlib/web/cookies/index.jsbefore this code runs, so they still serialize as the epoch. That is a separate problem and this change does not touch it.Tests
Added cases in
test/cookie/cookies.js, next to the existing numeric-expirestest:8640000000000001,1e16,Number.MAX_SAFE_INTEGER) omit the attribute8640000000000000still serializesInfinity,-Infinity,NaNstill serialize as the epochDateis still omittedReverting only
lib/web/cookies/util.jsmakes the new cases fail with:npx standard lib/web/cookies/util.js test/cookie/cookies.jsis clean.