Test your banner on http://localhost in Safari and the consent cookie may never stick: before Safari 27, WebKit dropped every cookie marked Secure on loopback hosts, silently. We measured it on Safari 26.6.2 — both a Set-Cookie header and a document.cookie write vanished, on 127.0.0.1 and on localhost, while Chromium kept all four. The trap is that window.isSecureContext is true on loopback, so the code has every reason to think Secure is safe to set. Safari 27.0, released 17 September 2026, fixes it.
This one wastes an afternoon because the symptom points at the wrong thing. The banner works. The click handler runs. The cookie write executes without an error. Reload, and the banner is back — only in Safari, and only on your machine.
What we measured
The fixture is a small Node server on 127.0.0.1:8931. Each load sets four cookies: two through a Set-Cookie response header and two through document.cookie, one of each pair carrying Secure. Then it reports what document.cookie holds, and what the browser sends back in the Cookie header on the next request.
Set-Cookie: hdr_secure=1; Secure; SameSite=Lax; Path=/
Set-Cookie: hdr_plain=1; SameSite=Lax; Path=/
document.cookie = "js_secure=1; Secure; SameSite=Lax; path=/";
document.cookie = "js_plain=1; SameSite=Lax; path=/";
Run on macOS 26.6.2 on 20 September 2026:
Safari 26.6.2 http://127.0.0.1:8931 hdr_plain=1; js_plain=1
Safari 26.6.2 http://localhost:8931 hdr_plain=1; js_plain=1
Chromium 152 http://127.0.0.1:8931 hdr_secure=1; hdr_plain=1; js_secure=1; js_plain=1
Chromium 152 http://localhost:8931 hdr_secure=1; hdr_plain=1; js_secure=1; js_plain=1
Safari kept the plain cookies and discarded both Secure ones, through both write paths. No exception, no console warning, no failed request. And in all four runs window.isSecureContext reported true, because loopback origins count as potentially trustworthy — which is exactly why a developer adds Secure here and expects it to work.
We did not test Safari 27 itself: this machine runs 26.6.2, the version before the fix. What is measured above is the old behaviour, which is still what everyone on macOS 15 or on an un-updated Safari has today.
Why the Storage tab does not help
The obvious next move is to open Web Inspector, look at Storage, and see whether the cookie is there. It will not be — and after Safari 27 it still will not be. The WebKit change says so directly: “Web Inspector will still not show Secure cookies for loopback hostnames with insecure schemes”, pointing at bug 311205. So on Safari 27 the cookie can be stored and sent while the inspector shows nothing, which is its own kind of confusing.
The reliable check is the one the fixture uses: read document.cookie, and look at the Cookie request header on the next request in the Network tab.
What Safari 27 actually changes, and where
The release note, published 17 September 2026, is short: “Safari 27.0 adds support for Secure cookies on loopback hosts”, so that on plaintext HTTP loopback they “can now be set via JavaScript and Set-Cookie headers, matching the behavior of other browsers”.
The conditions are in the pull request rather than the note, and they matter:
- It applies “on Cocoa builds only” — Safari and WKWebView on Apple platforms, not other WebKit ports.
- “For macOS builds, this change only takes effect on >= 26.0.” Safari 27 can be installed on macOS 15 Sequoia, but this particular fix depends on the newer OS.
- WebKit treats as loopback:
localhostand*.localhost, and addresses in127.0.0.0/8. A hostname that merely looks local, or a LAN address such as192.168.x.x, is not covered. - The PR notes it “in isolation does not make
Securecookies work correctly” without the underlying cookie storage accepting them too.
So “fixed in 27” is true, and “fixed for everyone testing on a Mac” is not.
Who this actually breaks
We read the current sources of the main open-source CMPs today, and most of them sidestep this by construction:
- CookieConsent adds the flag only on HTTPS:
if (secure && protocol === 'https:'). - tarteaucitron does the same:
location.protocol === 'https:' ? '; Secure' : ''. - Klaro writes
SameSite=Laxand never setsSecure. - c15t sets it when the caller configures it.
Which means the sites hit by this are the ones whose consent cookie is written by their own code or their framework: a server that always sends Secure on Set-Cookie, a session-cookie setting forced on globally, or a hand-rolled banner that copied a snippet with Secure in it. In production that flag is correct and should stay. The bug only ever appears in local development — which is precisely where you test consent logic.
What to do
- Test it in ten seconds. On your local site in Safari:
document.cookie = "t=1; Secure; path=/"; document.cookie.includes("t=1"). If that isfalseand the same line istruewithoutSecure, you have this. - Make the flag conditional, the way the CMPs do: set
Securewhenlocation.protocol === 'https:', and let local HTTP go without it. Same behaviour in production, no phantom bug in development. - Or run local HTTPS with a locally trusted certificate, which also gets you accurate
SameSite=Noneand third-party-cookie behaviour — the things a consent implementation actually needs to exercise. - Do not “fix” it by dropping
Securein production. The flag is what keeps a consent record off plaintext connections.
If the cookie survives but the banner still returns, the cause is elsewhere and we have measured two of the common ones: an Expires date Safari refuses to parse, which quietly turns the cookie into a session cookie, and the expiry you set versus the one the browser keeps.
A consent cookie that works in Chrome and disappears in Safari is the kind of thing nobody notices until the banner rate jumps. Scan your site to see which cookies are actually stored with CookieInspector.