feat(cookie): Finding 'vague_duration' — unkonkrete Speicherdauer

Flaggt Laufzeit-Angaben ohne konkrete Dauer/Kriterium ('dauerhaft', 'bis zur
Loeschung', 'bis Nutzer deaktiviert', 'unbegrenzt' …) — Art. 5(1)(e) + Art. 13
DSGVO. Library-unabhaengig, gilt fuer ALLE Cookies (Coverage auf BMWs 780).
'13 Monate'/'Session'/'bis Widerruf, max. X' bleiben ok.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-06-11 08:33:06 +02:00
parent d18ef79f18
commit 4c45f11e43
3 changed files with 58 additions and 0 deletions
@@ -53,6 +53,31 @@ _EEA = {
_SEV_ORDER = {"HIGH": 0, "MEDIUM": 1, "LOW": 2}
# Vage Laufzeit-Formulierungen — keine konkrete Speicherdauer i.S.v.
# Art. 5(1)(e) + Art. 13 DSGVO (User-Domain-Vorgabe 2026-06-11).
_VAGUE_DURATION = (
"dauerhaft", "bis zur löschung", "bis zur loeschung", "deaktiviert",
"unbegrenzt", "unbefristet", "solange erforderlich", "solange benötigt",
"unendlich", "permanent", "auf unbestimmte zeit", "kein ablauf",
"no expir", "persistent", "until deleted",
)
def _is_vague_duration(expiry: str) -> bool:
"""True, wenn die Angabe vage ist (keine konkrete Dauer/Session/Kriterium)."""
e = (expiry or "").strip().lower()
if not e:
return False
has_concrete = (
bool(re.search(r"\d+\s*(tag|woche|monat|jahr|stunde|minute|day|week|"
r"month|year|hour|min)", e))
or "session" in e
or "browser schließ" in e or "browser schliess" in e
or "schließen des browser" in e or "schliessen des browser" in e
)
return not has_concrete and any(p in e for p in _VAGUE_DURATION)
def _duration_days(s: str) -> int:
"""Grobe Normalisierung einer Laufzeit-Angabe in Tage (0 = Session)."""
s = (s or "").lower()
@@ -91,6 +116,20 @@ def analyze_cookies(vendors: list[dict], big_lib: dict | None = None) -> dict:
for c in v.get("cookies") or []:
checked += 1
name = c.get("name", "")
# Vage Speicherdauer — OHNE Library, gilt fuer ALLE Cookies.
if _is_vague_duration(c.get("expiry", "")):
findings.append({
"vendor": vname, "cookie": name, "type": "vague_duration",
"severity": "MEDIUM", "declared": c.get("expiry", ""),
"library_purpose": "",
"remediation": (
f"Speicherdauer von '{name}' ist nicht konkret angegeben "
f"('{c.get('expiry', '')}'). Art. 5 Abs. 1 lit. e + Art. 13 "
f"DSGVO verlangen eine konkrete Dauer oder nachvollziehbare "
f"Kriterien (z.B. '13 Monate', 'Session', 'bis Widerruf, "
f"max. 13 Monate')."
),
})
rich = lookup_cookie(name) or {}
big = big_lib.get(name.lower(), {})
if not rich and not big: