[ <- BACK ]

┤ 03 / 06 :: CONSENTSCAN ├

ConsentScan

Three-pass cookie banner audit engine (GDPR/CNIL) with timestamped PDF reports. Also powers Kreio prospecting.

Stack

  • Bun
  • Playwright
  • TypeScript
  • Zod

What I did

ConsentScan checks whether a website actually respects its visitors' cookie choices. The engine opens the page in a real browser, plays the visitor, and records what gets stored at each step: cookies, local storage, third-party hosts contacted, Google Tag Manager, Analytics or Ads IDs.

The output is a timestamped PDF report, with the final URL, the engine version and a SHA-256 fingerprint of the raw capture, to prove what was observed and when. I also use it for Kreio prospecting: a CLI audits a list of sites from a CSV and sets incomplete reports aside.

CONSENTSCANSCANNING...

Target : https://example.com

Pass : 1/3 [░░░░░░░░░░░░░░░░░░░░] 0%

    consentscan :: passes
    * 01 pass 1: baseline [+]

    Load with no interaction at all: anything set here is set before consent.

    * 02 pass 2: reject [+]

    Click "Reject" in a fresh browser context: no non-exempt tracker should remain.

    * 03 pass 3: accept [+]

    Click "Accept": if nothing changes, the CMP is broken.

    tree consentscan

    consentscan/

    ├──

    │ ├── scanner # Playwright

    │ ├── report # PDF + SHA-256

    │ └── shared # Zod

    ├──

    │ └── prospect-scan.ts # CSV -> PDF

    └── Dockerfile

    >> Technical highlights

    • Banner detection in 5 steps: known selectors, iframes, shadow DOM, text heuristics, late injection. 8 CMPs recognized (Didomi, Axeptio, Cookiebot, OneTrust, tarteaucitron…) plus TCF signals.
    • Accept / Reject parity measured: WCAG contrast, relative button area, click depth.
    • Score of 100 minus penalties by severity. When in doubt, no conclusion: a detection failure never counts as a violation, the report is flagged as partial.
    • SSRF guard on every request, redirects included: DNS resolution and private IP ranges blocked.
    • 13 HTML test pages served locally to cover the hard cases (iframe, shadow DOM, late-injected banner).
    • Multi-stage Docker image with Playwright Chromium, running as non-root.