Cookie without Secure flag

A cookie is set without the Secure attribute, so the browser will also send it over plain HTTP. An attacker who can trigger one HTTP request to your domain can capture it.

Do this: Add Secure to every cookie you set. The cookie is sent over plain HTTP too, so one unencrypted request hands the session to anyone listening.
PassAll cookies set on this page carry the Secure attribute.
MediumOne or more cookies are set without the Secure attribute.

The fix, in one snippet

Example to adapt Set-Cookie
Set-Cookie: session=…; Secure; HttpOnly; SameSite=Lax; Path=/

Illustrative values. Change the paths, hostnames and options to match your own site before using it.

The sections below explain what is tested, why it matters and the alternatives.

What we test

Scan.now parses every Set-Cookie header in the HTTPS response to / (and, if port 80 serves content rather than redirecting, in that response too). Each cookie's attributes are read: Secure, HttpOnly, SameSite, Domain, Path, Expires/Max-Age. This check fails for any cookie lacking Secure. Cookies whose names match common session or authentication patterns (PHPSESSID, JSESSIONID, connect.sid, laravel_session, wordpress_logged_in_*, ASP.NET_SessionId, csrftoken, anything containing session, auth or token) are listed first, since those carry the real risk; a language-preference cookie without the flag is noted but not emphasised. Scan.now never logs in, so it sees only cookies set to anonymous visitors; check your authenticated pages the same way in the browser's developer tools. Related: cookie-httponly-flag, cookie-samesite, cookie-prefixes.

Why it matters

Without Secure, the browser attaches the cookie to any http:// request for the domain, and an attacker does not need you to serve anything over HTTP to make one happen. On an open Wi-Fi network they inject <img src="http://example.com/x"> into any unencrypted page the victim views; the browser dutifully sends your session cookie in the clear with that image request, and the attacker replays it to become the victim. HSTS narrows this window but does not close it for cookies scoped to a parent domain when includeSubDomains is not set, and it does nothing for first-time visitors. Modern browsers also enforce "Leave Secure Cookies Alone": a cookie marked Secure cannot be overwritten from an insecure origin, which blocks a class of session-fixation attacks. The cookie flags guide covers the full set of attributes.

How to fix it

A well-formed session cookie looks like this:

Set-Cookie: session=abc123; Path=/; Secure; HttpOnly; SameSite=Lax

Set it at the framework level so every session cookie gets the flag. PHP (php.ini):

session.cookie_secure = 1
session.cookie_httponly = 1
session.cookie_samesite = Lax

Express with express-session (enable trust proxy when TLS terminates at a reverse proxy, or secure: true will refuse to set the cookie):

app.set('trust proxy', 1);
app.use(session({ cookie: { secure: true, httpOnly: true, sameSite: 'lax' }, /* ... */ }));

Django (settings.py): SESSION_COOKIE_SECURE = True and CSRF_COOKIE_SECURE = True. Rails: config.force_ssl = true marks all cookies Secure. If you cannot change the application, nginx 1.19.3+ can add flags to upstream cookies:

proxy_cookie_flags ~ secure httponly samesite=lax;

Apache: Header edit Set-Cookie ^(.*)$ "$1; Secure". Cloudflare does not modify cookie attributes, so fix the origin.

Where this fits

Cookie without Secure flag is check 2 of 4 that the website vulnerability scanner runs under cookie security, ordered the way they are worth fixing. That ordering is the point: Fixing this one while the check above it still fails buys less than it looks like.

Fix this one first

Above it in the same category sits Cookie without HttpOnly flag (medium), where a cookie is readable by JavaScript because it lacks the HttpOnly attribute. An attacker who has that does not need this, so it is the better use of the same hour.

What fixing this still leaves open

Cookie without Secure flag closes one route in. Immediately below it: Cookie without SameSite attribute, where a cookie is set without a SameSite attribute, or with SameSite=None but no Secure flag; Cookie name prefixes (__Host- / __Secure-), where session cookies do not use the __Host- or __Secure- name prefixes, so a subdomain, an HTTP origin or a lookalike path could plant a cookie that your site accepts as its own.

Found in the same scan

The website vulnerability scanner reports this alongside checks from other categories that are at least as serious, including Certificate chain and hostname validation, where the certificate presented for this hostname did not validate: The chain does not reach a trusted root, an intermediate is missing, the name does not match, or the certificate is self-signed or expired, and Exposed .env configuration file, where a .env configuration file is served from the web root. A single run of website vulnerability scanner answers all of them at once.

Prompt for an AI Hand this check to an assistant Sign in to copy it
The first few lines
You are a senior web engineer. I ran a security and SEO scanner against my site and it reported the finding below. Fix it properly rather than suppressing the symptom.

Finding: Cookie without Secure flag (medium severity)
Scanner check id: cookie-secure-flag
17 more lines, including the evidence and the exact fix

The rest of this prompt names the pages and line numbers we found the problem on, the configuration to change, and the constraints a good answer has to respect. It is free, it just needs an account so the work is not scraped wholesale.

Sign in with Google

Signing in is free and takes one click. We store your email address and nothing else.

References

  1. MDN: Set-Cookie
  2. IETF: Cookies: HTTP State Management Mechanism (rfc6265bis)
  3. OWASP Session Management Cheat Sheet

Related guides