Validates cookie security attributes and configuration
3 of 3 free audits left today
See what Cookie finds on your site. No sign-up needed.
Fetch β sends a HEAD request (or GET when HEAD is not supported) to the audited URL as 37AuditsBot. A blocked request ends the audit with 590; any other failure (timeout, DNS, TLS, or an HTTP status of 400 or more) ends it with 500.
Parse β reads every Set-Cookie header in order and parses each one once into its name, value and the Secure, HttpOnly, SameSite, Domain, Path and Expires attributes (attribute names are case-insensitive).
Rules β every rule runs over the whole list and emits one check per offending cookie, naming the cookie in the message, the recommendation and the check data. A cookie without HttpOnly (400) or with SameSite=None but no Secure (401) fails. A missing (300) or unknown (301) SameSite, a cookie set over HTTPS without Secure (302), a Domain without a dot (303), a Path that does not start with / (304) and an empty Set-Cookie header (305) warn.
Aggregate β FAIL wins over WARNING; when no cookie triggers any rule, or the page sets no cookie at all, the audit is SUCCESS (200) and the message lists the cookie names.
Specification pin β every run emits 37A-CookieAuditor-100 (INFORMATION), naming RFC 6265, HTTP State Management Mechanism (April 2011) and noting that SameSite comes from draft-ietf-httpbis-rfc6265bis. It does not change the overall status.
Every row maps to one checkRule* method and one CheckCode, in the order the auditor runs them. CheckCode suffixes use status ranges: 100 information, 200 success, 300β399 warning, 400β499 fail, 500β599 error. Per-cookie rules emit one check per offending cookie; {name} is the cookie name and {url} the audited URL.
| CheckCode | Status | When it fires | Recommendation | Why it matters |
|---|---|---|---|---|
37A-CookieAuditor-100 | INFORMATION | Always. Records the specification this auditor implements. | β (recommendation is null; nothing for the site to change) | β |
37A-CookieAuditor-400 | FAIL | A cookie lacks the HttpOnly attribute. | Add "HttpOnly" to the Set-Cookie header of "{name}" on {url}. | Any script that runs on the page, including an injected one, can read a cookie without HttpOnly and send it elsewhere, which is how sessions get stolen through cross-site scripting. |
37A-CookieAuditor-401 | FAIL | A cookie has SameSite=None without the Secure attribute. | Add "Secure" next to SameSite=None on cookie "{name}" of {url}, or use "SameSite=Lax" if the cookie is not needed cross-site. | Browsers reject SameSite=None cookies that are not Secure, so the cookie is never stored and the cross-site feature it supports, such as an embedded login or payment widget, breaks for visitors. |
37A-CookieAuditor-300 | WARNING | A cookie has no SameSite attribute (absent or blank). | Add "SameSite=Lax" (or "SameSite=Strict") to the Set-Cookie header of "{name}" on {url}. | Without SameSite, browsers decide on their own whether to send the cookie with requests started by other sites, so cross-site request forgery protection varies from one visitor to the next. |
37A-CookieAuditor-301 | WARNING | A cookie's SameSite value is not Lax, Strict or None (case-insensitive). | Replace SameSite="{sameSite}" with "SameSite=Lax", "SameSite=Strict" or "SameSite=None; Secure" on cookie "{name}" of {url}. | Browsers ignore an unknown SameSite value and fall back to their default, so the protection the site intended against cross-site requests is not applied. |
37A-CookieAuditor-302 | WARNING | The audited URL is HTTPS and a cookie lacks the Secure attribute. | Add "Secure" to the Set-Cookie header of "{name}" on {url}. | A cookie without Secure is also sent over plain HTTP, where anyone on the network path can read it and take over the visitor's session. |
37A-CookieAuditor-303 | WARNING | A cookie's Domain attribute is present but contains no dot. | Set Domain on cookie "{name}" to a fully qualified host such as the one serving {url} instead of "{domain}", or drop the attribute to scope the cookie to the current host. | Browsers reject a Domain that does not match the site, so the cookie is silently dropped and logins or preferences stop working for visitors. |
37A-CookieAuditor-304 | WARNING | A cookie's Path attribute is present but does not start with /. | Change Path="{path}" on cookie "{name}" to an absolute path such as "/{path}" or "/". | Browsers ignore a Path that does not start with a slash and use the request path instead, so the cookie is sent to different pages than the site expects. |
37A-CookieAuditor-305 | WARNING | A Set-Cookie header value is blank. | Remove the empty Set-Cookie header (#{position}) from the responses of {url}, or give it a name=value pair with HttpOnly, Secure and SameSite. | An empty Set-Cookie header sets nothing and usually means a broken template or proxy rule, so the cookie the site meant to send never reaches the visitor. |
37A-CookieAuditor-200 | SUCCESS | No Set-Cookie header, or no cookie triggered any rule. Message gives the cookie count and names. | β | β |
37A-CookieAuditor-500 | ERROR | The page could not be fetched (timeout, DNS, TLS, or an HTTP status of 400 or more other than a block). | Make sure {url} answers with HTTP 2xx, then run the audit again. Last error: {error}. | β |
37A-CookieAuditor-590 | ERROR | The audited page answered HTTP 403, HTTP 429 or a Cloudflare challenge, so 37AuditsBot was blocked before it could read the page. | Allow 37AuditsBot in your firewall or bot protection: allowlist its user agent, or verify its Web Bot Auth signature. See https://www.37audits.com/bot. | While 37AuditsBot is blocked this audit cannot look at the site, so problems on it go unreported. |
| Status | Description | Test logic |
|---|---|---|
| SUCCESS | Every cookie is hardened, or the page sets none | No Set-Cookie header, or no cookie triggered any rule (200). |
| WARNING | A cookie should be reviewed | Missing SameSite (300); unknown SameSite value (301); no Secure on an HTTPS page (302); Domain without a dot (303); Path not starting with / (304); empty Set-Cookie header (305). |
| FAIL | A cookie is exposed or rejected | Missing HttpOnly (400); SameSite=None without Secure (401). |
| ERROR | The auditor could not read the page | Fetch failure or HTTP status of 400 or more (500); site blocked 37AuditsBot (590). |
| INFORMATION | Specification pin | Always emitted (100); does not change overall status. |
Each per-cookie check carries cookieName, secure, httpOnly, sameSite, domain, path, expires (the parsed value or null) and attribute (the attribute the rule is about) in its data; the empty-header check adds position. The 200 check carries cookieCount and cookieNames.
A session cookie readable by JavaScript is the first thing a cross-site scripting payload exfiltrates; HttpOnly makes it invisible to scripts.
Without Secure, the same cookie is sent when anything on the page or a visitor's typed address falls back to http://, where it can be read on the network.
SameSite decides whether the cookie accompanies requests started by other sites, which is what cross-site request forgery relies on. Browsers default differently when it is missing, so an explicit value gives every visitor the same protection.
A missing HttpOnly and a SameSite=None without Secure fail; browsers reject the latter outright, so the feature that depends on it breaks.
A missing Secure on HTTPS is a warning: many frameworks add it automatically behind a proxy, but confirm it reaches the browser.
Cookies that must be read by page scripts (a CSRF token for a JavaScript client, a theme preference) legitimately lack HttpOnly. The auditor cannot tell them from session cookies, so review the finding for each cookie name.
A network error or an HTTP status of 400 or more on the audited page is now ERROR (500), not FAIL: it means the audit could not run, not that the site is wrong.
HttpOnly stays a FAIL and Secure stays a WARNING, as before.
Each finding now carries a CheckCode, the cookie name and a recommendation; findings are no longer keyed by the raw Set-Cookie string.
Only the audited URL is fetched, with a HEAD (or GET) request and no login: cookies set after sign-in, by other pages or by JavaScript (document.cookie) are not seen.
Expires and Max-Age are recorded but not judged; cookie lifetime is a policy decision.
Cookie prefixes (__Host-, __Secure-) and the Partitioned attribute are not validated.
A Domain with a leading dot is accepted; modern browsers ignore the dot.
This documentation is built and hosted on Mintlify, a developer documentation platform.
Add this auditor to your monitoring setup and start identifying issues on your websites today.