गाइड · SSL और सुरक्षा

Cookie Flags Explained: Secure, HttpOnly and SameSite

What the Secure, HttpOnly, SameSite, Domain, Path and cookie prefix attributes do, how to set them in common stacks, and how to debug cookies that go missing.

लेखक: SiteDownCheck संपादकीय टीम · अपडेट: अक्टूबर 5, 2026 · 7 मिनट पढ़ने में

Session cookies are the keys to a logged-in account. If one leaks, whoever holds it is the user. A handful of cookie attributes decide how easily that can happen: whether the cookie travels over plain HTTP, whether JavaScript can read it, and whether other sites can trigger requests that carry it. This guide explains each flag, the SameSite behavior that surprises developers, how to set them in popular stacks, and how to debug a cookie that vanishes.

A server creates a cookie with a Set-Cookie response header:

Set-Cookie: session=9f2c1a7e; Path=/; Secure; HttpOnly; SameSite=Lax; Max-Age=86400

The part before the first semicolon is the name and value. Everything else is an attribute that tells the browser how to store and send it. The browser does not return attributes to the server; on later requests it sends only Cookie: session=9f2c1a7e. That means you can only see attributes in the Set-Cookie response, in DevTools, or with the cookie checker.

Secure

The Secure attribute tells the browser to send the cookie only over HTTPS. Without it, a cookie set for example.com is also sent on any plain HTTP request to the same host, where a network attacker can read it. That includes the first HTTP request a user makes before your redirect to HTTPS happens.

Notes:

  • Set Secure on every cookie on an HTTPS site, not just the session cookie.
  • Browsers refuse to set a Secure cookie from an insecure origin, with the exception of localhost in most modern browsers, which is convenient for development.
  • Secure complements HSTS. HSTS stops the HTTP request being made at all, Secure stops the cookie being sent if one is made. See the HSTS preload guide.
  • Behind a reverse proxy or load balancer that terminates TLS, many frameworks only mark cookies Secure if they believe the request was HTTPS. If your app sees plain HTTP from the proxy, it may omit the flag. Configure the trusted proxy headers (X-Forwarded-Proto) properly.

HttpOnly

HttpOnly hides the cookie from JavaScript. document.cookie will not list it, and scripts cannot read or overwrite it. The point is to limit the impact of cross-site scripting: if an attacker injects script, they cannot simply read the session ID and send it to their server.

It is not a complete defense. A script running on your page can still make authenticated requests with the cookie attached, because the browser adds it automatically. But it blocks the most common theft scenario and costs nothing, so session cookies and any other cookie that only the server needs should be HttpOnly.

Leave HttpOnly off only for cookies that your frontend code genuinely must read, such as a UI theme preference. Never put anything secret in such a cookie.

SameSite

SameSite controls whether the browser attaches the cookie to requests that start on a different site. It is the primary defense against cross-site request forgery (CSRF) at the browser level and it limits tracking by third parties.

ValueCookie sent on cross-site requests?Typical use
StrictNever. Not even when a user clicks a link from another siteBanking, admin sessions
LaxOnly on top-level navigations using safe methods (GET), such as clicking a linkDefault for login sessions
NoneAlways, but requires SecureEmbedded widgets, cross-site APIs, third-party contexts

Important behavior:

  • Default is Lax in modern browsers. If you do not specify SameSite, Chrome and other Chromium browsers treat the cookie as Lax. Do not depend on the default; set it explicitly so behavior is consistent and reviewable.
  • SameSite=None without Secure is rejected. The cookie is silently dropped. The console shows a warning about the cookie being blocked.
  • "Site" is not "origin". Same-site means the same registrable domain (for example example.com), so app.example.com and www.example.com are same-site, and example.com and example.net are not. Cross-origin but same-site requests include SameSite cookies.
  • Strict can feel broken. With Strict, a user following a link to your site from an email or chat app arrives without the session cookie and looks logged out until they navigate again. Many sites use Lax for the main session and Strict for high-risk cookies.

SameSite reduces CSRF risk but does not replace anti-CSRF tokens for state-changing requests, especially while you must support older browsers.

Domain, Path and lifetime

  • Domain. If you omit it, the cookie is host-only: sent only to the exact host that set it. If you set Domain=example.com, it is also sent to all subdomains. Prefer host-only cookies. A broad domain cookie is exposed to every subdomain, including any that run weaker code or could be taken over. See subdomain takeover and dangling DNS.
  • Path. Restricts the cookie to a URL prefix. It is a convenience, not a security boundary, because other paths on the same origin can still access it from script unless HttpOnly is set.
  • Max-Age and Expires. Without either, the cookie is a session cookie that goes away when the browser closes (though browsers with session restore may keep it). Use Max-Age for clarity. Chrome limits cookie lifetime to 400 days regardless of what you ask for.

