curl -I https://example.com/ gets you the raw Set-Cookie header text
in seconds, and for a quick look that's often all you need. The value this tool adds isn't
reading the attribute names -- curl already shows you those. It's two things a manual read (or a
naive script built on top of curl's output) gets wrong.
First, knowing which attribute combinations a browser actively rejects rather
than merely tolerates weakened. SameSite=None without Secure, and a
__Host- or __Secure- prefixed cookie that violates the attribute rules
those prefixes require, aren't read as "less secure" by Chrome, Firefox, and Safari -- they're
rejected outright, and the cookie is never stored at all. Nothing about the raw header text tells
you that; you have to already know the rejection rules and apply them yourself, attribute
combination by attribute combination.
Second, parsing repeated Set-Cookie headers correctly. Most response
headers that repeat can be joined into one string and split on commas. Set-Cookie
cannot: an Expires attribute carries a comma of its own
(Expires=Wed, 21 Oct 2026 07:28:00 GMT), so that join-then-split silently corrupts
any cookie that sets one. This tool reads each Set-Cookie header as its own separate
value -- the way Node's own HTTP client already hands them back -- and never rejoins or re-splits
them.
Two real Set-Cookie headers from one response:
| # | Header value |
|---|---|
| 1 | session=abc123; Path=/; Expires=Wed, 21 Oct 2026 07:28:00 GMT; Secure; HttpOnly |
| 2 | csrf=xyz789; SameSite=None |
| Read correctly (this checker) | Joined and split on commas (the naive shortcut) |
|---|---|
2 cookies: session (Path, Expires, Secure, HttpOnly) and csrf (SameSite=None, flagged samesite-none-without-secure). |
3 fragments: session=abc123; Path=/; Expires=Wed, then 21 Oct 2026 07:28:00 GMT; Secure; HttpOnly with no cookie name attached at all, then csrf=xyz789; SameSite=None. |
The Expires attribute's own comma splits the session cookie's value
away from its trailing attributes mid-string, turning two real cookies into three fragments and
leaving one of them with no name at all. A tool built on the join-then-split shortcut either
drops that fragment or misreports it -- either way, it never reaches the actual attributes it was
supposed to check.
| Question | Where to answer it |
|---|---|
| I just want to eyeball whether a cookie has Secure or HttpOnly set at all. | curl -I -- that's exactly its job, and this tool checks the same attributes as a stricter, automated pass. |
| I want to know whether an attribute combination is one a browser actively rejects, not just weaker. | This checker -- applies the SameSite=None/Secure rule and the __Host-/__Secure- prefix contract for you, instead of leaving you to know and re-check both by eye. |
| I want this checked automatically in CI against my own staging environment. | node check.mjs <url> -- exit code 1 on a danger-severity finding, no reading required. |
| I'm scripting my own parser on top of curl's output and it needs to handle multiple Set-Cookie headers. | This checker's parseSetCookieHeader -- or at minimum, don't join repeated headers into one string before splitting on commas. |
curl -I shows you the raw header text, which is the easy part. What it doesn't tell you is which attribute combinations a compliant browser actively rejects rather than merely tolerates weakened -- SameSite=None without Secure, or a __Host-/__Secure- prefix whose attribute rules aren't met. Reading three attribute names off a terminal doesn't carry that judgment with it; you have to already know the rejection rules to apply them by eye.
The common shortcut is joining every Set-Cookie header into one string and splitting it on commas, the way most other repeated response headers can be handled. Set-Cookie can't: an Expires attribute contains its own comma ("Expires=Wed, 21 Oct 2026 07:28:00 GMT"), so that join-then-split silently breaks into the wrong number of fragments and corrupts the cookie's attributes the moment one of them carries an Expires date.
Two Set-Cookie headers: a session cookie with Path, Expires, Secure, and HttpOnly, and a csrf cookie with SameSite=None. Correctly read as two separate header values, that's two cookies. Joined with ", " and split on every comma instead, the Expires date's own comma splits the session cookie's attributes away from its name mid-value, producing three fragments instead of two -- one of which is just "21 Oct 2026 07:28:00 GMT; Secure; HttpOnly" with no cookie name attached to it at all.
No. The CLI (check.mjs) sends its one request straight from your machine to the URL you name -- never through this site. The browser page only parses JSON you paste into it yourself, locally. The only thing stored is an anonymous local count of which features were used and the day, with no target URLs and no Set-Cookie values in it.
Want the fuller explanation of why the SameSite/prefix rejections read as functional bugs before they read as security ones? Read why a SameSite=None cookie disappears instead of just weakening.