diff --git a/backend-compliance/compliance/services/doc_checks/cookie_checks.py b/backend-compliance/compliance/services/doc_checks/cookie_checks.py index d6078ca7..bf4ffb5f 100644 --- a/backend-compliance/compliance/services/doc_checks/cookie_checks.py +++ b/backend-compliance/compliance/services/doc_checks/cookie_checks.py @@ -276,19 +276,40 @@ COOKIE_CHECKLIST = [ }, # ── Neue L1: Cookie-Tabelle ─────────────────────────────────────── + # P95: Lockerer Match — Vendor-zentrische Detailseiten (BMW-Stil mit + # Adform-Block etc.) werden als gleichwertig akzeptiert. DSK-OH 2024 + # §3.2 verlangt die Informationen pro Cookie, schreibt aber keine + # Tabellenform vor. Ein Vendor-Block der Name+Anbieter+Zweck+Dauer+ + # Cookie-Namen aggregiert nennt erfuellt das. { "id": "cookie_table", - "label": "Strukturierte Cookie-Tabelle/Liste", + "label": "Strukturierte Cookie-Informationen (Tabelle oder Vendor-Blöcke)", "level": 1, "parent": None, "patterns": [ + # Klassische Tabelle r"(?:cookie[\-\s])?(?:tabelle|uebersicht|übersicht|liste|aufstellung)", r"(?:name|bezeichnung)\s*[\|\t]\s*(?:anbieter|zweck|dauer|laufzeit|funktion)", r"(?:first[\-\s]?party|third[\-\s]?party)\s*[\|\t]", r"(?:typ(?:en)?|name|funktion|speicherdauer)\s+(?:typ(?:en)?|name|funktion|speicherdauer)", r"folgende\s+cookies", r"(?:funktionale|session|analyse|tracking)\s+cookies?\s+\w+", + # P95: Vendor-zentrische Detail-Bloecke (BMW-Stil) — wenn + # mehrere typische Vendor-Block-Marker vorhanden, gilt als + # strukturiert. "Gesetzt von:" + "Opt-Out Link:" + "Privacy" + # ist ein klares Indiz fuer Vendor-Detailseite. + r"gesetzt\s+von\s*[:\|]", + r"opt[\-\s]?out[\s\-]?link\s*[:\|]", + r"speicherdauer\s*[:\|]\s*\d+\s+(?:tag|monat|jahr|day|month|year)", + r"(?:rechtsgrundlage|legal\s+basis)\s*[:\|]", + r"(?:diese\s+datenverarbeitung\s+verwendet\s+die\s+folgenden\s+cookies)", ], "severity": "LOW", - "hint": "Die DSK-Orientierungshilfe empfiehlt eine Tabelle mit 5 Spalten: Name, Anbieter, Zweck, Speicherdauer, Typ (First-/Third-Party). Viele Consent-Tools (Cookiebot, Usercentrics) generieren diese Tabelle automatisch — binden Sie sie ein.", + "hint": "DSK-OH Telemedien 2024 §3.2 verlangt Cookie-Informationen pro " + "Vendor/Cookie (Name, Anbieter, Zweck, Speicherdauer, Drittlandtransfer). " + "Akzeptable Formate: (a) Tabelle mit 5 Spalten oder (b) Vendor-Detailseite " + "mit Block pro Anbieter (Anbieter+Anschrift, Zweck, Speicherdauer aggregiert, " + "Cookie-Namen-Liste, Opt-Out-Link, Drittlandstatus). BMW-Stil mit Adform-" + "Block ist konform. Auch automatisierte CMP-Generierung (Cookiebot, Usercentrics) " + "ist OK.", }, ] diff --git a/consent-tester/services/banner_text_checker.py b/consent-tester/services/banner_text_checker.py index 433fb268..c6977def 100644 --- a/consent-tester/services/banner_text_checker.py +++ b/consent-tester/services/banner_text_checker.py @@ -159,8 +159,18 @@ async def check_banner_text(page) -> dict: # (e.g. only "Nur technisch Notwendige" — semantically # a reject but EDPB 5/2020 + DSK-OH 2024 prefer explicit # labeling so users recognize it as the reject option) - explicit_reject_texts = ["ablehnen", "reject", "alle ablehnen", - "decline", "alles ablehnen"] + # P93: EDPB 5/2020 schreibt kein bestimmtes Wort vor — Reject- + # Mechanismus muss gleichwertig zur Annahme sein. BMW nutzt + # "Cookies verbieten", andere Sites "Tracking ablehnen" o.ae. — + # alle rechtlich gleichwertig. + explicit_reject_texts = [ + "ablehnen", "reject", "alle ablehnen", + "decline", "alles ablehnen", + "cookies verbieten", "cookies blockieren", + "tracking ablehnen", "tracking verbieten", + "zurueckweisen", "block all", "deny all", + "alle verweigern", "verweigern", + ] implicit_reject_texts = ["nur notwendige", "nur technisch", "nur essenzielle", "nur essentielle", "notwendige akzeptieren", "essential only", "only necessary",