> ## Documentation Index
> Fetch the complete documentation index at: https://docs.37audits.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Cookie

> Reviews every Set-Cookie header for the HttpOnly, Secure, SameSite, Domain and Path attributes that keep session cookies out of reach of scripts and other sites.

<Info>
  **Security Auditor** — reads every `Set-Cookie` header the audited URL sends and checks that each cookie carries `HttpOnly`, `Secure` (on HTTPS), a valid `SameSite` and well-formed `Domain` and `Path` attributes.
</Info>

<CardGroup cols={2}>
  <Card title="Protection" icon="shield-halved">
    Keeps session and login cookies away from page scripts, plain-HTTP eavesdroppers and requests started by other sites.
  </Card>

  <Card title="Standards" icon="book">
    Follows RFC 6265 (HTTP State Management Mechanism) and the `SameSite` attribute from its revision in progress, draft-ietf-httpbis-rfc6265bis.
  </Card>
</CardGroup>

Cookies are how a site remembers who a visitor is. A session cookie that a script can read, that travels over plain HTTP or that rides along with requests started by other sites is a session an attacker can take over. The `Set-Cookie` attributes `HttpOnly`, `Secure` and `SameSite` close those three doors, and `Domain` and `Path` must be well-formed or browsers drop the cookie altogether. This auditor inspects every `Set-Cookie` header of the audited URL and reports one finding per cookie and attribute.

## How it works

1. **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`.
2. **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).
3. **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.
4. **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.
5. **Specification pin** — every run emits `37A-CookieAuditor-100` (`INFORMATION`), naming [RFC 6265, HTTP State Management Mechanism](https://www.rfc-editor.org/rfc/rfc6265) (April 2011) and noting that `SameSite` comes from draft-ietf-httpbis-rfc6265bis. It does not change the overall status.

## What it audits

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 |
| - | - | - | - | - |
| <a id="37A-CookieAuditor-100" />`37A-CookieAuditor-100` | `INFORMATION` | Always. Records the specification this auditor implements. | — (recommendation is `null`; nothing for the site to change) | — |
| <a id="37A-CookieAuditor-400" />`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. |
| <a id="37A-CookieAuditor-401" />`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. |
| <a id="37A-CookieAuditor-300" />`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. |
| <a id="37A-CookieAuditor-301" />`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. |
| <a id="37A-CookieAuditor-302" />`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. |
| <a id="37A-CookieAuditor-303" />`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. |
| <a id="37A-CookieAuditor-304" />`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. |
| <a id="37A-CookieAuditor-305" />`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. |
| <a id="37A-CookieAuditor-200" />`37A-CookieAuditor-200` | `SUCCESS` | No `Set-Cookie` header, or no cookie triggered any rule. Message gives the cookie count and names. | — | — |
| <a id="37A-CookieAuditor-500" />`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}`. | — |
| <a id="37A-CookieAuditor-590" />`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](https://www.37audits.com/bot). | While 37AuditsBot is blocked this audit cannot look at the site, so problems on it go unreported. |

## Output documentation

| 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`.

## Risks and considerations

### Why cookie attributes matter

* 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.

### Severity

* 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.

### Behavior changes from the previous version

* 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.

### What this auditor does not check

* 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](https://mintlify.com), a developer documentation platform.