Vulnerability

Insecure Cookie Attributes
detect, understand, remediate

Cookies that ship without Secure, HttpOnly, SameSite, or scoped prefixes expose sessions, CSRF tokens, and authentication state to script theft, network interception, cross-site request abuse, and cross-subdomain leakage. The bug is in the attribute set, not in the cookie value.

No credit card required. Free plan available forever.

Severity

Medium

CWE ID

CWE-1004

OWASP Top 10

A05:2021 - Security Misconfiguration

CVSS 3.1 Score

6.5

What are insecure cookie attributes?

Every Set-Cookie response header carries the cookie name, the cookie value, and a set of attributes that decide how the browser stores, transmits, and exposes the cookie. The attributes (Secure, HttpOnly, SameSite, Domain, Path, Expires or Max-Age, and the __Host- and __Secure- prefixes) are the security boundary around the value. When they are missing, weakened, or scoped too broadly, the cookie value can be read by JavaScript, sent over plaintext HTTP, replayed on cross-site requests, written by a sibling subdomain, or persisted longer than intended.

The vulnerability is in the attribute set, not in the cookie value. A cryptographically perfect session token with weak attributes is exploitable; a short, simple identifier with strong attributes is safer. This is why authenticated scanners, manual penetration tests, and SAST tools consistently flag cookie attribute findings even when the underlying session, CSRF, or remember-me token is otherwise well designed.

Insecure cookie attribute findings most often surface against session cookies, authentication tokens, CSRF anti-forgery tokens, remember-me cookies, and SSO assertion cookies. They also appear on third-party cookies set by analytics, marketing, and embedded widgets, which can leak browsing state across the wider session.

The cookie attribute set

Secure

Restricts the cookie to HTTPS transport. Without Secure, the cookie can be sent on the first plaintext HTTP request and stolen by a network attacker before HSTS upgrades the connection.

HttpOnly

Hides the cookie from document.cookie and any client-side script. Without HttpOnly, an XSS payload anywhere on the origin can read the session cookie directly.

SameSite

Controls whether the browser sends the cookie on cross-site requests. Strict blocks all cross-site sends, Lax allows top-level GET navigations, None requires Secure and is the only attribute that permits cross-site cookies.

Domain and Path

Decide which hosts and URL paths receive the cookie. A Domain set to the registrable domain rather than the exact host lets every subdomain read and write the cookie, including hosts you do not control.

__Host- and __Secure- prefixes

__Host- forces Secure, Path=/, no Domain attribute, and same-origin write. __Secure- forces Secure. Prefixes are the browser-enforced way to make attribute requirements non-overridable.

Expires and Max-Age

Decide how long the cookie persists on disk. A session cookie that becomes a multi-year persistent cookie outlives the user, the device handover, and the credential rotation it was supposed to track.

Partitioned (CHIPS)

Binds a third-party cookie to the top-level site. Without Partitioned, third-party cookies are increasingly blocked by browsers, breaking embedded flows; with Partitioned they survive without becoming a tracking signal.

Priority and SameParty (Chrome-only)

Browser-specific hints. Do not depend on them for security; they affect eviction order and first-party-set scoping rather than confidentiality or integrity.

How it goes wrong

1

Session cookie missing HttpOnly

An XSS payload reads document.cookie, exfiltrates the session token, and the attacker replays it from anywhere on the internet. HttpOnly closes this exfiltration path even when the XSS is otherwise present.

2

Session cookie missing Secure

On the first plaintext request to the origin (before HSTS, on a captive portal, or on a fresh device), the cookie ships in clear text and is captured by anyone on path.

3

SameSite=None without Secure

Browsers reject SameSite=None unless Secure is also set, so the cookie silently drops. The visible result is a broken cross-site embed, not a security alert.

4

Default SameSite ambiguity

Browsers default unset SameSite to Lax for top-level cookies, but the default is not portable across older clients, native WebViews, and legacy SDKs. Explicit SameSite avoids attribute drift.

5

Domain scoped to the registrable domain

Setting Domain=example.com instead of api.example.com lets every subdomain read and write the cookie. A compromised marketing subdomain can then steal or overwrite the production session cookie.

6

Session cookie with Max-Age in years

A session marker that persists for years removes the protective effect of logout, credential rotation, and device retirement; the cookie outlives the trust decision that produced it.

7

No __Host- on a single-origin cookie

Without the __Host- prefix, a future developer can quietly add Domain or change Path. The browser will not enforce the original constraint, and the cookie becomes writable by subdomains.

8

CSRF token reusing the session cookie attributes

A CSRF anti-forgery token cookie that is HttpOnly cannot be read by the JavaScript that needs to mirror it into a header. The defence collapses silently while the cookie attribute set looks correct.

9

Third-party cookie without Partitioned

Embedded widgets and SSO popups that depend on third-party cookies break across browsers that block unpartitioned third-party cookies, and silently fall back to insecure URL-based session passing.

Common causes

Framework defaults

Many web frameworks ship Set-Cookie defaults that omit HttpOnly and SameSite, or set Secure only in production. A misconfigured environment flag in staging leaks the same code path into production cookies.

