Securing cookies
What the Secure and HttpOnly attributes do and how to set them.
What we check
A cookie is a small note your site stores in the browser, for example for the shopping cart or the login. If a login cookie falls into the wrong hands, someone can pose as your user. We look at the cookies your homepage sets on the first visit and check two attributes on each. The result shows up to six notices for this.
A cookie is set with the Set-Cookie header. After the value come attributes that tell the browser how to handle the cookie. Without Secure or HttpOnly, the browser handles it more loosely.
Cookies don’t affect the grade. We don’t see cookies that are set only after a login or by JavaScript.
We only report cookies whose name looks like a session, login or token, such as session, sid, PHPSESSID, JSESSIONID, laravel_session, fe_typo_user or auth_token. Cookies for language, analytics, load balancing or consent don’t carry an account and often have to be readable by scripts. For them the notice would be a false alarm. Tokens against forged forms (CSRF, XSRF) must be readable by your own script, so for them we only check Secure.
Secure
With the Secure attribute, the browser sends the cookie only over encrypted connections. Without Secure, a single request over http is enough for the cookie to travel unencrypted. Someone on the same network can then read it.
How to fix it: add Secure to every cookie. If your site runs over HTTPS, there is no reason not to.
HttpOnly
With HttpOnly, the cookie is invisible to scripts. This mainly protects login cookies. If foreign code runs on your site, it can’t read them and can’t pose as your user. How such code gets onto a page and how to stop it is covered under Protection against injected scripts.
How to fix it: set HttpOnly on everything your own browser scripts don’t need to read, and always on session cookies. The exception is cookies a script needs, such as a consent banner that remembers what visitors chose.
What it looks like done right
Set-Cookie: session=…; Path=/; Secure; HttpOnly; SameSite=LaxWe don’t check SameSite=Lax, but it is a good default. It makes it harder for other sites to trigger requests with the cookie on behalf of your visitors. Here is how to set the attributes in two common places:
session.cookie_secure = 1
session.cookie_httponly = 1
session.cookie_samesite = Laxres.cookie("session", value, { secure: true, httpOnly: true, sameSite: "lax" });If a cookie comes from a third-party service, such as an analytics tool or the shop system, you often can’t change it yourself. Check that service’s settings instead.
Still have questions? Email us.