@aegis-scan/skills 0.2.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/ATTRIBUTION.md +171 -4
  2. package/CHANGELOG.md +112 -1
  3. package/README.md +27 -0
  4. package/dist/skills-loader.d.ts +43 -0
  5. package/dist/skills-loader.d.ts.map +1 -1
  6. package/dist/skills-loader.js +102 -0
  7. package/dist/skills-loader.js.map +1 -1
  8. package/package.json +1 -1
  9. package/skills/compliance/_INDEX.md +49 -0
  10. package/skills/compliance/aegis-native/brutaler-anwalt/CHANGELOG.md +202 -0
  11. package/skills/compliance/aegis-native/brutaler-anwalt/LICENSE +43 -0
  12. package/skills/compliance/aegis-native/brutaler-anwalt/README.md +236 -0
  13. package/skills/compliance/aegis-native/brutaler-anwalt/SKILL.md +437 -6
  14. package/skills/compliance/aegis-native/brutaler-anwalt/references/aegis-integration.md +3 -4
  15. package/skills/compliance/aegis-native/brutaler-anwalt/references/audit-patterns.md +842 -5
  16. package/skills/compliance/aegis-native/brutaler-anwalt/references/bgh-urteile.md +226 -10
  17. package/skills/compliance/aegis-native/brutaler-anwalt/references/branchenrecht.md +365 -1
  18. package/skills/compliance/aegis-native/brutaler-anwalt/references/checklisten.md +33 -0
  19. package/skills/compliance/aegis-native/brutaler-anwalt/references/dsgvo.md +26 -0
  20. package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/BDSG/paragraphs.md +62 -0
  21. package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/BFSG/paragraphs.md +85 -0
  22. package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/BGB/paragraphs.md +112 -0
  23. package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/DDG/paragraphs.md +71 -0
  24. package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/DSGVO/articles.md +182 -0
  25. package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/AI-Act-2024-1689/articles.md +108 -0
  26. package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/DSA-2022-2065/articles.md +131 -0
  27. package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/HGB-AO/paragraphs.md +61 -0
  28. package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/INDEX.md +93 -0
  29. package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/TDDDG/paragraphs.md +67 -0
  30. package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/UWG/paragraphs.md +117 -0
  31. package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/VSBG/paragraphs.md +57 -0
  32. package/skills/compliance/aegis-native/brutaler-anwalt/references/it-recht.md +22 -0
  33. package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/INDEX.md +122 -0
  34. package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/ai/mistral-eu.md +123 -0
  35. package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/ai/openai-dpa.md +120 -0
  36. package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/auth/nextauth-tom.md +120 -0
  37. package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/auth/supabase-auth-tom.md +104 -0
  38. package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/nextjs/proxy-csp-pattern.md +93 -0
  39. package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/payment/stripe-pci-tom.md +121 -0
  40. package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/tracking/plausible-pattern.md +107 -0
  41. package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/AffiliateDisclaimer.tsx.example +54 -0
  42. package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/COMPLIANCE-AUDIT-TRAIL-template.md +95 -0
  43. package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/DSE-Section-UGC.md.example +77 -0
  44. package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/DSFA-template.md +76 -0
  45. package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/LostFoundReportForm-consent.tsx.example +126 -0
  46. package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/README.md +33 -0
  47. package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/UmamiScript.tsx.example +64 -0
  48. package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/VVT-template.md +60 -0
  49. package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/data-retention-cron.ts.example +52 -0
  50. package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/data-retention-workflow.yml.example +47 -0
  51. package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/proxy-strict-dynamic.ts.example +80 -0
  52. package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/security.txt.example +26 -0
  53. package/skills/compliance/aegis-native/brutaler-anwalt/scripts/health-check.sh +120 -0
  54. package/skills/defensive/aegis-native/rls-defense/SKILL.md +110 -0
  55. package/skills/defensive/aegis-native/tenant-isolation-defense/SKILL.md +26 -0
  56. package/skills/foundation/_INDEX.md +73 -0
  57. package/skills/foundation/aegis-native/aegis-audit/SKILL.md +194 -0
  58. package/skills/foundation/aegis-native/aegis-audit/references/layer-1-headers.md +138 -0
  59. package/skills/foundation/aegis-native/aegis-audit/references/layer-2-html.md +153 -0
  60. package/skills/foundation/aegis-native/aegis-audit/references/layer-3-impressum.md +159 -0
  61. package/skills/foundation/aegis-native/aegis-audit/references/layer-4-dse.md +178 -0
  62. package/skills/foundation/aegis-native/aegis-audit/references/layer-5-cookie.md +180 -0
  63. package/skills/foundation/aegis-native/aegis-audit/references/layer-6-branche.md +204 -0
  64. package/skills/foundation/aegis-native/aegis-audit/references/layer-7-code-cross-check.md +212 -0
  65. package/skills/foundation/aegis-native/aegis-audit/references/layer-8-schadens-diagnose.md +232 -0
  66. package/skills/foundation/aegis-native/aegis-customer-build/SKILL.md +232 -0
  67. package/skills/foundation/aegis-native/aegis-customer-build/references/phase-1-recon.md +147 -0
  68. package/skills/foundation/aegis-native/aegis-customer-build/references/phase-2-architecture.md +164 -0
  69. package/skills/foundation/aegis-native/aegis-customer-build/references/phase-3-component-build.md +231 -0
  70. package/skills/foundation/aegis-native/aegis-customer-build/references/phase-4-content.md +196 -0
  71. package/skills/foundation/aegis-native/aegis-customer-build/references/phase-5-integration.md +273 -0
  72. package/skills/foundation/aegis-native/aegis-customer-build/references/phase-6-mid-audit.md +200 -0
  73. package/skills/foundation/aegis-native/aegis-customer-build/references/phase-7-final-verify.md +258 -0
  74. package/skills/foundation/aegis-native/aegis-handover-writer/SKILL.md +128 -0
  75. package/skills/foundation/aegis-native/aegis-module-builder/SKILL.md +255 -0
  76. package/skills/foundation/aegis-native/aegis-orchestrator/SKILL.md +229 -0
  77. package/skills/foundation/aegis-native/aegis-quality-gates/SKILL.md +182 -0
  78. package/skills/foundation/aegis-native/aegis-skill-creator/SKILL.md +223 -0
  79. package/skills/foundation/aegis-native/aegis-skill-creator/references/hard-constraint-template.md +213 -0
  80. package/skills/foundation/aegis-native/aegis-skill-creator/references/skillforge-methodology.md +220 -0
  81. package/skills/foundation/aegis-native/dsgvo-compliance/SKILL.md +185 -0
  82. package/skills/foundation/aegis-native/dsgvo-compliance/references/art-13-15-templates.md +309 -0
  83. package/skills/foundation/aegis-native/dsgvo-compliance/references/datenpanne-runbook.md +291 -0
  84. package/skills/offensive/matty-fork/cicd-redteam/SKILL.md +531 -0
  85. package/skills/offensive/matty-fork/cloud-security/SKILL.md +106 -0
  86. package/skills/offensive/matty-fork/container-escape/SKILL.md +174 -0
  87. package/skills/offensive/matty-fork/mobile-pentester/SKILL.md +357 -0
  88. package/skills/offensive/matty-fork/subdomain-takeover/SKILL.md +154 -0
  89. package/skills/osint/elementalsouls-fork/offensive-osint/README.md +92 -0
  90. package/skills/osint/elementalsouls-fork/offensive-osint/SKILL.md +4177 -0
  91. package/skills/osint/elementalsouls-fork/osint-methodology/README.md +66 -0
  92. package/skills/osint/elementalsouls-fork/osint-methodology/SKILL.md +1695 -0
  93. package/sbom.cdx.json +0 -1
