secure limits a cookie to HTTPS (curl 3,008 also stores it from 127.0.0.1). httponly hides it from document.cookie and thus from XSS (XSS and Escaping). For cross-site requests, samesite=Strict never sends the cookie, Lax sends it only on top-level GET links, and None always sends it but requires secure. Only Chromium 4,389 browsers default to Lax, so always set it.
partitioned (PHP 8.5) opts a third-party cookie into CHIPS: the browser also keys it by the top-level site, so a chat widget embedded in two shops gets two jars and cannot track anyone across them. It is Baseline since December 2025; Chrome 1 keeps third-party cookies, but Safari 10 blocks and Firefox 555 partitions them, so embeddable widgets should opt in.
<?php
$base = ['path' => '/', 'secure' => true, 'httponly' => true];
setcookie('__Host-csrf', bin2hex(random_bytes(8)), $base + ['samesite' => 'Strict']);
setcookie('lang', 'en', $base + ['samesite' => 'Lax', 'expires' => time() + 400 * 86400]);
setcookie('chat', 'w-17', $base + ['samesite' => 'None', 'partitioned' => true]);$ curl -si 127.0.0.1:8215/attrs.php | grep -i ^set-cookie | fold_cookies
Set-Cookie: __Host-csrf=f8f865c02b4c73dc;
path=/; secure; HttpOnly; SameSite=Strict
Set-Cookie: lang=en;
expires=Thu, 28 Oct 2027 08:30:19 GMT; Max-Age=34560000;
path=/; secure; HttpOnly; SameSite=Lax
Set-Cookie: chat=w-17;
path=/; secure; HttpOnly; SameSite=None; PartitionedWithout secure, the chat call throws a ValueError. A __Host- cookie is accepted only with secure, path=/ and no domain, so a hijacked subdomain cannot overwrite it. Sessions take these flags from session.cookie_*.