Consent Gap
Does Reject actually reject? ConsentGap checks the cookie banner in front of you, not the policy document behind it.
ConsentGap
Does Reject actually reject? ConsentGap checks the cookie banner in front of you, not the policy document behind it.
Date: 2026-10-26
Form factor: Browser extension (Manifest V3)
Browser surface: toolbar popup + on-demand content script (chrome.scripting)
Status: Prototype
What it is
ConsentGap sits in the toolbar and audits the cookie banner on whatever page you're looking at. It measures whether "Accept" and "Reject" get equal visual weight, checks for pre-ticked opt-in toggles, and — the part no other tool in this collection checks — watches document.cookie for a few seconds after you click Reject to see if a tracking cookie shows up anyway.
Why it has to be an extension
The thing being audited is the live DOM of the page you're on: the actual banner markup, its computed styles, and the cookie jar before and after you click. A site can't tell you its own banner is lying, and a separate web app has no way to reach into a tab you have open. ConsentGap injects a short-lived script into the current tab (chrome.scripting.executeScript, granted by activeTab), reads the banner in place, and keeps watching after the popup closes — the result lands in chrome.storage.local so it's there the next time you open the popup, even if you clicked away in the meantime.
Who it serves
People who've started noticing that clicking "Reject" doesn't always feel like it did anything, and privacy-minded shoppers who want a receipt, not just a feeling. It also fits a second audience almost by accident: site owners and small agencies who want to catch their own banner's "divergence" bug before a regulator or a plaintiff's firm does it for them.
Why it could be profitable
This isn't a hypothetical compliance problem. CNIL fined Google €200 million and SHEIN €150 million in September 2025 for exactly this pattern — a banner that visually honors "Reject all" while the tracking code underneath keeps running. In the US, more than 1,000 California Invasion of Privacy Act lawsuits were filed in 2025 and early 2026 over the same gap between what a banner promises and what the backend does. The EU's Digital Fairness Act, expected as a Commission proposal in Q4 2026, names cookie-banner dark patterns directly.
The free tier is what's built here: one audit per site, kept until you close the tab. The case for a paid tier is standing watch continuously (badge alerts on every new site, not just the one you clicked audit on) and exporting a dated, timestamped report — which is worth more to a privacy researcher building a case than to a casual user, so the honest framing is a niche power-user and B2B compliance-testing product, not a mass-market one. I haven't found a direct competitor doing the before/after cookie check specifically; the closest tools audit banner text against policy, not banner behavior against its own buttons.
How to load it in Chrome
- Open
chrome://extensionsand turn on Developer mode. - Click Load unpacked and select this folder's
extension/directory. - Visit a site with a cookie banner, click the ConsentGap icon, then click Audit this page. Click Accept or Reject on the banner itself — the result appears in the popup a couple of seconds later, even if you close and reopen it.
How to try the demo
- Open
index.htmlin any modern browser — no server needed, it loads its sample data from an inline JSON block as a fallback iffetch()ofsample-data.jsonis blocked byfile://restrictions. - Click the extension icon in the mock toolbar to open the popup panel, then click Audit this page.
- Click Necessary Only on the mock cookie banner at the bottom of the page. Wait about three seconds — the popup's verdict badge will flip to "Divergence detected."
The demo's script.js plays the part of the real content script: it quietly sets a tracking cookie after "Necessary Only" is clicked, the same way a real banner's backend might ignore the click behind the scenes. That part is simulated for the harness; everything the popup shows you is read from real document.cookie state, not a scripted animation.
Permissions, and why each one
| Permission | Why it's needed |
|---|---|
activeTab |
Grants temporary access to the tab you're looking at when you open the popup, so the content script can be injected and read that tab's URL and cookies without asking for every site you visit. |
scripting |
Lets the popup inject content.js into the current tab on demand, instead of running on every page load. |
storage |
Saves each tab's audit result and the recent-audits history so they survive the popup closing. |
What's in this prototype
- Toolbar popup with a working "Audit this page" button, a verdict badge, a findings list, and a recent-audits history
- Content script that detects a cookie banner by DOM heuristics, measures Accept/Reject visual weight, flags pre-ticked toggles, and diffs cookies before and after your click
chrome.storage.localpersistence so results survive the popup closing and reopening- "Copy evidence" button that puts a plain-text, timestamped report on the clipboard
- Demo harness with a mock shop page carrying an intentionally lopsided banner, so the dark pattern and the audit are both visible without installing anything
Roadmap
- Background badge counter that flags divergence on any tab, not just the one you've audited
- Exportable PDF/CSV report for the paid tier, with a hash of the before/after cookie snapshot for evidentiary weight
- Known-CMP opt-out hooks (OneTrust, Cookiebot, Usercentris JS APIs) so the audit can fire the "real" reject call instead of only observing the banner's own buttons
- Cross-device sync of audit history for the paid tier
- A "site owner" mode that runs the same check against a staging URL before launch
Sources
- Cookie Banner Dark Patterns: New Manipulation Tactics Regulators Are Targeting (2026) — CNIL's €200M fine against Google and €150M fine against SHEIN, both in September 2025, both over banners that kept tracking after a "Reject all" click.
- Cookie Window Lawsuits: The Illusion of Consent — over 1,000 CIPA lawsuits filed in 2025 and early 2026 targeting the same promise-versus-backend gap.
- Towards a Digital Fairness Act — EPRS briefing, October 5, 2026 — European Parliament briefing confirming a Commission DFA proposal expected in Q4 2026, targeting dark patterns directly.
Requirements
ConsentGap — Requirements
Goals
- Detect a cookie/consent banner on the current tab without any site-specific configuration.
- Flag visual-weight asymmetry between Accept and Reject controls.
- Flag opt-in toggles that are pre-checked and not labeled as strictly necessary.
- Observe whether a new cookie appears after the visitor clicks Reject, and report it as divergence.
- Persist the result per site so it survives the popup closing.
- Run on minimal permissions — no
<all_urls>, no background service worker, no host permissions beyond whatactiveTabalready grants.
Primary user
A privacy-conscious shopper or reader who keeps seeing a "Reject All" button and no longer trusts that it does anything, plus a secondary B2B user: a small agency or in-house privacy lead who wants to catch a divergent banner on their own site before a regulator or a CIPA plaintiff's firm does.
Functional requirements
- FR1: The popup must show the current tab's origin.
- FR2: Clicking "Audit this page" must inject a content script into the active tab via
chrome.scripting.executeScript. - FR3: The content script must search the page for a banner element containing both accept-like and reject-like controls, using a DOM heuristic (ID/class hints plus button text matching), not a per-site allowlist.
- FR4: If no banner is found, the audit must report
bannerFound: falserather than erroring. - FR5: The content script must compare the Accept and Reject controls' rendered size and fill color and flag asymmetry when the size ratio exceeds 1.6x or only one control has a filled background.
- FR6: The content script must flag any checked toggle inside the banner whose label doesn't contain "necessary," "essential," or "required."
- FR7: The content script must snapshot
document.cookiebefore the visitor acts on the banner. - FR8: The content script must attach click listeners to the detected Accept and Reject controls to record which one the visitor chose.
- FR9: 2.5 seconds after a decision, the content script must re-snapshot cookies and compute which cookie names are new.
- FR10: Divergence is true only when the recorded decision was "reject" and at least one new cookie appeared.
- FR11: Every audit result (found/not found, asymmetry, toggles, decision, divergence) must be written to
chrome.storage.local, keyed by the tab's origin. - FR12: The popup must read the stored result for the current origin on open and whenever the user re-triggers an audit, polling at a short interval so a result that lands after the popup was reopened still shows up.
- FR13: The popup must list the most recent audits across origins, each with a verdict indicator and a relative timestamp.
- FR14: The popup must offer a "Copy evidence" action that copies a plain-text, timestamped summary of the current origin's audit to the clipboard, enabled only once a decision has been observed.
- FR15: The content script must guard against double injection if the user clicks "Audit this page" more than once on the same page load.
User stories
- As a shopper, I want to see whether a site's "Reject All" button actually stopped tracking, so I know whether to trust it next time.
- As a shopper, I want the audit to keep running after I close the popup, so I don't have to keep the extension open while I click through the banner.
- As a privacy researcher, I want a timestamped, copyable record of a divergence finding, so I have something concrete to cite.
- As a site owner, I want to run the same audit against my own banner before launch, so I don't find out about a divergence bug from a lawsuit.
- As a returning user, I want to see my recent audits at a glance, so I can tell which sites have a history of this pattern.
Extension surfaces
- Toolbar popup — shows the current site's audit status, triggers a new audit, lists recent audits, and offers evidence export.
- Content script (
chrome.scripting, injected on demand) — detects the banner, measures asymmetry, checks toggles, and watches cookies before/after the visitor's decision. chrome.storage.local— persists per-origin audit records and the recent-audits list across popup sessions.
Non-functional requirements
- Permissions are limited to
activeTab,scripting, andstorage— no<all_urls>, no persistent background worker. - The content script must not alter the page's own Accept/Reject behavior; it only observes and listens, never calls
.click()on the visitor's behalf. - Cookie inspection is limited to
document.cookie, which only exposes non-HttpOnlycookies readable by page JavaScript — the same cookies the site's own client-side trackers would use. - The popup must render a usable result within one second of the content script finishing its static checks (banner found, asymmetry, toggles), independent of the slower divergence check.
Out of scope (for the prototype)
- Automatically clicking Reject on the visitor's behalf.
- Recognizing specific CMP vendors (OneTrust, Cookiebot, etc.) by name or calling their opt-out JS APIs directly.
- Cross-device sync of audit history.
- Exporting a formatted PDF/CSV report.
- Monitoring every open tab in the background without an explicit audit trigger.
Open questions
- How reliably does the banner-detection heuristic generalize across real-world CMP markup versus the handful of patterns tested here?
- Is 2.5 seconds long enough to catch a delayed tracker fire, or does it need to be configurable per site?
- Should "Accept" being clicked also trigger a cookie diff, to show the baseline a Reject click is supposed to beat?