Low risk Website cookies · HttpOnly · Secure · SameSite
Cookies missing HttpOnly, Secure or SameSite: what it means and how to fix it
Short answer: cookies are how your website remembers who is logged in. Three small flags control how safely the browser handles them. Without them, a stolen or leaked cookie can let someone take over a logged-in session without knowing the password.
The fix: set login and session cookies with all three flags:
Set-Cookie: session=…; HttpOnly; Secure; SameSite=Lax; Path=/
Most platforms have a setting for this. They're listed below.
What the three flags do
| Flag | What it does | Protects against |
|---|---|---|
HttpOnly | JavaScript in the page can't read the cookie | A malicious script (XSS) stealing login sessions |
Secure | The cookie is only sent over HTTPS | Someone on public Wi-Fi reading it from unencrypted traffic |
SameSite | Controls whether the cookie is sent when another site links to or loads yours | Cross-site request forgery (CSRF), where another site makes a logged-in visitor's browser act for them |
SameSite has three values. Lax fits most sites: the cookie is sent when people click a link to you, but not on hidden requests from other sites. Strict never sends it from other sites, which can log people out when they arrive from an email link. None always sends it, is only for cookies that must work inside other sites (like an embedded widget), and requires Secure.
How serious is it?
On its own it's Low, which is how OWASP ZAP rates it too. These flags limit the damage when something else goes wrong, like a script injection bug or a visitor on an untrusted network. They matter most for sites with logins, shopping carts, customer accounts or admin areas. For a site with no logins, findings about analytics or preference cookies are usually minor.
- 443 Cookie No HttpOnly Flag Found on 4 URLs Low
- 443 Cookie without SameSite Attribute Found on 4 URLs Low
First, find out which cookies it is
The cookie's name tells you what set it, and whether it needs fixing:
- Login and session cookies (names like
PHPSESSID,wordpress_logged_in_…,sessionid,connect.sid,ASP.NET_SessionId,JSESSIONID): fix these first, with all three flags. - Cart, checkout or CSRF cookies: add
SecureandSameSite. AddHttpOnlyunless your site's JavaScript needs to read them. - Analytics, ads and preference cookies (
_ga,_fbp, a cookie-banner choice): these are often set by JavaScript on purpose, so they can't be HttpOnly. Making sure they'reSecureis enough. It's fine to accept the HttpOnly finding for them.
To see your cookies' flags, open your site, press F12, and go to Application (Chrome, Edge) or Storage (Firefox) → Cookies. There are columns for HttpOnly, Secure and SameSite. Or check from the command line:
curl -sI https://your-site.com | grep -i set-cookie
How to fix it on common platforms
PHP (sessions), in php.ini, or ask your host:
session.cookie_httponly = 1
session.cookie_secure = 1
session.cookie_samesite = "Lax"
For cookies your own code sets, pass the options array to setcookie() with 'httponly' => true, 'secure' => true, 'samesite' => 'Lax'.
WordPress. Its login cookies are already HttpOnly. Make sure the whole site uses HTTPS (the WordPress Address and Site Address under Settings → General both start with https://) so they're also Secure. Findings about other cookies usually come from a plugin or theme. The cookie name tells you which, and the plugin's settings or a plugin update may fix it.
Node.js / Express with express-session:
app.set('trust proxy', 1); // if behind a proxy or load balancer
app.use(session({
secret: process.env.SESSION_SECRET,
cookie: { httpOnly: true, secure: true, sameSite: 'lax' },
}));
Django, in settings.py (HttpOnly and Lax are already the defaults for the session cookie):
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SAMESITE = "Lax"
ASP.NET (classic, web.config):
<system.web>
<httpCookies httpOnlyCookies="true" requireSSL="true" sameSite="Lax" />
</system.web>
On ASP.NET Core, set HttpOnly, SecurePolicy = CookieSecurePolicy.Always and SameSite = SameSiteMode.Lax in the cookie or session options.
nginx in front of an app (version 1.19.3 or later) can add the flags to cookies the app sends:
proxy_cookie_flags ~ secure httponly samesite=lax;
Apache can rewrite cookies with mod_headers when the app itself can't be changed. Fixing it in the app is cleaner, because this rule adds the flags even if a cookie already has them:
Header always edit Set-Cookie ^(.*)$ "$1; HttpOnly; Secure; SameSite=Lax"
Test after the change
- Log in, log out, add something to the cart and check out, to make sure nothing broke.
- If your site uses a payment page or login on another domain that sends visitors back to you, check that step specifically. It may need
Laxrather thanStrict. - Re-run the Deep Scan, or check the cookie columns in developer tools again.
Extra credit
- Use the
__Host-name prefix for session cookies (for example__Host-session). Browsers then insist the cookie is Secure, set by your own domain only, and valid for the whole site, which blocks some cookie tricks from subdomains. - Don't set
Domain=on a session cookie unless subdomains really need it. ZAP reports a "Loosely Scoped Cookie" when a cookie is shared more widely than it needs to be. - Pair this with a Content-Security-Policy, which makes script injection harder in the first place, and HSTS, which keeps visitors on HTTPS.
Common questions
Browsers already default to SameSite=Lax. Do I still need to set it?
Chrome and Edge treat cookies without SameSite as Lax, but not every browser does the same, and scanners flag the missing attribute. Setting it explicitly gives the same result everywhere.
Why can't my analytics cookie be HttpOnly?
Because the analytics script sets and reads it in the browser. HttpOnly would stop it from working. That's expected. Make sure it's Secure, and focus HttpOnly on login and session cookies.
Will adding Secure break anything?
Only if part of your site still uses plain HTTP. Secure cookies aren't sent there, so users would appear logged out. Move the whole site to HTTPS first.
Sources: MDN: Set-Cookie · OWASP Session Management cheat sheet · ZAP: Cookie No HttpOnly Flag · ZAP: Cookie Without Secure Flag · ZAP: Cookie without SameSite Attribute · PHP session settings · nginx proxy_cookie_flags