Reverse proxy or load balancer rewriting

A proxy that terminates TLS may strip the Secure flag if the upstream service believes it is on HTTP. The cookie becomes visible to plaintext clients without any application code change.

Domain set wider than intended

Teams set Domain to the registrable domain to support SSO across subdomains, then never narrow it after consolidation. The wider scope outlives the original requirement.

Library upgrades that flip defaults

A framework or middleware upgrade can flip a default attribute (SameSite, Path, Domain) without surfacing in the release notes. Cookie attribute regression is one of the easiest defaults to miss.

Mixed authentication strategies

Teams that move from session cookies to bearer tokens often leave the legacy cookie in place with weak attributes; the unused cookie remains exploitable until it is removed.

Third-party SDK Set-Cookie

Analytics, A/B testing, and customer support widgets set cookies through their own JavaScript. The first-party application owns the origin but not the attributes the SDK chooses.

How to detect it

Automated detection

  • SecPortal's external scanner records every Set-Cookie attribute from every scanned response and flags missing Secure, HttpOnly, SameSite, and prefix protections
  • Authenticated scanning follows the login flow and inspects the post-authentication cookie set, including SSO and remember-me cookies that only appear after a real session begins
  • Continuous monitoring re-scans on a defined cadence so a framework upgrade or proxy change that quietly weakens attributes is caught against the previous baseline
  • Code scanning against connected repositories flags Set-Cookie call sites and framework cookie configuration that omits attributes

Manual testing

  • Inspect Set-Cookie response headers in browser developer tools (Network tab) for every cookie set during login, password reset, MFA enrolment, and logout
  • Run document.cookie in the console after logging in; if the session cookie appears, HttpOnly is missing
  • Force an HTTP request to the origin and confirm the session cookie does not ship over plaintext; verify HSTS is present so the first request is protected even before the cookie is set
  • Trigger a cross-site GET (via an attacker page) and confirm the session cookie is not sent because of SameSite=Lax or Strict
  • Try to set or overwrite the session cookie from a sibling subdomain to validate that Domain is not scoped too broadly

How to fix it

Set HttpOnly on every session, auth, and MFA cookie

HttpOnly blocks the JavaScript exfiltration path for stolen session cookies. The only cookies that should not be HttpOnly are CSRF anti-forgery cookies that must be read by client script to be mirrored into a request header.

Set Secure on every authentication-bearing cookie

Combine Secure with HSTS so the first request to the origin is also upgraded. Test that staging and local development paths do not silently drop Secure based on environment flags.

Set SameSite explicitly, prefer Strict for session and Lax for CSRF

Explicit SameSite avoids browser default drift. Use Strict for session and authentication cookies, Lax for cookies that need to survive top-level navigations, and None+Secure only when a cross-site embed genuinely requires it.

Prefer the __Host- prefix where possible

A cookie named __Host-Session forces Secure, Path=/, and no Domain attribute; the browser will reject any Set-Cookie that does not meet these constraints. The constraint outlives any future developer who might quietly widen Domain.

Scope Domain to the exact host

Default Domain to omitted (host-only). Only set Domain to the registrable domain when subdomain sharing is required, and document the threat model that allows it (every subdomain becomes a trust boundary).

Bound Max-Age and Expires to the session lifetime

Session cookies should expire on browser close or after a defined idle window. Persistent remember-me cookies should be short-lived and rebound through a server-side rotation step on every use.

Add Partitioned for legitimate third-party cookies

For widgets, SSO popups, and embedded flows that must work cross-site, add Partitioned alongside Secure and SameSite=None. This keeps the cookie usable as browsers tighten third-party cookie policies.

Regression-test cookie attributes in CI

Assert the expected attribute set in integration tests so a framework upgrade or middleware change cannot silently weaken cookies. Cookie attribute regression is invisible to functional tests but devastating to session security.

What this looks like in SecPortal

External scan attribute capture

Every external scan records the Set-Cookie attributes returned by the scanned origin. Missing Secure, HttpOnly, SameSite, and prefix protections are surfaced as findings against the scanned host, with the full response header preserved as evidence on the finding record.

Authenticated scan post-login cookies

Authenticated scanning carries the configured login flow forward and inspects cookies that only appear after authentication (session, SSO, remember-me, MFA). The post-login cookie set is the highest-impact attribute surface and the one external scanning cannot reach.

Code scanning against the framework configuration

Code scanning across connected repositories flags Set-Cookie call sites and framework cookie configuration that omit attributes, so the fix lands at the source rather than at the perimeter.

Retest after the fix ships

Once the attribute change deploys, a targeted retest verifies the new Set-Cookie response and closes the finding with the post-fix evidence attached. Continuous monitoring then re-checks on the defined cadence to catch regressions.

Related tools and reading

Compliance impact

Find cookies with missing attributes in one scan

SecPortal records Set-Cookie attributes from every scanned response, flags missing Secure, HttpOnly, SameSite, and prefix protections, and tracks the fix through retest. Start scanning for free.

No credit card required. Free plan available forever.