feat(consent-tester): 3 Edge-Cases — kein-Banner-konform, Geo-Caveat, Non-Cookie-Tracking

#1/#2: Wenn KEIN Banner erkannt UND kein Tracking vor Consent (statische Seite
oder nur technisch notwendige Cookies, §25 Abs.2 TDDDG) → affirmativer LOW-Befund
"konform, kein Banner nötig" statt stillem "Banner fehlt". Inkl. Geo-Caveat
(Scan außerhalb EU sieht geo-getargetete Banner evtl. nicht).

#3: detect_non_cookie_tracking erkennt Pixel/Fingerprinting per Domain-Signatur
(Meta, TikTok, LinkedIn, Pinterest, Clarity, FingerprintJS, Hotjar, Reddit,
Snapchat) → MEDIUM-Befund "§25/Art.5(3) gilt auch ohne Cookies". '0 Cookies' ≠
'kein einwilligungspflichtiges Tracking'.

Verdrahtet in consent_scanner vor dem Return. Tests + py_compile grün.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-06-12 19:49:55 +02:00
parent d8a9e3049d
commit c2422138e6
3 changed files with 129 additions and 1 deletions
@@ -94,6 +94,76 @@ def _cookieless_finding(has_dse: bool) -> Violation:
)
# ── #1/#2: Kein Banner erkannt → affirmativ einordnen (nicht still) ─────
def build_no_banner_finding(has_dse: bool) -> Violation:
"""Wenn KEIN Banner erkannt wurde UND vor Consent kein einwilligungs-
pflichtiges Tracking lief: kein Banner noetig (statische Seite / nur
technisch notwendige Cookies, §25 Abs.2 TDDDG) → konform. Inkl. Geo-Caveat.
Nur aufrufen, wenn before_violations UND before_tracking leer sind."""
return Violation(
service="Cookie-Banner",
severity="LOW",
text=(
"Kein Consent-Banner erkannt — und es ist auch keiner erforderlich: "
"Vor einer Einwilligung wurde kein einwilligungspflichtiges Tracking "
"geladen (keine Tracking-Skripte/-Pixel). Typisch fuer eine statische "
"Seite oder eine Seite mit ausschliesslich technisch notwendigen Cookies "
"(Session, CSRF, Login, Warenkorb, Sprache) — die nach §25 Abs.2 TDDDG / "
"Art.5(3) ePrivacy KEINE Einwilligung brauchen. Bewertung: konform. Es "
"bleibt nur die Informationspflicht — eine Datenschutzerklaerung muss "
"erreichbar sein"
+ ("." if has_dse else " (DSE-Link wurde hier nicht gefunden — bitte pruefen).")
+ " METHODEN-HINWEIS: Falls die Seite Geo-Targeting nutzt, sieht ein Scan "
"ausserhalb der EU evtl. keinen Banner — den Scanner-Standort (EU-IP) bei "
"diesem Befund mitdenken."
),
legal_ref="§25 Abs. 2 TDDDG (Ausnahme technisch notwendig), Art. 5(3) ePrivacy, "
"EDPB Guidelines 2/2023",
)
# ── #3: Non-Cookie-Tracking (Pixel/Fingerprinting) — §25 gilt auch ohne Cookies ──
# Domain-Signaturen, die auf Script-URLs zuverlaessig matchen.
_NON_COOKIE_TRACKERS = {
"Meta-Pixel (Facebook)": ("connect.facebook.net", "facebook.com/tr"),
"TikTok-Pixel": ("analytics.tiktok.com",),
"LinkedIn Insight Tag": ("snap.licdn.com",),
"Pinterest-Tag": ("s.pinimg.com/ct",),
"Microsoft Clarity": ("clarity.ms",),
"Fingerprinting (FingerprintJS)": ("fingerprintjs", "fpjs.io", "fpcdn.io"),
"Hotjar": ("static.hotjar.com",),
"Reddit-Pixel": ("redditstatic.com/ads",),
"Snapchat-Pixel": ("sc-static.net", "tr.snapchat.com"),
}
def detect_non_cookie_tracking(scripts: list) -> list:
"""Erkennt cookieloses/script-basiertes Tracking (Pixel/Fingerprinting) in
den geladenen Skript-URLs. Pure + testbar. §25 Abs.1 TDDDG/Art.5(3) ist
technologieneutral → gilt auch ohne Cookies."""
blob = " ".join(s.lower() for s in (scripts or []) if s)
return [name for name, sigs in _NON_COOKIE_TRACKERS.items()
if any(sig in blob for sig in sigs)]
def build_non_cookie_tracking_finding(detected: list) -> Violation:
return Violation(
service="Cookie-Banner",
severity="MEDIUM",
text=(
"Non-Cookie-Tracking erkannt: " + ", ".join(detected) + ". "
"§25 Abs.1 TDDDG / Art.5(3) ePrivacy ist technologieneutral — die "
"Einwilligungspflicht gilt AUCH ohne Cookies (Pixel, Web-Beacons, "
"Fingerprinting). Ein reiner Cookie-Check uebersieht das: '0 Cookies' "
"heisst NICHT 'kein einwilligungspflichtiges Tracking'. Diese Techniken "
"vor jeder Einwilligung pruefen. (Hinweis: Google Consent Mode v2 ist "
"KEINE gueltige Einwilligung, sondern sendet nur modellierte Signale.)"
),
legal_ref="§25 Abs.1 TDDDG, Art.5(3) ePrivacy, EDPB Guidelines 2/2023 "
"(Pixel/Fingerprinting/URL-Tracking einwilligungspflichtig)",
)
async def check_banner_text(page) -> dict:
"""Check cookie banner text for legal issues.