@slashgear/gdpr-cookie-scanner 2.0.4 → 3.1.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.
- package/.github/workflows/update-trackers.yml +95 -0
- package/CHANGELOG.md +102 -0
- package/CLAUDE.md +1 -1
- package/README.md +78 -5
- package/dist/analyzers/compliance.d.ts.map +1 -1
- package/dist/analyzers/compliance.js +52 -9
- package/dist/analyzers/compliance.js.map +1 -1
- package/dist/classifiers/cookie-classifier.d.ts.map +1 -1
- package/dist/classifiers/cookie-classifier.js +2 -1
- package/dist/classifiers/cookie-classifier.js.map +1 -1
- package/dist/classifiers/network-classifier.d.ts +1 -0
- package/dist/classifiers/network-classifier.d.ts.map +1 -1
- package/dist/classifiers/network-classifier.js +10 -1
- package/dist/classifiers/network-classifier.js.map +1 -1
- package/dist/classifiers/tracker-list.d.ts +1 -0
- package/dist/classifiers/tracker-list.d.ts.map +1 -1
- package/dist/classifiers/tracker-list.js +7 -1
- package/dist/classifiers/tracker-list.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +51 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/dist/report/generator.d.ts.map +1 -1
- package/dist/report/generator.js +82 -41
- package/dist/report/generator.js.map +1 -1
- package/dist/scanner/index.js +4 -4
- package/dist/scanner/index.js.map +1 -1
- package/dist/scanner/network.d.ts.map +1 -1
- package/dist/scanner/network.js +1 -0
- package/dist/scanner/network.js.map +1 -1
- package/dist/types.d.ts +2 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +11 -2
- package/scripts/update-trackers.ts +273 -0
- package/src/analyzers/compliance.ts +54 -11
- package/src/classifiers/cookie-classifier.ts +2 -1
- package/src/classifiers/network-classifier.ts +11 -1
- package/src/classifiers/tracker-list.ts +9 -1
- package/src/cli.ts +1 -5
- package/src/index.ts +87 -0
- package/src/report/generator.ts +83 -44
- package/src/scanner/index.ts +4 -4
- package/src/scanner/network.ts +1 -0
- package/src/types.ts +2 -1
- package/tests/analyzers/compliance.test.ts +489 -0
- package/tests/analyzers/wording.test.ts +160 -0
- package/tests/classifiers/cookie-classifier.test.ts +270 -0
- package/tests/classifiers/network-classifier.test.ts +140 -0
- package/tests/e2e/scanner.test.ts +4 -7
- package/tests/unit/compliance.test.ts +99 -13
- package/tests/unit/network-classifier.test.ts +27 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
name: Update Tracker DB
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
# 1st of every month at 04:00 UTC
|
|
6
|
+
- cron: "0 4 1 * *"
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
update:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
permissions:
|
|
13
|
+
contents: write
|
|
14
|
+
pull-requests: write
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v6
|
|
18
|
+
|
|
19
|
+
- uses: pnpm/action-setup@v4
|
|
20
|
+
with:
|
|
21
|
+
version: latest
|
|
22
|
+
|
|
23
|
+
- uses: actions/setup-node@v4
|
|
24
|
+
with:
|
|
25
|
+
node-version: 24
|
|
26
|
+
cache: pnpm
|
|
27
|
+
|
|
28
|
+
- name: Install dependencies
|
|
29
|
+
run: pnpm install --frozen-lockfile
|
|
30
|
+
|
|
31
|
+
- name: Fetch & merge tracker lists
|
|
32
|
+
run: pnpm update-trackers
|
|
33
|
+
|
|
34
|
+
- name: Detect changes
|
|
35
|
+
id: diff
|
|
36
|
+
run: |
|
|
37
|
+
git diff --quiet src/classifiers/tracker-list.ts \
|
|
38
|
+
&& echo "changed=false" >> "$GITHUB_OUTPUT" \
|
|
39
|
+
|| echo "changed=true" >> "$GITHUB_OUTPUT"
|
|
40
|
+
|
|
41
|
+
- name: Format
|
|
42
|
+
if: steps.diff.outputs.changed == 'true'
|
|
43
|
+
run: pnpm format
|
|
44
|
+
|
|
45
|
+
- name: Type-check
|
|
46
|
+
if: steps.diff.outputs.changed == 'true'
|
|
47
|
+
run: pnpm typecheck
|
|
48
|
+
|
|
49
|
+
- name: Create PR
|
|
50
|
+
if: steps.diff.outputs.changed == 'true'
|
|
51
|
+
env:
|
|
52
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
53
|
+
run: |
|
|
54
|
+
BRANCH="chore/tracker-db-$(date +%Y%m)"
|
|
55
|
+
DATE="$(date +%Y-%m-%d)"
|
|
56
|
+
SLUG="tracker-db-update-${DATE}"
|
|
57
|
+
|
|
58
|
+
git config user.name "github-actions[bot]"
|
|
59
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
60
|
+
git checkout -b "$BRANCH"
|
|
61
|
+
|
|
62
|
+
# Write changeset
|
|
63
|
+
cat > ".changeset/${SLUG}.md" << EOF
|
|
64
|
+
---
|
|
65
|
+
"@slashgear/gdpr-cookie-scanner": patch
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
chore: monthly tracker DB update from Disconnect.me and DuckDuckGo Tracker Radar
|
|
69
|
+
EOF
|
|
70
|
+
|
|
71
|
+
git add src/classifiers/tracker-list.ts ".changeset/${SLUG}.md"
|
|
72
|
+
git commit -m "chore: update tracker DB from Disconnect.me and DuckDuckGo Tracker Radar"
|
|
73
|
+
git push origin "$BRANCH"
|
|
74
|
+
|
|
75
|
+
gh pr create \
|
|
76
|
+
--title "chore: monthly tracker DB update ($(date +%B %Y))" \
|
|
77
|
+
--body "$(cat <<'BODY'
|
|
78
|
+
## Summary
|
|
79
|
+
|
|
80
|
+
Automated monthly update of `src/classifiers/tracker-list.ts`.
|
|
81
|
+
|
|
82
|
+
- **Sources**: [Disconnect.me](https://github.com/disconnectme/disconnect-tracking-protection) · [DuckDuckGo Tracker Radar](https://github.com/duckduckgo/tracker-radar)
|
|
83
|
+
- Manually curated entries and `consentRequired: false` overrides are preserved unchanged.
|
|
84
|
+
- New entries are appended in the `AUTO-GENERATED` section (prevalence ≥ 0.1 %).
|
|
85
|
+
|
|
86
|
+
## Test plan
|
|
87
|
+
|
|
88
|
+
- [ ] `pnpm typecheck` passes (validated by CI)
|
|
89
|
+
- [ ] Review the diff in `tracker-list.ts` for obviously incorrect category assignments
|
|
90
|
+
- [ ] Spot-check 2–3 new domains against their actual tracker type
|
|
91
|
+
|
|
92
|
+
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
|
93
|
+
BODY
|
|
94
|
+
)" \
|
|
95
|
+
--base main
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,107 @@
|
|
|
1
1
|
# @slashgear/gdpr-cookie-scanner
|
|
2
2
|
|
|
3
|
+
## 3.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 305c80d: Add programmatic API (`scan()` function and public exports)
|
|
8
|
+
|
|
9
|
+
Exposes a `scan(url, options?)` convenience function and re-exports `Scanner`, `ReportGenerator`, and all public TypeScript types from the package entry point (`dist/index.js`).
|
|
10
|
+
|
|
11
|
+
This allows using the scanner as a library without going through the CLI:
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { scan, ReportGenerator } from "@slashgear/gdpr-cookie-scanner";
|
|
15
|
+
|
|
16
|
+
const result = await scan("https://example.com", { locale: "fr-FR" });
|
|
17
|
+
console.log(result.compliance.grade);
|
|
18
|
+
|
|
19
|
+
// Optionally generate a report
|
|
20
|
+
const generator = new ReportGenerator({
|
|
21
|
+
outputDir: "./reports",
|
|
22
|
+
formats: ["html"],
|
|
23
|
+
...result,
|
|
24
|
+
});
|
|
25
|
+
const paths = await generator.generate(result);
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`ScanOptions.outputDir` is now optional: it is only required when screenshots or report generation is needed. `ReportGenerator.generate()` throws a clear error if called without `outputDir`.
|
|
29
|
+
|
|
30
|
+
- cd4d616: feat: add automated tracker DB update script
|
|
31
|
+
|
|
32
|
+
Adds `scripts/update-trackers.ts`, a maintenance script that fetches
|
|
33
|
+
Disconnect.me and DuckDuckGo Tracker Radar and merges new tracker entries
|
|
34
|
+
into `src/classifiers/tracker-list.ts`. Manually curated entries (including
|
|
35
|
+
`consentRequired: false` overrides like Plausible) are preserved as-is; only
|
|
36
|
+
previously unknown domains are appended in a clearly delimited auto-generated
|
|
37
|
+
section.
|
|
38
|
+
|
|
39
|
+
Also adds a monthly GitHub Actions workflow (`.github/workflows/update-trackers.yml`)
|
|
40
|
+
that runs the script automatically and opens a PR when new trackers are found.
|
|
41
|
+
|
|
42
|
+
### Patch Changes
|
|
43
|
+
|
|
44
|
+
- 578a778: Wire `contrastRatio` into compliance scoring (section B — Easy Refusal).
|
|
45
|
+
|
|
46
|
+
The contrast ratio was already computed and displayed in reports but had no effect on the score. A "Refuser" button rendered in grey on white would silently pass. Now:
|
|
47
|
+
|
|
48
|
+
- Reject button contrast < 3.0 → critical issue, −10 pts
|
|
49
|
+
- Reject button contrast < 4.5 (WCAG AA) → warning, −5 pts
|
|
50
|
+
- Accept contrast ≥ 1.5× reject contrast → relative asymmetry warning, −3 pts
|
|
51
|
+
|
|
52
|
+
- 6113643: Add unit test suite (224 tests) and fix two classifier bugs
|
|
53
|
+
|
|
54
|
+
Introduces a full vitest test suite covering the four pure-function modules:
|
|
55
|
+
`cookie-classifier`, `network-classifier`, `wording` analyzer, and `compliance` analyzer.
|
|
56
|
+
|
|
57
|
+
Two production bugs were discovered and fixed in the process:
|
|
58
|
+
|
|
59
|
+
- **`cookie-classifier`**: the YouTube pattern `^(yt-|VISITOR_INFO|YSC|GPS)$` used a `$` anchor
|
|
60
|
+
that prevented `VISITOR_INFO1_LIVE` (the real cookie name) from matching. Split into two
|
|
61
|
+
entries so `VISITOR_INFO` is matched as a prefix.
|
|
62
|
+
- **`tracker-list`**: the entry `"facebook.com/tr"` included a URL path, making it unmatchable
|
|
63
|
+
by the hostname-only classifier. Replaced with the dedicated `pixel.facebook.com` hostname.
|
|
64
|
+
|
|
65
|
+
## 3.0.0
|
|
66
|
+
|
|
67
|
+
### Major Changes
|
|
68
|
+
|
|
69
|
+
- db3e538: Change the default output format from `md,pdf` to `html`.
|
|
70
|
+
|
|
71
|
+
Previously running `gdpr-scan scan <url>` with no `--format` flag produced both a Markdown bundle (3 files) and a PDF — requiring a full Playwright PDF render on every invocation. The HTML report is self-contained, opens in any browser without extra tooling, and is faster to generate, making it a better default for first-time users and CI pipelines alike. Pipelines that relied on the implicit `md` or `pdf` output must now pass `--format md,pdf` explicitly.
|
|
72
|
+
|
|
73
|
+
Also fixes the erroneous `npx` invocation in the README (issue #22): the correct command is `npx @slashgear/gdpr-cookie-scanner scan <url>`, not `npx @slashgear/gdpr-cookie-scanner gdpr-scan scan <url>`.
|
|
74
|
+
|
|
75
|
+
### Minor Changes
|
|
76
|
+
|
|
77
|
+
- db3e538: Add `requiresConsent` field to `NetworkRequest`, mark Plausible Analytics as consent-exempt, and fix scoring for tracking-free sites.
|
|
78
|
+
|
|
79
|
+
Two related issues are fixed:
|
|
80
|
+
|
|
81
|
+
1. **Plausible Analytics false positive** — Plausible is cookieless and exempt from ePrivacy consent under CNIL guidance, but requests to `plausible.io/api/event` were matching the generic pixel pattern and penalising the score. A `requiresConsent: boolean` field is added to `NetworkRequest` (mirroring the same field on `ScannedCookie`). A new optional `consentRequired` flag on `TrackerEntry` lets known-exempt services opt out of the default consent requirement. All compliance and report logic now uses `requiresConsent` instead of testing `trackerCategory !== "cdn"` directly. Plausible Analytics is added to `TRACKER_DB` with `consentRequired: false`.
|
|
82
|
+
|
|
83
|
+
2. **Tracking-free sites capped at 97** — The "no privacy policy link on page" check deducted 3 points unconditionally, even when no consent was required. A site with no non-essential cookies or trackers now correctly scores 100/100.
|
|
84
|
+
|
|
85
|
+
### Patch Changes
|
|
86
|
+
|
|
87
|
+
- 5f0e14e: Fix false non-compliance for sites with no cookies or trackers
|
|
88
|
+
|
|
89
|
+
A site with no consent modal but also no non-essential cookies and no
|
|
90
|
+
third-party trackers was previously scored 0/75 and graded F, because
|
|
91
|
+
the three consent-related dimensions (consent validity, easy refusal,
|
|
92
|
+
transparency) were zeroed out whenever no modal was detected.
|
|
93
|
+
|
|
94
|
+
GDPR and the ePrivacy Directive only require a consent mechanism when
|
|
95
|
+
the site actually uses cookies or trackers that need consent. A
|
|
96
|
+
tracking-free site has no such obligation and must now correctly receive
|
|
97
|
+
a full score (grade A) and raise no compliance issues.
|
|
98
|
+
|
|
99
|
+
The fix adds a `consentRequired` guard in `analyzeCompliance`: the
|
|
100
|
+
three modal-related dimensions are only penalised when non-essential
|
|
101
|
+
cookies or non-CDN trackers are present. The report generator
|
|
102
|
+
(executive summary, recommendations, checklist) is updated to reflect
|
|
103
|
+
the same distinction. Unit and E2E tests are updated accordingly.
|
|
104
|
+
|
|
3
105
|
## 2.0.4
|
|
4
106
|
|
|
5
107
|
### Patch Changes
|
package/CLAUDE.md
CHANGED
|
@@ -68,7 +68,7 @@ Phase 3 and 4 require two separate browser sessions so cookie state is fully iso
|
|
|
68
68
|
- **`src/classifiers/tracker-list.ts`** — Static database of tracker domains by category
|
|
69
69
|
- **`src/analyzers/compliance.ts`** — Scores 4 dimensions (0–25 each) and surfaces `DarkPatternIssue` objects: consent validity, easy refusal, transparency, cookie behavior
|
|
70
70
|
- **`src/analyzers/wording.ts`** — Text analysis of button labels and modal copy
|
|
71
|
-
- **`src/report/generator.ts`** — Renders
|
|
71
|
+
- **`src/report/generator.ts`** — Renders report files from `ScanResult` in the requested formats. The default output format is HTML. Markdown output produces 3 files: the main compliance report (`gdpr-report-*.md`), the checklist (`gdpr-checklist-*.md`), and the cookie inventory (`gdpr-cookies-*.md`); runs `oxfmt` on all generated Markdown files
|
|
72
72
|
- **`src/types.ts`** — All shared TypeScript interfaces (`ScanResult`, `ScanOptions`, `ComplianceScore`, `ConsentModal`, etc.)
|
|
73
73
|
|
|
74
74
|
### Compliance scoring
|
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ npx playwright install chromium
|
|
|
30
30
|
Or run without installing:
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
npx @slashgear/gdpr-cookie-scanner
|
|
33
|
+
npx @slashgear/gdpr-cookie-scanner scan https://example.com
|
|
34
34
|
# Playwright is still required the first time:
|
|
35
35
|
npx playwright install chromium
|
|
36
36
|
```
|
|
@@ -61,7 +61,7 @@ gdpr-scan scan <url> [options]
|
|
|
61
61
|
| ------------------------ | ---------------- | ------------------------------------------------------------- |
|
|
62
62
|
| `-o, --output <dir>` | `./gdpr-reports` | Output directory for the report |
|
|
63
63
|
| `-t, --timeout <ms>` | `30000` | Navigation timeout |
|
|
64
|
-
| `-f, --format <formats>` | `
|
|
64
|
+
| `-f, --format <formats>` | `html` | Output formats: `md`, `html`, `json`, `pdf` (comma-separated) |
|
|
65
65
|
| `--no-screenshots` | — | Disable screenshot capture |
|
|
66
66
|
| `-l, --locale <locale>` | `fr-FR` | Browser locale |
|
|
67
67
|
| `-v, --verbose` | — | Show full stack trace on error |
|
|
@@ -69,7 +69,7 @@ gdpr-scan scan <url> [options]
|
|
|
69
69
|
### Examples
|
|
70
70
|
|
|
71
71
|
```bash
|
|
72
|
-
# Basic scan
|
|
72
|
+
# Basic scan — produces an HTML report by default
|
|
73
73
|
gdpr-scan scan https://example.com
|
|
74
74
|
|
|
75
75
|
# With custom output directory
|
|
@@ -78,8 +78,8 @@ gdpr-scan scan https://example.com -o ./reports
|
|
|
78
78
|
# Scan in English, without screenshots
|
|
79
79
|
gdpr-scan scan https://example.com --locale en-US --no-screenshots
|
|
80
80
|
|
|
81
|
-
# Generate
|
|
82
|
-
gdpr-scan scan https://example.com -f
|
|
81
|
+
# Generate a Markdown report instead
|
|
82
|
+
gdpr-scan scan https://example.com -f md
|
|
83
83
|
|
|
84
84
|
# Generate all formats at once
|
|
85
85
|
gdpr-scan scan https://example.com -f md,html,json,pdf
|
|
@@ -88,6 +88,79 @@ gdpr-scan scan https://example.com -f md,html,json,pdf
|
|
|
88
88
|
gdpr-scan list-trackers
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
+
## Programmatic API
|
|
92
|
+
|
|
93
|
+
The package can be used as a Node.js library — no CLI required.
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
npm install @slashgear/gdpr-cookie-scanner
|
|
97
|
+
npx playwright install chromium
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Quick scan
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
import { scan } from "@slashgear/gdpr-cookie-scanner";
|
|
104
|
+
|
|
105
|
+
const result = await scan("https://example.com");
|
|
106
|
+
console.log(result.compliance.grade); // 'A' | 'B' | 'C' | 'D' | 'F'
|
|
107
|
+
console.log(result.compliance.totalScore); // 0–100
|
|
108
|
+
console.log(result.compliance.issues); // DarkPatternIssue[]
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
All fields of `ScanResult` — cookies, network requests, modal analysis, compliance score — are available in the returned object.
|
|
112
|
+
|
|
113
|
+
### Options
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
const result = await scan("https://example.com", {
|
|
117
|
+
locale: "fr-FR", // browser locale, also controls report language
|
|
118
|
+
timeout: 60_000, // navigation timeout in ms (default: 30 000)
|
|
119
|
+
screenshots: true, // capture screenshots (requires outputDir)
|
|
120
|
+
outputDir: "./reports", // where to save screenshots
|
|
121
|
+
verbose: false, // log scanner phases to stdout
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Generating reports
|
|
126
|
+
|
|
127
|
+
Pass the result to `ReportGenerator` to write files in one or more formats:
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
import { scan, ReportGenerator } from "@slashgear/gdpr-cookie-scanner";
|
|
131
|
+
|
|
132
|
+
const result = await scan("https://example.com", { locale: "fr-FR" });
|
|
133
|
+
|
|
134
|
+
const generator = new ReportGenerator({
|
|
135
|
+
url: result.url,
|
|
136
|
+
outputDir: "./reports",
|
|
137
|
+
formats: ["html", "json"], // 'md' | 'html' | 'json' | 'pdf'
|
|
138
|
+
locale: "fr-FR",
|
|
139
|
+
timeout: 30_000,
|
|
140
|
+
screenshots: false,
|
|
141
|
+
verbose: false,
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
const paths = await generator.generate(result);
|
|
145
|
+
console.log(paths.html); // './reports/example.com/gdpr-report-example.com-2024-01-01.html'
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### TypeScript types
|
|
149
|
+
|
|
150
|
+
All interfaces are exported from the package root:
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
import type {
|
|
154
|
+
ScanResult,
|
|
155
|
+
ScanOptions,
|
|
156
|
+
ComplianceScore,
|
|
157
|
+
DarkPatternIssue,
|
|
158
|
+
ScannedCookie,
|
|
159
|
+
NetworkRequest,
|
|
160
|
+
ConsentModal,
|
|
161
|
+
} from "@slashgear/gdpr-cookie-scanner";
|
|
162
|
+
```
|
|
163
|
+
|
|
91
164
|
## How it works
|
|
92
165
|
|
|
93
166
|
```mermaid
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compliance.d.ts","sourceRoot":"","sources":["../../src/analyzers/compliance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EAEZ,aAAa,EACb,cAAc,EACf,MAAM,aAAa,CAAC;AAGrB,UAAU,eAAe;IACvB,KAAK,EAAE,YAAY,CAAC;IACpB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,wBAAwB,EAAE,aAAa,EAAE,CAAC;IAC1C,kBAAkB,EAAE,aAAa,EAAE,CAAC;IACpC,kBAAkB,EAAE,aAAa,EAAE,CAAC;IACpC,wBAAwB,EAAE,cAAc,EAAE,CAAC;IAC3C,kBAAkB,EAAE,cAAc,EAAE,CAAC;IACrC,kBAAkB,EAAE,cAAc,EAAE,CAAC;CACtC;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,eAAe,GAAG,eAAe,
|
|
1
|
+
{"version":3,"file":"compliance.d.ts","sourceRoot":"","sources":["../../src/analyzers/compliance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EAEZ,aAAa,EACb,cAAc,EACf,MAAM,aAAa,CAAC;AAGrB,UAAU,eAAe;IACvB,KAAK,EAAE,YAAY,CAAC;IACpB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,wBAAwB,EAAE,aAAa,EAAE,CAAC;IAC1C,kBAAkB,EAAE,aAAa,EAAE,CAAC;IACpC,kBAAkB,EAAE,aAAa,EAAE,CAAC;IACpC,wBAAwB,EAAE,cAAc,EAAE,CAAC;IAC3C,kBAAkB,EAAE,cAAc,EAAE,CAAC;IACrC,kBAAkB,EAAE,cAAc,EAAE,CAAC;CACtC;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,eAAe,GAAG,eAAe,CAgPzE"}
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import { analyzeButtonWording, analyzeModalText } from "./wording.js";
|
|
2
2
|
export function analyzeCompliance(input) {
|
|
3
3
|
const issues = [];
|
|
4
|
+
// Determine whether a consent mechanism is actually required
|
|
5
|
+
const hasNonEssentialCookies = [
|
|
6
|
+
...input.cookiesBeforeInteraction,
|
|
7
|
+
...input.cookiesAfterAccept,
|
|
8
|
+
].some((c) => c.requiresConsent);
|
|
9
|
+
const hasNonEssentialTrackers = [
|
|
10
|
+
...input.networkBeforeInteraction,
|
|
11
|
+
...input.networkAfterAccept,
|
|
12
|
+
].some((r) => r.requiresConsent);
|
|
13
|
+
const consentRequired = hasNonEssentialCookies || hasNonEssentialTrackers;
|
|
4
14
|
// ── A. Consent validity (0-25) ────────────────────────────────
|
|
5
15
|
let consentValidity = 25;
|
|
6
|
-
if (!input.modal.detected) {
|
|
16
|
+
if (!input.modal.detected && consentRequired) {
|
|
7
17
|
issues.push({
|
|
8
18
|
type: "no-reject-button",
|
|
9
19
|
severity: "critical",
|
|
@@ -12,7 +22,7 @@ export function analyzeCompliance(input) {
|
|
|
12
22
|
});
|
|
13
23
|
consentValidity = 0;
|
|
14
24
|
}
|
|
15
|
-
else {
|
|
25
|
+
else if (input.modal.detected) {
|
|
16
26
|
// Wording analysis
|
|
17
27
|
const wordingResult = analyzeButtonWording(input.modal.buttons);
|
|
18
28
|
const textResult = analyzeModalText(input.modal.text);
|
|
@@ -38,10 +48,10 @@ export function analyzeCompliance(input) {
|
|
|
38
48
|
}
|
|
39
49
|
// ── B. Easy refusal (0-25) ────────────────────────────────────
|
|
40
50
|
let easyRefusal = 25;
|
|
41
|
-
if (!input.modal.detected) {
|
|
51
|
+
if (!input.modal.detected && consentRequired) {
|
|
42
52
|
easyRefusal = 0;
|
|
43
53
|
}
|
|
44
|
-
else {
|
|
54
|
+
else if (input.modal.detected) {
|
|
45
55
|
const acceptButton = input.modal.buttons.find((b) => b.type === "accept");
|
|
46
56
|
const rejectButton = input.modal.buttons.find((b) => b.type === "reject");
|
|
47
57
|
if (!rejectButton) {
|
|
@@ -88,13 +98,46 @@ export function analyzeCompliance(input) {
|
|
|
88
98
|
easyRefusal -= 5;
|
|
89
99
|
}
|
|
90
100
|
}
|
|
101
|
+
// Contrast ratio: reject button must meet minimum legibility
|
|
102
|
+
if (rejectButton && rejectButton.contrastRatio !== null) {
|
|
103
|
+
const ratio = rejectButton.contrastRatio;
|
|
104
|
+
if (ratio < 3.0) {
|
|
105
|
+
issues.push({
|
|
106
|
+
type: "asymmetric-prominence",
|
|
107
|
+
severity: "critical",
|
|
108
|
+
description: "Reject button has critically low contrast ratio",
|
|
109
|
+
evidence: `Contrast ratio ${ratio}:1 — WCAG AA requires 4.5:1 for normal text (${rejectButton.backgroundColor ?? "?"} / ${rejectButton.textColor ?? "?"})`,
|
|
110
|
+
});
|
|
111
|
+
easyRefusal -= 10;
|
|
112
|
+
}
|
|
113
|
+
else if (ratio < 4.5) {
|
|
114
|
+
issues.push({
|
|
115
|
+
type: "asymmetric-prominence",
|
|
116
|
+
severity: "warning",
|
|
117
|
+
description: "Reject button contrast ratio is below WCAG AA threshold",
|
|
118
|
+
evidence: `Contrast ratio ${ratio}:1 — WCAG AA requires 4.5:1 for normal text (${rejectButton.backgroundColor ?? "?"} / ${rejectButton.textColor ?? "?"})`,
|
|
119
|
+
});
|
|
120
|
+
easyRefusal -= 5;
|
|
121
|
+
}
|
|
122
|
+
// Relative contrast asymmetry: accept visually pops, reject is muted
|
|
123
|
+
const acceptContrast = acceptButton?.contrastRatio ?? null;
|
|
124
|
+
if (acceptContrast !== null && acceptContrast >= rejectButton.contrastRatio * 1.5) {
|
|
125
|
+
issues.push({
|
|
126
|
+
type: "asymmetric-prominence",
|
|
127
|
+
severity: "warning",
|
|
128
|
+
description: "Accept button has significantly higher contrast than reject button",
|
|
129
|
+
evidence: `Accept: ${acceptContrast}:1, Reject: ${rejectButton.contrastRatio}:1`,
|
|
130
|
+
});
|
|
131
|
+
easyRefusal -= 3;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
91
134
|
}
|
|
92
135
|
// ── C. Transparency (0-25) ────────────────────────────────────
|
|
93
136
|
let transparency = 25;
|
|
94
|
-
if (!input.modal.detected) {
|
|
137
|
+
if (!input.modal.detected && consentRequired) {
|
|
95
138
|
transparency = 0;
|
|
96
139
|
}
|
|
97
|
-
else {
|
|
140
|
+
else if (input.modal.detected) {
|
|
98
141
|
if (!input.modal.hasGranularControls) {
|
|
99
142
|
transparency -= 10;
|
|
100
143
|
}
|
|
@@ -114,8 +157,8 @@ export function analyzeCompliance(input) {
|
|
|
114
157
|
transparency -= 5;
|
|
115
158
|
}
|
|
116
159
|
}
|
|
117
|
-
// No privacy policy link anywhere on the page
|
|
118
|
-
if (!input.privacyPolicyUrl) {
|
|
160
|
+
// No privacy policy link anywhere on the page (only relevant when consent is required)
|
|
161
|
+
if (!input.privacyPolicyUrl && consentRequired) {
|
|
119
162
|
issues.push({
|
|
120
163
|
type: "missing-info",
|
|
121
164
|
severity: "warning",
|
|
@@ -149,7 +192,7 @@ export function analyzeCompliance(input) {
|
|
|
149
192
|
cookieBehavior -= Math.min(15, consentCookiesAfterReject.length * 3);
|
|
150
193
|
}
|
|
151
194
|
// Network trackers firing before interaction
|
|
152
|
-
const preInteractionTrackers = input.networkBeforeInteraction.filter((r) => r.
|
|
195
|
+
const preInteractionTrackers = input.networkBeforeInteraction.filter((r) => r.requiresConsent);
|
|
153
196
|
if (preInteractionTrackers.length > 0) {
|
|
154
197
|
issues.push({
|
|
155
198
|
type: "auto-consent",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compliance.js","sourceRoot":"","sources":["../../src/analyzers/compliance.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAatE,MAAM,UAAU,iBAAiB,CAAC,KAAsB;IACtD,MAAM,MAAM,GAAuB,EAAE,CAAC;IAEtC,iEAAiE;IACjE,IAAI,eAAe,GAAG,EAAE,CAAC;IAEzB,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"compliance.js","sourceRoot":"","sources":["../../src/analyzers/compliance.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cookie-classifier.d.ts","sourceRoot":"","sources":["../../src/classifiers/cookie-classifier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,cAAc,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;CAC1B;
|
|
1
|
+
{"version":3,"file":"cookie-classifier.d.ts","sourceRoot":"","sources":["../../src/classifiers/cookie-classifier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,cAAc,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;CAC1B;AA2GD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,oBAAoB,CAahG"}
|
|
@@ -80,7 +80,8 @@ const COOKIE_PATTERNS = [
|
|
|
80
80
|
{ pattern: /^_ttp$/i, category: "advertising", requiresConsent: true }, // TikTok
|
|
81
81
|
// ── Social ─────────────────────────────────────────────────────
|
|
82
82
|
{ pattern: /^(fbsr_|fbm_)/, category: "social", requiresConsent: true }, // Facebook login
|
|
83
|
-
{ pattern: /^(yt-|
|
|
83
|
+
{ pattern: /^(yt-|YSC|GPS)$/i, category: "social", requiresConsent: true }, // YouTube
|
|
84
|
+
{ pattern: /^VISITOR_INFO/i, category: "social", requiresConsent: true }, // YouTube VISITOR_INFO1_LIVE etc.
|
|
84
85
|
// ── Personalization ────────────────────────────────────────────
|
|
85
86
|
{
|
|
86
87
|
pattern: /^(ab_|abt_|abtest|experiment|variant|split[-_]test)/i,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cookie-classifier.js","sourceRoot":"","sources":["../../src/classifiers/cookie-classifier.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"cookie-classifier.js","sourceRoot":"","sources":["../../src/classifiers/cookie-classifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ interface NetworkClassification {
|
|
|
3
3
|
isThirdParty: boolean;
|
|
4
4
|
trackerCategory: TrackerCategory | null;
|
|
5
5
|
trackerName: string | null;
|
|
6
|
+
requiresConsent: boolean;
|
|
6
7
|
}
|
|
7
8
|
export declare function classifyNetworkRequest(url: string, resourceType: string): NetworkClassification;
|
|
8
9
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"network-classifier.d.ts","sourceRoot":"","sources":["../../src/classifiers/network-classifier.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,UAAU,qBAAqB;IAC7B,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,eAAe,GAAG,IAAI,CAAC;IACxC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"network-classifier.d.ts","sourceRoot":"","sources":["../../src/classifiers/network-classifier.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,UAAU,qBAAqB;IAC7B,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,eAAe,GAAG,IAAI,CAAC;IACxC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,qBAAqB,CAoD/F"}
|
|
@@ -5,7 +5,12 @@ export function classifyNetworkRequest(url, resourceType) {
|
|
|
5
5
|
hostname = new URL(url).hostname.replace(/^www\./, "");
|
|
6
6
|
}
|
|
7
7
|
catch {
|
|
8
|
-
return {
|
|
8
|
+
return {
|
|
9
|
+
isThirdParty: false,
|
|
10
|
+
trackerCategory: null,
|
|
11
|
+
trackerName: null,
|
|
12
|
+
requiresConsent: false,
|
|
13
|
+
};
|
|
9
14
|
}
|
|
10
15
|
// Check tracker database (exact match or suffix match)
|
|
11
16
|
for (const [domain, entry] of Object.entries(TRACKER_DB)) {
|
|
@@ -14,6 +19,7 @@ export function classifyNetworkRequest(url, resourceType) {
|
|
|
14
19
|
isThirdParty: true,
|
|
15
20
|
trackerCategory: entry.category,
|
|
16
21
|
trackerName: entry.name,
|
|
22
|
+
requiresConsent: entry.consentRequired !== false && entry.category !== "cdn",
|
|
17
23
|
};
|
|
18
24
|
}
|
|
19
25
|
}
|
|
@@ -23,6 +29,7 @@ export function classifyNetworkRequest(url, resourceType) {
|
|
|
23
29
|
isThirdParty: true,
|
|
24
30
|
trackerCategory: "pixel",
|
|
25
31
|
trackerName: "Tracking Pixel",
|
|
32
|
+
requiresConsent: true,
|
|
26
33
|
};
|
|
27
34
|
}
|
|
28
35
|
// Resource type heuristics
|
|
@@ -31,12 +38,14 @@ export function classifyNetworkRequest(url, resourceType) {
|
|
|
31
38
|
isThirdParty: true,
|
|
32
39
|
trackerCategory: "pixel",
|
|
33
40
|
trackerName: "Tracking Pixel (image)",
|
|
41
|
+
requiresConsent: true,
|
|
34
42
|
};
|
|
35
43
|
}
|
|
36
44
|
return {
|
|
37
45
|
isThirdParty: false,
|
|
38
46
|
trackerCategory: null,
|
|
39
47
|
trackerName: null,
|
|
48
|
+
requiresConsent: false,
|
|
40
49
|
};
|
|
41
50
|
}
|
|
42
51
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"network-classifier.js","sourceRoot":"","sources":["../../src/classifiers/network-classifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"network-classifier.js","sourceRoot":"","sources":["../../src/classifiers/network-classifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAU/D,MAAM,UAAU,sBAAsB,CAAC,GAAW,EAAE,YAAoB;IACtE,IAAI,QAAgB,CAAC;IAErB,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,YAAY,EAAE,KAAK;YACnB,eAAe,EAAE,IAAI;YACrB,WAAW,EAAE,IAAI;YACjB,eAAe,EAAE,KAAK;SACvB,CAAC;IACJ,CAAC;IAED,uDAAuD;IACvD,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACzD,IAAI,QAAQ,KAAK,MAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,MAAM,EAAE,CAAC,EAAE,CAAC;YAC3D,OAAO;gBACL,YAAY,EAAE,IAAI;gBAClB,eAAe,EAAE,KAAK,CAAC,QAAQ;gBAC/B,WAAW,EAAE,KAAK,CAAC,IAAI;gBACvB,eAAe,EAAE,KAAK,CAAC,eAAe,KAAK,KAAK,IAAI,KAAK,CAAC,QAAQ,KAAK,KAAK;aAC7E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,qCAAqC;IACrC,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QAC5C,OAAO;YACL,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,OAAO;YACxB,WAAW,EAAE,gBAAgB;YAC7B,eAAe,EAAE,IAAI;SACtB,CAAC;IACJ,CAAC;IAED,2BAA2B;IAC3B,IAAI,YAAY,KAAK,OAAO,IAAI,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;QACnD,OAAO;YACL,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,OAAO;YACxB,WAAW,EAAE,wBAAwB;YACrC,eAAe,EAAE,IAAI;SACtB,CAAC;IACJ,CAAC;IAED,OAAO;QACL,YAAY,EAAE,KAAK;QACnB,eAAe,EAAE,IAAI;QACrB,WAAW,EAAE,IAAI;QACjB,eAAe,EAAE,KAAK;KACvB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,GAAW;IAChC,MAAM,CAAC,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IAC5B,OAAO,CACL,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC1C,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;QACf,4CAA4C,CAAC,IAAI,CAAC,GAAG,CAAC,CACvD,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracker-list.d.ts","sourceRoot":"","sources":["../../src/classifiers/tracker-list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,eAAe,CAAC;CAC3B;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"tracker-list.d.ts","sourceRoot":"","sources":["../../src/classifiers/tracker-list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,eAAe,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAuFnD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,EAQlC,CAAC"}
|
|
@@ -17,7 +17,7 @@ export const TRACKER_DB = {
|
|
|
17
17
|
// ── Meta / Facebook ───────────────────────────────────────────
|
|
18
18
|
"connect.facebook.net": { name: "Facebook SDK", category: "social" },
|
|
19
19
|
"graph.facebook.com": { name: "Facebook Graph API", category: "social" },
|
|
20
|
-
"facebook.com
|
|
20
|
+
"pixel.facebook.com": { name: "Meta Pixel", category: "advertising" },
|
|
21
21
|
"fbcdn.net": { name: "Facebook CDN", category: "social" },
|
|
22
22
|
// ── Microsoft ─────────────────────────────────────────────────
|
|
23
23
|
"bat.bing.com": { name: "Bing Ads", category: "advertising" },
|
|
@@ -70,6 +70,12 @@ export const TRACKER_DB = {
|
|
|
70
70
|
"optimizely.com": { name: "Optimizely", category: "analytics" },
|
|
71
71
|
"vwo.com": { name: "VWO", category: "analytics" },
|
|
72
72
|
"app.convert.com": { name: "Convert", category: "analytics" },
|
|
73
|
+
// ── Consent-exempt analytics (CNIL ePrivacy exemption) ───────
|
|
74
|
+
"plausible.io": {
|
|
75
|
+
name: "Plausible Analytics",
|
|
76
|
+
category: "analytics",
|
|
77
|
+
consentRequired: false,
|
|
78
|
+
},
|
|
73
79
|
};
|
|
74
80
|
/**
|
|
75
81
|
* Patterns for detecting tracking pixels and beacons by URL shape.
|