@@ -0,0 +1,159 @@
1
+ # Layer 3 Reference — Impressum (DDG §5)
2
+
3
+ Layer 3 verifies the Impressum (legal notice) per DDG §5 (formerly TMG §5, renamed 2024-05-14 with TDDDG enactment). Catches: missing pflichtangaben, broken links, browser-vs-bot-walled pages. **Time:** ~3-5 min per target.
4
+
5
+ ---
6
+
7
+ ## Pflichtangaben Checklist (DDG §5)
8
+
9
+ | # | Pflichtangabe | Field-name | Required when |
10
+ |---|---|---|---|
11
+ | 1 | Name + Anschrift | Geschäftsbezeichnung + Straße + PLZ + Ort | always (geschäftsmäßig) |
12
+ | 2 | Vertretungsberechtigter | Geschäftsführer (bei juristischen Personen) | for GmbH/AG/UG/etc. |
13
+ | 3 | Kontakt: E-Mail + Telefon | E-Mail + Tel. | always |
14
+ | 4 | Handelsregister | HRB-Nummer + Registergericht | for handelsregister-pflichtige Rechtsformen |
15
+ | 5 | Umsatzsteuer-ID | USt-IdNr. (`DE...`) | when § 27a UStG applies |
16
+ | 6 | Wirtschafts-ID | W-IdNr. | when applicable |
17
+ | 7 | Aufsichtsbehörde | Name + Adresse | for state-licensed industries (Anwalt, Arzt, Architekt, Steuerberater, ...) |
18
+ | 8 | Berufsbezeichnung + Kammer | Bezeichnung + verleihender Staat + Kammer | for regulated professions |
19
+ | 9 | Berufshaftpflicht | Versicherer + räumlicher Geltungsbereich | for regulated professions (Anwalt, Arzt, ...) |
20
+ | 10 | Online-Streitbeilegung Hinweis | Link zu ec.europa.eu/consumers/odr | for B2C with online-business |
21
+ | 11 | Verbraucherstreitbeilegung Hinweis | Bereit-/Nicht-Bereit-Erklärung | for B2C |
22
+ | 12 | Inhaltlich Verantwortlicher (§ 18 Abs. 2 MStV) | Name + Anschrift | for journalistic-redaktional Angebote |
23
+
24
+ ---
25
+
26
+ ## Probe Pattern
27
+
28
+ ```bash
29
+ # Resolve impressum-URL
30
+ IMPRESSUM_URL=$(node -e "
31
+ const html = require('fs').readFileSync('/tmp/audit-html-static.html', 'utf-8');
32
+ const match = html.match(/href=['\"]([^'\"]*impressum[^'\"]*)['\"]/i);
33
+ console.log(match ? new URL(match[1], '$TARGET').href : '');
34
+ ")
35
+
36
+ if [ -z "$IMPRESSUM_URL" ]; then
37
+ echo "L3-IMPRESSUM-NO-FOOTER-LINK: KRITISCH"
38
+ exit 1
39
+ fi
40
+
41
+ # Fetch with browser-UA (some sites bot-wall)
42
+ curl -sL -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" "$IMPRESSUM_URL" > /tmp/audit-impressum.html
43
+
44
+ # Or fall-back to Playwright
45
+ [ "$(wc -c < /tmp/audit-impressum.html)" -lt 1000 ] && {
46
+ npx -y playwright-core@latest <<EOF | tee /tmp/audit-impressum.html
47
+ const { chromium } = require('playwright-core');
48
+ (async () => {
49
+ const b = await chromium.launch();
50
+ const p = await (await b.newContext()).newPage();
51
+ await p.goto('$IMPRESSUM_URL', { waitUntil: 'networkidle' });
52
+ console.log(await p.content());
53
+ await b.close();
54
+ })();
55
+ EOF
56
+ }
57
+ ```
58
+
59
+ ---
60
+
61
+ ## Per-Field Detection Patterns
62
+
63
+ ```bash
64
+ # Geschäftsbezeichnung + Anschrift (presence check)
65
+ grep -E '(GmbH|UG|AG|e\.K\.|[A-ZÄÖÜ][a-zäöü]+ [A-ZÄÖÜ][a-zäöü]+)' /tmp/audit-impressum.html | head -3
66
+ grep -E '\b[0-9]{5}\b' /tmp/audit-impressum.html # German postal code
67
+
68
+ # E-Mail + Telefon
69
+ grep -oE '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' /tmp/audit-impressum.html | head -3
70
+ grep -oE '\+?49[ /-]?[0-9 /-]{7,}' /tmp/audit-impressum.html | head -3
71
+
72
+ # USt-IdNr.
73
+ grep -oE 'DE[ ]?[0-9]{9}' /tmp/audit-impressum.html
74
+
75
+ # Handelsregister
76
+ grep -oE 'HRB[ ]?[0-9]+' /tmp/audit-impressum.html
77
+ grep -oE 'Amtsgericht [A-ZÄÖÜ][a-zäöü]+' /tmp/audit-impressum.html
78
+
79
+ # OS-Streitbeilegung Link
80
+ grep -E 'ec\.europa\.eu/consumers/odr' /tmp/audit-impressum.html
81
+
82
+ # Verbraucherstreitbeilegung Hinweis
83
+ grep -E '(Verbraucherstreitbeilegung|Streitbeilegungsverfahren)' /tmp/audit-impressum.html
84
+ ```
85
+
86
+ ---
87
+
88
+ ## Severity Matrix
89
+
90
+ | Missing field | Severity |
91
+ |---|---|
92
+ | Geschäftsbezeichnung + Anschrift | KRITISCH |
93
+ | Vertretungsberechtigter (when GmbH/AG/UG) | KRITISCH |
94
+ | E-Mail | KRITISCH |
95
+ | Telefon | HOCH (some courts accept E-Mail-only; abmahn-risk) |
96
+ | HRB + Registergericht (when handelsregister-pflichtig) | KRITISCH |
97
+ | USt-IdNr. (when § 27a UStG applies) | KRITISCH |
98
+ | Aufsichtsbehörde (for regulated industries) | KRITISCH |
99
+ | Berufshaftpflicht (for regulated professions) | KRITISCH |
100
+ | OS-Streitbeilegung Link (when B2C online) | HOCH |
101
+ | Verbraucherstreitbeilegung Hinweis (B2C) | MITTEL |
102
+ | Inhaltlich Verantwortlicher (when journalistic) | KRITISCH |
103
+
104
+ ---
105
+
106
+ ## Cross-Check: Code-Repo (when Layer 7 enabled)
107
+
108
+ If aegis-audit runs against a local repo (Layer 7 enabled), cross-check:
109
+
110
+ ```bash
111
+ # Find impressum data in code
112
+ find . -path ./node_modules -prune -o -type f \( -name '*.ts' -o -name '*.tsx' -o -name '*.json' -o -name '*.md' \) -print | xargs grep -lE 'impressum|HRB|USt-IdNr' 2>/dev/null
113
+
114
+ # Verify code-data matches rendered-data
115
+ # E.g., site says HRB 12345 but code has HRB 67890 — drift
116
+ ```
117
+
118
+ If drift detected → L3-IMPRESSUM-CODE-DRIFT: HOCH (data inconsistency).
119
+
120
+ ---
121
+
122
+ ## Court-Decision References
123
+
124
+ For findings, cite court-decisions where applicable:
125
+
126
+ - KG Berlin 2010-04-21 (5 W 39/10) — vollständiger Name + Anschrift Pflicht
127
+ - LG Düsseldorf 2008-05-21 (12 O 250/07) — Telefon Pflicht für unmittelbare Kontaktaufnahme
128
+ - EuGH 2008-10-16 (C-298/07) — § 5 TMG (= jetzt DDG §5) ist Verbraucherinformations-Pflicht; B2B + B2C
129
+ - BGH 2007-09-20 (I ZR 88/05) — Impressum 2-clicks-rule (vom Footer aus erreichbar)
130
+ - LG München I 2022-01-20 (3 O 17493/20) — Google-Fonts (cross-layer with L4 + L5)
131
+
132
+ ---
133
+
134
+ ## Findings Format
135
+
136
+ ```yaml
137
+ - id: L3-IMPRESSUM-VAT-MISSING
138
+ layer: 3
139
+ severity: KRITISCH
140
+ evidence:
141
+ url: <impressum-url>
142
+ field: USt-IdNr.
143
+ matches: []
144
+ detection: "no DE-prefixed VAT-ID found in /impressum HTML"
145
+ recommendation: "Add 'Umsatzsteuer-Identifikationsnummer: DE123456789' under § 27a UStG section"
146
+ citation: "DDG § 5 Abs. 1 Nr. 6, § 27a UStG"
147
+ abmahn_risk: "€500-2000 per finding (industry × visibility-dependent)"
148
+ ```
149
+
150
+ ---
151
+
152
+ ## Anti-Patterns specific to Layer 3
153
+
154
+ - ❌ Reporting "USt-IdNr. missing" for a Kleinunternehmer (§ 19 UStG) — only § 27a UStG businesses need to publish.
155
+ - ❌ Reporting "OS-Streitbeilegung missing" for B2B-only sites — only B2C requires this.
156
+ - ❌ Skipping browser-UA fallback — many sites bot-wall scanners; without browser-UA the impressum returns 403.
157
+ - ❌ Inferring "Aufsichtsbehörde missing" without first detecting industry — non-regulated industries don't need this.
158
+ - ❌ Reporting on Inhaltlich-Verantwortlicher (§ 18 MStV) for non-journalistic sites — pure commercial sites don't need.
159
+ - ❌ Reporting "missing Berufshaftpflicht" for unregulated professions — pflicht only for Anwalt / Arzt / Steuerberater / Architekt.
@@ -0,0 +1,178 @@
1
+ # Layer 4 Reference — DSE (Datenschutzerklärung, DSGVO Art. 13/14)
2
+
3
+ Layer 4 verifies the Datenschutzerklärung against DSGVO Art. 13 (Informationspflicht bei Erhebung beim Betroffenen) + Art. 14 (Erhebung bei Dritten) + Drittlandtransfer-Konformität (Schrems-II / SCC). **Time:** ~5-10 min per target.
4
+
5
+ ---
6
+
7
+ ## Art. 13 Pflichtangaben Checklist
8
+
9
+ | # | Field | Severity if missing |
10
+ |---|---|---|
11
+ | 1 | Verantwortlicher (Name + Anschrift) | KRITISCH |
12
+ | 2 | Vertreter in der EU (when applicable) | HOCH |
13
+ | 3 | Datenschutzbeauftragter (when applicable per Art. 37) | HOCH (when pflicht) |
14
+ | 4 | Verarbeitungszwecke + Rechtsgrundlage (Art. 6 / Art. 9) | KRITISCH |
15
+ | 5 | Berechtigte Interessen (when Art. 6 Abs. 1 lit. f) | HOCH |
16
+ | 6 | Empfänger / Empfängerkategorien | HOCH |
17
+ | 7 | Drittlandtransfer + Schutzgarantien | KRITISCH (when transfer happens but DSE absent) |
18
+ | 8 | Speicherdauer / Löschkonzept | HOCH |
19
+ | 9 | Betroffenenrechte (Art. 15-22) | KRITISCH |
20
+ | 10 | Beschwerderecht bei Aufsichtsbehörde | HOCH |
21
+ | 11 | Pflicht zur Bereitstellung + Folgen | MITTEL |
22
+ | 12 | Automatisierte Entscheidung / Profiling | HOCH (when applicable) |
23
+
24
+ ---
25
+
26
+ ## Probe Pattern
27
+
28
+ ```bash
29
+ # Resolve DSE-URL (often /datenschutz, /privacy, /datenschutzerklaerung)
30
+ DSE_URL=$(node -e "
31
+ const html = require('fs').readFileSync('/tmp/audit-html-static.html', 'utf-8');
32
+ const match = html.match(/href=['\"]([^'\"]*(datenschutz|privacy)[^'\"]*)['\"]/i);
33
+ console.log(match ? new URL(match[1], '$TARGET').href : '');
34
+ ")
35
+
36
+ curl -sL -A "Mozilla/5.0" "$DSE_URL" > /tmp/audit-dse.html
37
+ ```
38
+
39
+ ---
40
+
41
+ ## Per-Field Detection Patterns
42
+
43
+ ```bash
44
+ # Verantwortlicher (matches typical phrasing)
45
+ grep -E 'Verantwortliche[r]?\s+i[mn]?\s+Sinne' /tmp/audit-dse.html
46
+
47
+ # Datenschutzbeauftragter
48
+ grep -iE '(Datenschutzbeauftragte[rn]|Data Protection Officer|DSB)' /tmp/audit-dse.html
49
+
50
+ # Verarbeitungszwecke (look for Art. 6 references)
51
+ grep -E 'Art\.\s*6\s*Abs\.\s*1\s*lit\.\s*[abcdef]' /tmp/audit-dse.html
52
+
53
+ # Drittlandtransfer (US, GB post-Brexit)
54
+ grep -iE '(Drittland|USA|United States|Standardvertragsklauseln|SCC|Privacy Shield|TIA)' /tmp/audit-dse.html
55
+
56
+ # Speicherdauer
57
+ grep -iE '(Speicherdauer|Löschkonzept|Aufbewahrungsfrist)' /tmp/audit-dse.html
58
+
59
+ # Betroffenenrechte (Art. 15-22)
60
+ grep -E 'Art\.\s*1[5-9]|Art\.\s*2[0-2]' /tmp/audit-dse.html
61
+ grep -iE '(Auskunftsrecht|Berichtigung|Löschung|Einschränkung|Datenübertragbarkeit|Widerspruch)' /tmp/audit-dse.html
62
+
63
+ # Beschwerderecht
64
+ grep -iE '(Beschwerderecht|Aufsichtsbehörde|Datenschutzbeauftragte des Landes)' /tmp/audit-dse.html
65
+ ```
66
+
67
+ ---
68
+
69
+ ## Drittland-Transfer Detection (cross-check Layer 1 + Layer 5)
70
+
71
+ Layer 4 cross-references with Layer 1 (CDN / 3rd-party domains in HTTP-headers) + Layer 5 (cookies set by 3rd-party trackers) to detect:
72
+
73
+ ```bash
74
+ # 3rd-party domains active on the page (from Layer 1 / Layer 5)
75
+ 3p_domains=$(grep -oE 'https?://[^/]+' /tmp/audit-html-dynamic.html | sort -u | grep -v "$TARGET_DOMAIN")
76
+
77
+ # For each 3rd-party, check if DSE mentions it
78
+ for domain in $3p_domains; do
79
+ if grep -q "$domain" /tmp/audit-dse.html; then
80
+ echo "L4-DSE-MENTIONS: $domain ✓"
81
+ else
82
+ echo "L4-DSE-3P-NOT-MENTIONED: $domain (HOCH)"
83
+ fi
84
+ done
85
+ ```
86
+
87
+ US-headquartered 3rd-parties (Google, Meta, Cloudflare, AWS) trigger Drittlandtransfer concerns. DSE MUST mention:
88
+
89
+ - The 3rd-party (by name or category)
90
+ - The country of transfer
91
+ - The schutzgarantien (SCC + TIA per Schrems-II requirements post-2020-07-16 EuGH C-311/18)
92
+
93
+ If 3rd-party transfer happens AND DSE doesn't address it → KRITISCH (Schrems-II).
94
+
95
+ ---
96
+
97
+ ## Common Schrems-II Findings
98
+
99
+ | 3rd-party | DSE-required addressing |
100
+ |---|---|
101
+ | Google Fonts (when loaded from fonts.googleapis.com) | KRITISCH if not local-bundled (LG München I 2022-01-20 3 O 17493/20) |
102
+ | Google Analytics (without IP-anonymization + consent) | KRITISCH |
103
+ | Google Maps embed (without consent OR static-image-fallback) | HOCH |
104
+ | reCAPTCHA v3 (silent tracking) | KRITISCH |
105
+ | Cloudflare (when used as CDN with EU-traffic) | MITTEL (DPA exists; SCC referenced) |
106
+ | AWS / Azure / GCP (US-region) | HOCH (require SCC-DPA) |
107
+ | Vercel (US-hosted) | MITTEL (Vercel offers DPA) |
108
+ | Mailchimp / Sendinblue / Brevo | HOCH (US/EU split, requires SCC) |
109
+
110
+ For each, check if DSE has the required transfer-section AND processor-AVV (Auftragsverarbeitung) listing.
111
+
112
+ ---
113
+
114
+ ## AVV-List Detection
115
+
116
+ DSGVO Art. 28 requires AVV (Auftragsverarbeitung-Vertrag) for every processor handling personal data. DSE should reference:
117
+
118
+ ```bash
119
+ grep -iE '(Auftragsverarbeitung|Art\.\s*28|AVV)' /tmp/audit-dse.html
120
+ ```
121
+
122
+ For each 3rd-party from Layer 1 + 5: AVV must exist (signed contract); DSE should mention by name.
123
+
124
+ ---
125
+
126
+ ## Severity Matrix
127
+
128
+ | Missing | Severity |
129
+ |---|---|
130
+ | Verantwortlicher (Art. 13 Abs. 1 lit. a) | KRITISCH |
131
+ | Verarbeitungszwecke + Rechtsgrundlage (Art. 13 Abs. 1 lit. c-d) | KRITISCH |
132
+ | Betroffenenrechte (Art. 15-22) | KRITISCH |
133
+ | Drittlandtransfer + SCC + TIA (when transfer happens) | KRITISCH |
134
+ | Speicherdauer (Art. 13 Abs. 2 lit. a) | HOCH |
135
+ | Empfänger (Art. 13 Abs. 1 lit. e) | HOCH |
136
+ | Beschwerderecht (Art. 13 Abs. 2 lit. d) | HOCH |
137
+ | Datenschutzbeauftragter (when pflicht per Art. 37) | HOCH |
138
+ | Vertreter in der EU (when ext.-EU controller) | HOCH |
139
+ | Automatisierte Entscheidung (when applicable) | HOCH |
140
+ | Pflicht zur Bereitstellung (Art. 13 Abs. 2 lit. e) | MITTEL |
141
+
142
+ ---
143
+
144
+ ## Court-Decision References
145
+
146
+ - EuGH 2020-07-16 (C-311/18) — Schrems-II — invalidation of Privacy Shield; SCC + TIA required
147
+ - LG München I 2022-01-20 (3 O 17493/20) — Google-Fonts via Google CDN = Drittlandtransfer ohne Rechtsgrundlage; 100€ Schadensersatz pro Betroffenem
148
+ - BGH 2020-05-28 (I ZR 7/16) — Cookie-Banner BGB
149
+ - OLG Düsseldorf 2019-03-26 (I-20 U 75/18) — DSE als wettbewerbsrechtliche Pflicht (UWG abmahnbar)
150
+ - EDSA Recommendations 01/2020 — Schutzgarantien-Beurteilung TIA-Methodik
151
+
152
+ ---
153
+
154
+ ## Findings Format
155
+
156
+ ```yaml
157
+ - id: L4-DSE-DRITTLAND-MISSING
158
+ layer: 4
159
+ severity: KRITISCH
160
+ evidence:
161
+ dse_url: <dse-url>
162
+ detected_3p: ["fonts.googleapis.com", "www.google-analytics.com"]
163
+ dse_mentions_drittland: false
164
+ dse_mentions_scc: false
165
+ recommendation: "Add Drittlandtransfer-section listing US-3rd-parties (Google Fonts, GA), reference SCC + TIA per Schrems-II"
166
+ citation: "DSGVO Art. 13 Abs. 1 lit. f, Art. 46; EuGH C-311/18 (Schrems-II); LG München I 3 O 17493/20"
167
+ abmahn_risk: "€2000-15000 per Betroffenem (LG München-Linie); aggregated risk per visitor-month"
168
+ ```
169
+
170
+ ---
171
+
172
+ ## Anti-Patterns specific to Layer 4
173
+
174
+ - ❌ Reporting "Drittlandtransfer missing" without verifying transfer actually happens — first detect 3rd-parties via Layer 1 + 5.
175
+ - ❌ Skipping AVV-cross-check — Art. 28 AVV is separate from Art. 13 DSE.
176
+ - ❌ Reporting "DSB missing" for small businesses (< 20 employees handling personal data routinely) — Art. 37 thresholds apply.
177
+ - ❌ Inferring DSE-completeness from word-count — short DSE can be complete; long DSE can miss fields.
178
+ - ❌ Reporting on automatisierte Entscheidung when site has no profiling — only applies when profiling/decisions actually happen.
@@ -0,0 +1,180 @@
1
+ # Layer 5 Reference — Cookie + Consent (TTDSG/TDDDG §25)
2
+
3
+ Layer 5 verifies cookie-banner + consent-flow against TTDSG/TDDDG §25 (formerly TTDSG, renamed 2024-05-14 with TDDDG enactment) + BGH cookie-decision (2020-05-28) + EU-Cookie-Banner-Guidelines. **Time:** ~5-10 min per target.
4
+
5
+ ---
6
+
7
+ ## Probe Pattern
8
+
9
+ ```bash
10
+ # Fresh page-load (no prior consent-cookies)
11
+ mkdir -p /tmp/audit-cookie-jar
12
+ rm -f /tmp/audit-cookie-jar/*
13
+ curl -sL -A "Mozilla/5.0" -c /tmp/audit-cookie-jar/cookies.txt "$TARGET" > /tmp/audit-fresh.html
14
+
15
+ # What cookies were set BEFORE consent?
16
+ cat /tmp/audit-cookie-jar/cookies.txt
17
+ ```
18
+
19
+ Then a Playwright-based probe to detect dynamic cookies (set by JS) AND verify the consent-banner appears + works:
20
+
21
+ ```bash
22
+ npx -y playwright-core@latest <<EOF
23
+ const { chromium } = require('playwright-core');
24
+ (async () => {
25
+ const b = await chromium.launch();
26
+ const ctx = await b.newContext();
27
+ const p = await ctx.newPage();
28
+
29
+ // Capture all requests + responses
30
+ const requests = [];
31
+ p.on('request', r => requests.push({ url: r.url(), type: r.resourceType() }));
32
+
33
+ // Navigate
34
+ await p.goto('$TARGET', { waitUntil: 'networkidle' });
35
+
36
+ // Capture cookies pre-consent
37
+ const preConsentCookies = await ctx.cookies();
38
+
39
+ // Check for consent-banner
40
+ const bannerSelector = 'div[id*="cookie"], div[class*="cookie"], div[class*="consent"]';
41
+ const banner = await p.$(bannerSelector);
42
+ const bannerHasBoth = banner ? await banner.evaluate(el => {
43
+ const text = el.innerText.toLowerCase();
44
+ return text.includes('akzeptieren') && (text.includes('ablehnen') || text.includes('reject'));
45
+ }) : false;
46
+
47
+ console.log(JSON.stringify({
48
+ preConsentCookies,
49
+ requests: requests.length,
50
+ bannerPresent: !!banner,
51
+ bannerHasBoth,
52
+ }, null, 2));
53
+
54
+ await b.close();
55
+ })();
56
+ EOF > /tmp/audit-cookie-probe.json
57
+ ```
58
+
59
+ ---
60
+
61
+ ## TTDSG/TDDDG §25 Pre-Consent-Tracker Detection
62
+
63
+ ```bash
64
+ # Pre-consent cookies (any technically-non-required cookie set before consent = §25 violation)
65
+ pre_count=$(jq -r '.preConsentCookies | length' /tmp/audit-cookie-probe.json)
66
+
67
+ # Filter for tracking-cookies (heuristic: 3rd-party domain or known-tracking-pattern)
68
+ tracking_pre=$(jq -r '.preConsentCookies[] | select(.domain | test("google|facebook|meta|doubleclick|hotjar|matomo|fathom|plausible|gtag|gads|fb_pixel|tiktok"))' /tmp/audit-cookie-probe.json)
69
+
70
+ [ -n "$tracking_pre" ] && echo "L5-PRE-CONSENT-TRACKER: KRITISCH"
71
+ ```
72
+
73
+ ---
74
+
75
+ ## Banner-Pattern Compliance
76
+
77
+ | Check | Severity if violated |
78
+ |---|---|
79
+ | Banner appears on first page-load | KRITISCH (no banner = no consent collected) |
80
+ | Banner has equal-prominence "Accept" + "Reject all" | KRITISCH (BGH I ZR 7/16 — dark-pattern) |
81
+ | Banner is granular (per-vendor opt-in for non-essential) | HOCH (BGH 2020-05-28 — global-opt-in invalid) |
82
+ | Banner appears BEFORE any tracking-cookie set | KRITISCH (TTDSG §25) |
83
+ | User can opt-out at any time (e.g., footer-link to /cookies/einstellungen) | HOCH |
84
+ | Pre-checked checkboxes for opt-in | KRITISCH (DSGVO Art. 7 Abs. 2 — explicit consent required) |
85
+ | Bundling consent (e.g., AGB + Cookie consent in one checkbox) | HOCH |
86
+ | Continuing-to-use-site interpreted as consent | KRITISCH (BGH 2020-05-28 — mere browsing ≠ consent) |
87
+ | Re-prompt period reasonable (≥ 6 months between prompts unless settings changed) | LOW |
88
+
89
+ ---
90
+
91
+ ## Granular vs Global
92
+
93
+ | Pattern | Compliance |
94
+ |---|---|
95
+ | "Akzeptieren" + "Ablehnen" only (no granular) | HOCH (BGH-line — granular better) |
96
+ | "Akzeptieren" + "Ablehnen" + per-vendor toggle | OK (granular) |
97
+ | "Akzeptieren" + "Einstellungen" (where settings = granular) | OK if reachable in 1 click |
98
+ | "Akzeptieren" + tiny "Ablehnen" (visual asymmetry) | KRITISCH (dark-pattern, BGH-line) |
99
+ | "Akzeptieren" only (no reject-button on first banner) | KRITISCH |
100
+
101
+ ---
102
+
103
+ ## Consent-Mode-v2 (Google) Detection
104
+
105
+ If site uses Google products (Analytics, Ads, Tag Manager), check for Consent-Mode-v2:
106
+
107
+ ```bash
108
+ grep -E 'gtag\(.consent.,\s*.default.|consentDefault' /tmp/audit-fresh.html
109
+
110
+ # default state should be 'denied' for ad_storage, ad_user_data, ad_personalization, analytics_storage
111
+ ```
112
+
113
+ Default-`granted` for analytics_storage = pre-consent-tracking even with Consent-Mode = KRITISCH.
114
+
115
+ ---
116
+
117
+ ## Cookie-Categories Mapping
118
+
119
+ For each cookie set on the site, classify:
120
+
121
+ | Category | Consent-required | Examples |
122
+ |---|---|---|
123
+ | Strictly necessary | NO | session-id, csrf-token, cookie-consent-state |
124
+ | Functional | Implicitly OK | language-preference, theme |
125
+ | Analytics (anonymized) | YES (per §25) | matomo (with anonymize_ip), google-analytics-with-anonymize |
126
+ | Marketing / Advertising | YES (explicit, granular) | _ga, _gid (without anonymize_ip), _fbp, fr, doubleclick |
127
+ | Third-party content | YES (depending on data) | YouTube embed, Google Maps with API-key |
128
+
129
+ If a cookie is "Strictly necessary" — must be on a justified business-need; not just "we want it".
130
+
131
+ ---
132
+
133
+ ## Cookie-Banner-Library Detection
134
+
135
+ ```bash
136
+ # Common libraries used on DACH sites
137
+ grep -iE '(usercentrics|cookiefirst|cookieyes|borlabs|webcm|consent-manager|onetrust|cookiepro|privacymanager|cookieinformation|complianz|iubenda)' /tmp/audit-fresh.html | head -3
138
+ ```
139
+
140
+ If a recognized library is used — check its current-version compliance (via library-CHANGELOG cross-reference; e.g., Borlabs Cookie ≥ 2.2.0 is compliant; older versions had known dark-pattern bugs).
141
+
142
+ ---
143
+
144
+ ## CMP IAB-Framework Detection
145
+
146
+ ```bash
147
+ # IAB-TCF-API presence
148
+ grep -E '__tcfapi\(|TCF_API|cmp\.openWindow' /tmp/audit-fresh.html
149
+ ```
150
+
151
+ If TCF-v2 used — verify Vendor-List up-to-date + Purposes match what's actually loaded.
152
+
153
+ ---
154
+
155
+ ## Findings Format
156
+
157
+ ```yaml
158
+ - id: L5-PRE-CONSENT-TRACKER
159
+ layer: 5
160
+ severity: KRITISCH
161
+ evidence:
162
+ target: <target>
163
+ pre_consent_cookies: ["_ga", "_gid", "_fbp"]
164
+ banner_present: true
165
+ banner_appears_after_load: true # but cookies were already set
166
+ recommendation: "Move all tracking-cookies behind cookie-banner consent. Use Google Consent-Mode-v2 with default='denied'. Verify with fresh page-load + cookies.txt empty."
167
+ citation: "TTDSG/TDDDG §25 Abs. 1; DSGVO Art. 7 Abs. 1; BGH I ZR 7/16 (2020-05-28); EuGH C-673/17 (Planet49)"
168
+ abmahn_risk: "€500-5000 per finding (industry × visibility); composite with L4-DSE-DRITTLAND-MISSING bumps to €5000-15000"
169
+ ```
170
+
171
+ ---
172
+
173
+ ## Anti-Patterns specific to Layer 5
174
+
175
+ - ❌ Probing with stale cookie-jar — always use fresh /tmp/audit-cookie-jar.
176
+ - ❌ Skipping Playwright probe "because curl is enough" — JS-set cookies invisible to curl.
177
+ - ❌ Reporting "no banner" for sites with technically-only cookies (no consent-required) — first verify what cookies are actually set.
178
+ - ❌ Marking "_ga" as KRITISCH if site uses Consent-Mode-v2 with default-denied — first check the consent-default-state.
179
+ - ❌ Reporting "global opt-in invalid" without checking BGH-line context — granular is preferred but global-only is HOCH not KRITISCH per current BGH-Linie.
180
+ - ❌ Inferring tracking-cookie from name alone — verify domain + actual purpose; some "_ga"-prefixed cookies are 1st-party-only.