~/blog/consent-mode-is-not-a-consent-gatePOSTED
by Shady Nathan Tawfik · October 7, 2026 · 7 min

Consent Mode Is Not a Consent Gate

A digital agency's website had an up-to-date consent platform, a banner that rendered correctly and Google Consent Mode enabled — and still fired analytics, ads, Meta and LinkedIn before any opt-in, wrote cookies without consent and without Secure, and left its session cookie unprotected. Why signalling is not blocking, and how the fix was measured instead of argued about.

Interactive[blog-2.0]

TL;DR: The consent platform was installed, licensed and current. The banner rendered. Google Consent Mode was switched on. And a fresh browser profile still walked away from the first page load with _ga, _gcl_au, _fbp and nmstat in the jar, having talked to eight third-party hosts — none of which required a click. The platform was in observe mode, not enforce mode: consent mode signals a decision, it does not prevent the tag from loading. The remediation was proven in a lab mirror of the same stack: four pre-consent tag fires became zero.

The scenario

A mid-sized digital agency — the kind of company whose own website is supposed to be a reference for its clients — asked for an external look at their public web surface. Not a penetration test, not an intrusion: a black-box review of what a normal visitor (and a normal crawler, and a normal competitor) can observe without logging in.

The perimeter turned out to be the good kind of boring. The reverse proxy blocked dotfiles and management paths, there was no exposed actuator, no Jenkins, no Solr, no debug console, the certificate covered the whole brand family, and the site was a custom application rather than a plugin-driven CMS. Whoever built it cared.

Then the browser test started and the story inverted.

I removed all identifying information. The target is described only by sector and technology class, and all tag identifiers are redacted, so the pattern can be reused without exposing anyone.

The pattern

The confusion is understandable. A consent platform does two very different things: it collects a decision, and it enforces it. The banner, the settings dialog, the legal texts — that is the collection half. The enforcement half is a configuration: which service is allowed to load in which state, and what happens to a tag that is not yet permitted.

In this case the enforcement half was never configured. Every service was effectively in "observe" mode — visible in the dashboards, reported in the reports, and loading regardless. The banner looked perfect because the banner was perfect. It was answering a question nobody acted on.

Google Consent Mode deserves its own paragraph, because it is the most common source of this false sense of safety. Consent Mode passes a state to Google's tags: "this user denied analytics", "this user denied ads". What Google does with that signal is Google's business — it affects how data is used, not whether the tag runs. The script loads, the cookie is written, the request leaves the visitor's browser.

If you want blocking, the tag must not execute until permission exists. That is a loader decision, not a signal decision.

The evidence is not "the banner looks fine" — it is a fresh profile

The only test that proves anything is a fresh browser profile, no cache, no prior consent state, zero interaction, watching the network and the cookie jar for the first page load. Warm profiles and previously granted consent hide the defect completely. In our run:

  • eight third-party hosts were contacted before any interaction
  • five tracking cookies plus the application's session cookie were set
  • every first-party cookie lacked Secure — on an HTTPS-only site
  • the session cookie was HttpOnly but not Secure

The rest of the perimeter told its own story

While the browser was open, the review also collected: no Content-Security-Policy, no X-Content-Type-Options, no Permissions-Policy, HSTS without includeSubDomains, SPF ending in ~all and DMARC on p=quarantine — plus a set of public DNS verification records that enumerated the agency's entire SaaS stack (two Google properties, JetBrains, Miro, and an AI vendor) for anyone who cared to look.

TL;DR: The banner rendered, the consent platform was up to date, Google Consent Mode was active — and yet a fresh browser profile left the first page load with analytics, ads, Meta and LinkedIn cookies in the jar. Consent Mode signals; it does not block. The blocking was never configured, so the tags simply ran.

Findings

SeverityFindingEvidence
HIGHTracking before consent: tag manager, analytics, ads, Meta pixel, LinkedIn ads, an analytics suite and a video embed all loaded on first paintfresh-profile network capture
HIGHCookies written without consent: _ga, _ga_*, _gcl_au, _fbp, nmstat plus video- and LinkedIn-owned cookiescookie dump with flags
MEDIUMNo Secure flag on any first-party cookie, including the application sessioncookie flags
MEDIUMMissing CSP, nosniff, Permissions-Policy, COOP/CORP; HSTS without includeSubDomains/preload; legacy X-XSS-Protectionresponse headers
MEDIUMSPF softfail, DMARC quarantine onlypublic DNS
LOWrobots.txt, sitemap.xml, security.txt missingpath probes
LOWSaaS stack enumerable from public verification TXT recordspublic DNS
INFOConsent platform present and rendering — enforcement not configuredshadow-DOM inspection

The attack path

  1. Profile first. Consent enforcement aside, the public DNS records hand an attacker the tool stack. From there the question is not "how do I get in" but "which of these five vendors is the weakest link".
  2. Spoof the brand. With SPF on softfail and DMARC on quarantine, forged invoice or application mails in the agency's name survive most filters — and an agency's mailboxes are full of client documents.
  3. Wait for the session. The session cookie travels without Secure. One plaintext request anywhere on the path — a mis-typed http://, a captive portal, an old bookmark — is enough to lift it.
  4. Prep the browser. No CSP and no nosniff is not an exploit by itself; it is the absence of the safety net that turns an injected string into an execution.
  5. Then the tracking, quietly. Eight third-party hosts receive visitor identifiers — including job applicants on the careers pages — before consent. Under TTDSG §25 and GDPR Art. 6 that is not a technicality; it is the finding a regulator starts with.

Reproducing it — and proving the fix

Findings that cannot be reproduced are opinions. So the same stack was rebuilt as a lab mirror: a mock application behind a reverse proxy, a consent gate with a tag loader, and a server-side counter that records which tag fired in which consent state.

ScenarioMeasured result
Vulnerable build, no interaction4 tag fires pre-consent (analytics, ads, Meta, LinkedIn)
Hardened build, no interaction0 fires
Hardened build, after opt-in0 pre-consent / 4 post-consent
Session cookieHttpOnly → HttpOnly; Secure; SameSite=Lax
Hardening headers0 → CSP + nosniff (+ Permissions-Policy, HSTS preload)

That is the difference between "we recommend blocking" and "blocking produces exactly this state, and here is the counter".

How to detect it in your own estate

  • Fresh-profile test on every release, in CI if possible: load the site with a clean profile and fail the build if a third-party host is contacted before consent.
  • Consent platform: report on services that are configured but never block. A service that appears only in the observe column is the defect.
  • Cookie audit: assert the Secure flag on all first-party cookies, and treat any tracking cookie present before opt-in as a release blocker.
  • Header baseline: CSP, nosniff, Permissions-Policy, HSTS with includeSubDomains — checked as a pipeline gate, not a PDF.
  • DNS review every quarter: SPF/DMARC posture and the growing list of vendor verification records.

How to fix it (in this order)

  1. P0 — Enforcement, not observation. In the consent platform, set every non-essential service to blocking, and load the tag manager only through the controlled mode. Verify with a fresh profile: zero third-party requests before opt-in.
  2. P0 — Align the privacy notice with the data flows that actually happen, including the transfer basis for US services.
  3. P1 — Cookies. Secure on all first-party and session cookies; review SameSite.
  4. P1 — Headers. CSP (start report-only), nosniff, Permissions-Policy, COOP/CORP, HSTS to includeSubDomains; preload.
  5. P1 — Mail. SPF to -all, DMARC to p=reject once the reports stay clean.
  6. P2 — Hygiene. robots.txt, sitemap.xml, security.txt; prune unused verification records; move video embeds to youtube-nocookie or click-to-load.

Once an attacker gains access, they can perform the following actions:

Track every visitor — including job applicants — across Google, Meta, LinkedIn and an analytics suite without consent: profiling plus GDPR fine risk
Forge mails in the agency name (SPF softfail, DMARC quarantine only) — invoice and application phishing against clients and HR
Harvest the session cookie off insecure channels (no Secure flag) and enter internal areas as an employee
Prepare clickjacking and content injection on forms and login — no CSP, no nosniff
Map the entire SaaS and tool stack from public verification records and plan targeted supply-chain attacks
Prepare SSL stripping across the brand family — HSTS without includeSubDomains or preload

The takeaway

A consent platform is not a compliance switch. It is a loader — and a loader only blocks the things you tell it to block. The banner will keep rendering beautifully while every tag you forgot to configure sails past it. The only honest test is a fresh profile with no interaction, and the only honest fix is one whose result you can count.

Shady Nathan Tawfik

Founder & Cyber IT Security Engineer in Bielefeld. Offensive security, audits and full-stack builds. More at

For educational purposes only. Every reproducible command targets my own lab environment (localhost), never a live system. © 2026