Prefixes add constraints the browser enforces on the cookie name:

  • __Secure- requires the Secure attribute and a cookie set from a secure origin.
  • __Host- requires Secure, Path=/, and no Domain attribute, locking the cookie to the exact host.
Set-Cookie: __Host-session=9f2c1a7e; Path=/; Secure; HttpOnly; SameSite=Lax

__Host- stops a sibling subdomain from planting or overwriting your session cookie, a technique called cookie tossing. It is the strongest simple setting for a session cookie on a single host.

Partitioned cookies (CHIPS)

Browsers are restricting third-party cookies. If your service runs inside an iframe on other sites (a chat widget or embedded payment form) and needs state, the Partitioned attribute opts a cookie into per-top-level-site storage. It must be combined with Secure and is typically used with SameSite=None. Support varies by browser, so check current compatibility data before relying on it.

Setting flags in common stacks

PHP, for the session cookie:

session_set_cookie_params([
    'lifetime' => 0,
    'path' => '/',
    'secure' => true,
    'httponly' => true,
    'samesite' => 'Lax',
]);
session_start();

Or globally in php.ini:

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

Express (Node.js) with express-session:

app.use(session({
  name: '__Host-sid',
  secret: process.env.SESSION_SECRET,
  cookie: { secure: true, httpOnly: true, sameSite: 'lax', maxAge: 86400000 },
  resave: false,
  saveUninitialized: false,
}));
app.set('trust proxy', 1); // when behind a TLS-terminating proxy

Django in settings.py:

SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = "Lax"
CSRF_COOKIE_SECURE = True

WordPress sets its own cookies, and the usual fix is enabling HTTPS everywhere and using a hardening plugin or wp-config.php constants. See the WordPress security hardening checklist.

At the web server or proxy level, you can rewrite flags on cookies from a legacy app. For nginx with the proxy module this can be done with proxy_cookie_flags:

proxy_cookie_flags ~ secure httponly samesite=lax;

Debugging cookies that go missing

  1. Inspect the raw header. curl -sI https://example.com/login | grep -i set-cookie shows exactly what the server sends. Use the HTTP header checker or cookie checker if you prefer a UI.
  2. Open DevTools, Application, Cookies. Chrome shows each cookie with its flags and, in the Issues panel, why a cookie was blocked.
  3. Look for the cross-site cause. Login through a third-party identity provider, a payment redirect, or an embedded iframe often fails because the return trip is a cross-site POST, which Lax does not carry. Use SameSite=None; Secure for the specific cookie that must survive, and keep the rest Lax.
  4. Check the scheme. A cookie marked Secure will not be set or returned on http:// pages, which is often the hidden reason a dev environment behaves differently from production.
  5. Check the size and count. Browsers limit a cookie to about 4 KB and cap the number per domain. Oversized cookies are dropped or can cause server errors on the next request.
  6. Check domain mismatches. A cookie set for www.example.com is not sent to example.com, and the reverse only holds if Domain is set.

A baseline policy

For a typical site: session cookie __Host- prefixed, Secure; HttpOnly; SameSite=Lax; Path=/, short idle timeout, regenerated at login, and a CSRF token on state-changing forms. Anything cross-site gets SameSite=None; Secure only where required. Back this with HTTPS everywhere, HTTP security headers, and a Content Security Policy.

अगले कदम

सामान्य प्रश्न

Do I need Secure if I use HSTS?

Yes. HSTS protects future connections after the browser has seen it, and Secure protects the cookie itself. Use both; they cover different failure modes.

SameSite=None requires Secure. Without it, modern browsers reject the cookie. Serve the site over HTTPS and add Secure.

Does HttpOnly stop XSS?

No. It stops scripts from reading the cookie, but injected script can still perform actions as the user. It reduces damage; fixing XSS and adding a CSP prevents the attack.

Should analytics cookies be HttpOnly?

Usually not, because client-side analytics code needs to read them. Keep sensitive session and authentication cookies separate from these.

Get notified when this guide updates

Plus occasional practical tips on uptime and monitoring, nothing else. Unsubscribe anytime.

यह पेज सामान्य जानकारी है, जिसे हमारी संपादकीय टीम ने लिखा है और दस्तावेज़ीकरण बदलने पर अपडेट किया जाता है। सर्वर और प्रदाता अलग-अलग होते हैं, इसलिए बदलाव पहले सुरक्षित तरीके से जाँचें। देखें: संपादकीय नीति और अस्वीकरण.