fix(audit): P98 + P100 — Cookie-Tabellen-Whitespace + Anpassen-Button-Check
CI / detect-changes (push) Successful in 11s
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / secret-scan (push) Has been skipped
CI / go-lint (push) Has been skipped
CI / validate-canonical-controls (push) Successful in 18s
CI / loc-budget (push) Failing after 17s
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / nodejs-build (push) Has been skipped
CI / test-go (push) Has been skipped
CI / iace-gt-coverage (push) Has been skipped
CI / test-python-backend (push) Has been skipped
CI / test-python-document-crawler (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped

P98: HTML-Tabellen-Zellen wurden bei VW-Cookie-Richtlinie ohne Whitespace
verkettet ('smartSignals2UiDsmartSignals2sUiDsmartSignals2CPs...'). Grund:
el.textContent ignoriert Block-Element-Grenzen. Fix: innerText (whitespace-
respecting) statt textContent. Cookie-Namen werden jetzt einzeln erkannt —
VW-Lauf sollte ~100 Cookies statt 1 finden.

P100: Banner-Check fuer 'Anpassen'/'Einstellungen'-Button im Initial-Banner.
VW-Pattern: nur 2 Buttons (Nur technisch notwendige / Alle akzeptieren),
keine granulare Wahl vor Akzeptanz/Ablehnung. Faktische Manipulation
Richtung Pauschal-Akzeptanz. HIGH-Finding nach EDPB 5/2020 §82.
Pattern: anpassen/einstellungen/cookie-einstellungen/manage cookies/
preferences/customize.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-05-21 15:08:33 +02:00
parent 50ed0f45af
commit 9c11b5463c
2 changed files with 37 additions and 3 deletions
@@ -196,6 +196,33 @@ async def check_banner_text(page) -> dict:
legal_ref="EDPB 5/2020 (Consent) + DSK-OH 2024 (Telemedien)",
))
# P100: Granular-Wahl-Pruefung — "Anpassen"/"Einstellungen"-Button
# im Initial-Banner. Wenn er FEHLT (VW-Pattern), ist die granulare
# Cookie-Wahl erst nach Akzeptanz/Ablehnung moeglich — faktische
# Manipulation Richtung "Alle akzeptieren". EDPB 5/2020 §82.
granular_button_texts = [
"anpassen", "einstellungen", "cookie-einstellungen",
"cookies verwalten", "manage cookies", "customize",
"weitere optionen", "more options", "settings",
"individuell", "detaillierte einstellungen",
"praeferenzen", "preferences",
]
has_granular_button = any(t in banner_lower for t in granular_button_texts)
if not has_granular_button:
violations.append(Violation(
service="Cookie-Banner",
severity="HIGH",
text="Granulare Cookie-Auswahl im Initial-Banner nicht "
"moeglich (kein 'Anpassen'/'Einstellungen'-Button). "
"Nutzer koennen nur 'Alle akzeptieren' oder 'Nur "
"technisch notwendige' waehlen — Detailwahl pro "
"Kategorie erst nach Akzeptanz/Ablehnung. Das ist "
"faktische Manipulation Richtung Pauschal-Akzeptanz.",
legal_ref="EDPB Guidelines 5/2020 §82 (granular consent), "
"§25 Abs. 1 TDDDG, Art. 4(11) DSGVO (informierte "
"Einwilligung)",
))
# Check 5: Pre-ticked checkboxes (EuGH Planet49)
try:
pre_checked = await page.evaluate("""
+10 -3
View File
@@ -506,14 +506,21 @@ async def discover_dsi_documents(
];
for (const sel of selectors) {
const el = document.querySelector(sel);
if (el && el.textContent.trim().length > 200) {
return el.textContent.trim();
if (el) {
// P98: innerText statt textContent — innerText
// respektiert Whitespace zwischen Block-Elementen.
// textContent verkettet HTML-Tabellen-Zellen ohne
// Spaces (VW-Cookie-Tabelle: ~100 Cookie-Namen
// wurden zu einem Klumpen "smartSignals2UiDsmartSignals2sUiD...").
const txt = (el.innerText || el.textContent || '').trim();
if (txt.length > 200) return txt;
}
}
// Fallback: full body minus nav/header/footer
const body = document.body.cloneNode(true);
body.querySelectorAll('nav, header, footer, script, style, [class*="nav"], [class*="sidebar"]').forEach(e => e.remove());
return body.textContent?.trim() || '';
// P98: innerText respektiert Whitespace (s.o.)
return (body.innerText || body.textContent || '').trim();
}
""")
if text and len(text) > 50: