@slashgear/gdpr-cookie-scanner 3.2.0 → 3.2.2
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/ci.yml +2 -0
- package/.github/workflows/release.yml +9 -0
- package/CHANGELOG.md +25 -0
- package/NEXT_STEPS.md +104 -0
- package/README.md +6 -0
- package/dist/scanner/consent-modal.d.ts.map +1 -1
- package/dist/scanner/consent-modal.js +8 -2
- package/dist/scanner/consent-modal.js.map +1 -1
- package/package.json +1 -1
- package/src/scanner/consent-modal.ts +11 -2
package/.github/workflows/ci.yml
CHANGED
|
@@ -59,12 +59,21 @@ jobs:
|
|
|
59
59
|
username: ${{ github.actor }}
|
|
60
60
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
61
61
|
|
|
62
|
+
- name: Set up QEMU
|
|
63
|
+
if: steps.changesets.outputs.published == 'true'
|
|
64
|
+
uses: docker/setup-qemu-action@v3
|
|
65
|
+
|
|
66
|
+
- name: Set up Docker Buildx
|
|
67
|
+
if: steps.changesets.outputs.published == 'true'
|
|
68
|
+
uses: docker/setup-buildx-action@v3
|
|
69
|
+
|
|
62
70
|
- name: Build and push Docker image
|
|
63
71
|
if: steps.changesets.outputs.published == 'true'
|
|
64
72
|
uses: docker/build-push-action@v6
|
|
65
73
|
with:
|
|
66
74
|
context: .
|
|
67
75
|
push: true
|
|
76
|
+
platforms: linux/amd64,linux/arm64
|
|
68
77
|
tags: |
|
|
69
78
|
${{ steps.version.outputs.image }}:latest
|
|
70
79
|
${{ steps.version.outputs.image }}:${{ steps.version.outputs.version }}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @slashgear/gdpr-cookie-scanner
|
|
2
2
|
|
|
3
|
+
## 3.2.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- f83c693: Restrict CI workflow to least-privilege permissions (CodeQL alert #1).
|
|
8
|
+
|
|
9
|
+
The CI workflow had no explicit `permissions:` block, meaning the default GitHub Actions
|
|
10
|
+
token was granted broad write access to repository contents. Added `permissions: contents: read`
|
|
11
|
+
to enforce the minimum permissions required for the job.
|
|
12
|
+
|
|
13
|
+
- f83c693: Fix incomplete URL scheme check in privacy policy link detection (CodeQL alert #2).
|
|
14
|
+
|
|
15
|
+
`findPrivacyPolicyUrl` only blocked `javascript:` and `#` hrefs. An attacker-controlled
|
|
16
|
+
page could bypass this check with `data:`, `vbscript:`, or a mixed-case variant such as
|
|
17
|
+
`JavaScript:` (the check was not case-normalised). The fix adds `data:` and `vbscript:`
|
|
18
|
+
to the blocklist and lowercases the href before comparing scheme prefixes.
|
|
19
|
+
|
|
20
|
+
## 3.2.1
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- 9ab986f: Fix: "Tout rejeter" and "rejeter" were not recognised as valid reject buttons.
|
|
25
|
+
|
|
26
|
+
The `REJECT_PATTERNS` regex only covered the `refus*` stem (refuser, tout refuser) but missed the `rejet*` stem (rejeter, tout rejeter) which is used by many CMPs including Didomi and OneTrust in French. This caused the scanner to incorrectly report a missing reject button and penalise the easy-refusal score on sites that do provide one.
|
|
27
|
+
|
|
3
28
|
## 3.2.0
|
|
4
29
|
|
|
5
30
|
### Minor Changes
|
package/NEXT_STEPS.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Next steps
|
|
2
|
+
|
|
3
|
+
Ideas and improvement areas for `gdpr-cookie-scanner`. Not a roadmap — pick what matters most.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Bug fixes / quick wins
|
|
8
|
+
|
|
9
|
+
- **Hex & named colour support in contrast ratio parser** — `computeContrastRatio` only handles `rgba?()` strings (parsed via regex in `consent-modal.ts:329`). Named colours (`white`, `black`) and hex values (`#fff`) silently return `null`, causing false negatives in the easy-refusal contrast check.
|
|
10
|
+
|
|
11
|
+
- **Button text matching is whitespace-sensitive** — `classifyButtonType` calls `.trim()` but embedded line breaks or ` ` characters (common in CMP HTML) can still break the regex. Worth normalising whitespace fully before matching.
|
|
12
|
+
|
|
13
|
+
- **Cookie value truncation is silent** — values are truncated to 100 chars (`cookies.ts:19`) with no indication in the output. Add an `isTruncated` flag to `ScannedCookie` so reports can flag it.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Language support
|
|
18
|
+
|
|
19
|
+
Currently only French and English patterns are covered. A lot of EU sites served in other locales will get false "no reject button" results.
|
|
20
|
+
|
|
21
|
+
Languages to add at minimum (ordered by EU population / GDPR enforcement activity):
|
|
22
|
+
|
|
23
|
+
| Locale | Reject examples | Accept examples |
|
|
24
|
+
| ------- | ------------------------ | -------------------------------- |
|
|
25
|
+
| `de-DE` | Ablehnen, Alle ablehnen | Alle akzeptieren, Zustimmen |
|
|
26
|
+
| `es-ES` | Rechazar, Rechazar todo | Aceptar, Aceptar todo |
|
|
27
|
+
| `it-IT` | Rifiuta, Rifiuta tutto | Accetta, Accetta tutto |
|
|
28
|
+
| `nl-NL` | Weigeren, Alles weigeren | Accepteren, Alles accepteren |
|
|
29
|
+
| `pl-PL` | Odrzuć, Odrzuć wszystkie | Zaakceptuj, Zaakceptuj wszystkie |
|
|
30
|
+
| `pt-PT` | Rejeitar, Rejeitar tudo | Aceitar, Aceitar tudo |
|
|
31
|
+
|
|
32
|
+
The patterns live in `src/scanner/consent-modal.ts`. A locale-aware pattern map keyed by BCP 47 tag would be cleaner than one giant regex.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Dark pattern detection gaps
|
|
37
|
+
|
|
38
|
+
Patterns that are explicitly listed in CNIL/EDPB guidelines but not yet detected:
|
|
39
|
+
|
|
40
|
+
- **Cookie wall** — detect when the page content is blurred, hidden, or inaccessible before consent is given. Requires comparing DOM structure / visible content area before and after interaction.
|
|
41
|
+
|
|
42
|
+
- **Colour nudging** — accept button in green / reject button in grey or red is a documented dark pattern. Detect hue of each button's background colour and flag when accept is visually "positive" and reject is "negative".
|
|
43
|
+
|
|
44
|
+
- **Scroll- or navigation-as-consent** — some sites display a banner and treat scrolling as acceptance. Would require simulating a scroll event and checking whether the banner disappears without an explicit click.
|
|
45
|
+
|
|
46
|
+
- **Bundled opt-outs** — some CMPs only provide "reject analytics + marketing" as a single checkbox rather than granular controls. Could be inferred from `hasGranularControls` combined with a single reject-all path.
|
|
47
|
+
|
|
48
|
+
- **Consent fatigue / re-prompting** — detecting a banner reappearing on the next page load after rejection is hard without multi-page scanning, but worth exploring.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Scanner robustness
|
|
53
|
+
|
|
54
|
+
- **Configurable wait times** — the `waitForTimeout(2000)` / `waitForTimeout(3000)` values in `scanner/index.ts` are hardcoded. Some pages need more time (heavy SPAs); others waste time. Expose them as `ScanOptions` fields with sensible defaults.
|
|
55
|
+
|
|
56
|
+
- **Mobile viewport** — all scans use a 1280×900 desktop viewport. Many consent banners have different layouts on mobile (bottom sheets, full-screen overlays). A `--viewport mobile|tablet|desktop` option would let users test the responsive behaviour.
|
|
57
|
+
|
|
58
|
+
- **Multi-page scanning** — run the scan across several URLs of the same domain (home page + one inner page) and merge results. Useful for detecting banners that only appear on the first visit, or trackers that fire on specific pages.
|
|
59
|
+
|
|
60
|
+
- **Batch mode** — accept a list of URLs (file or `--url` repeated) and produce a summary report alongside individual reports. Useful for agencies auditing multiple client sites.
|
|
61
|
+
|
|
62
|
+
- **Firefox / WebKit** — Playwright supports both. Firefox in particular is relevant because some CMPs behave differently across engines. A `--browser chromium|firefox|webkit` flag would be low-effort to wire up.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Tracker & cookie classification
|
|
67
|
+
|
|
68
|
+
- **Tracker database size** — the hardcoded list (`src/classifiers/tracker-list.ts`) currently has ~55 entries. The monthly auto-update workflow merges Disconnect.me and DuckDuckGo Tracker Radar entries but the result needs review before merge. Consider auto-approving updates that only add entries (no removals or category changes).
|
|
69
|
+
|
|
70
|
+
- **Cookieless analytics exemptions** — only Plausible is marked `consentRequired: false`. Fathom, Simple Analytics, Cabin, and Pirsch have the same privacy-by-design model and should be listed.
|
|
71
|
+
|
|
72
|
+
- **Unknown first-party cookies default** — unknown cookies default to `requiresConsent: false` (conservative). This means new or obfuscated tracking cookies slip through. Consider a stricter mode (`--strict`) that flips the default to `requiresConsent: true` for unrecognised cookies.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Report improvements
|
|
77
|
+
|
|
78
|
+
- **Single-file Markdown** — the current 3-file split (report + checklist + inventory) is logical but awkward to share or attach in a ticket. An optional `--merge-md` flag that concatenates the three files would help.
|
|
79
|
+
|
|
80
|
+
- **Report localisation** — recommendations and section headings are hardcoded in French even when `--locale en-US` is used. The report language should follow `--locale`.
|
|
81
|
+
|
|
82
|
+
- **Historical comparison** — if a previous JSON report for the same hostname exists in the output directory, surface a diff (score delta, issues resolved/introduced). Useful for tracking progress over time.
|
|
83
|
+
|
|
84
|
+
- **Structured exit summary** — when `--fail-on` causes an exit 1, emit a machine-readable summary to stdout (JSON lines) so CI systems can parse it without reading the full report file.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Testing
|
|
89
|
+
|
|
90
|
+
- **Report output tests** — no tests currently validate the content of generated Markdown, HTML, or JSON files. Add snapshot tests for at least the JSON output and spot-checks for key sections in HTML.
|
|
91
|
+
|
|
92
|
+
- **Contrast ratio unit tests** — `computeContrastRatio` is pure logic but only exercised through E2E tests. Deserves a dedicated unit test file covering edge cases (identical colours, transparent backgrounds, named/hex inputs once supported).
|
|
93
|
+
|
|
94
|
+
- **Locale-specific button pattern tests** — once multi-language patterns land, add a test case per locale to prevent regressions.
|
|
95
|
+
|
|
96
|
+
- **Performance baseline** — the E2E suite takes ~2 minutes. As features grow, tracking suite duration in CI would help catch regressions early.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Infrastructure
|
|
101
|
+
|
|
102
|
+
- **Node version consistency** — CI runs Node 24 but the release workflow runs Node 22. Align to a single version across all workflows.
|
|
103
|
+
|
|
104
|
+
- **Pre-built GitHub Action** — a dedicated `uses: slashgear/gdpr-cookie-scanner-action@v1` action would make the GitHub Actions integration one step instead of running the Docker container manually. The action wrapper would handle artifact upload and PR comments automatically.
|
package/README.md
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
[](https://www.typescriptlang.org)
|
|
9
9
|
[](https://playwright.dev)
|
|
10
10
|
[](CODE_OF_CONDUCT.md)
|
|
11
|
+
[](https://ghcr.io/slashgear/gdpr-cookie-scanner)
|
|
11
12
|
|
|
12
13
|
A CLI tool that **automates a subset of GDPR cookie consent checks** on any website — consent modal detection, dark patterns, cookie behaviour before/after interaction, and network trackers. It produces a scored report (0–100) with a per-rule checklist and a cookie inventory.
|
|
13
14
|
|
|
@@ -49,6 +50,11 @@ docker run --rm \
|
|
|
49
50
|
The image is published to [GitHub Container Registry](https://ghcr.io/slashgear/gdpr-cookie-scanner)
|
|
50
51
|
on every release and supports `linux/amd64` and `linux/arm64`.
|
|
51
52
|
|
|
53
|
+
> [!NOTE]
|
|
54
|
+
> The image is ~500 MB compressed (~1.2 GB unpacked). This is inherent to shipping a full Chromium
|
|
55
|
+
> browser — significantly smaller than the official Playwright image (~1.8 GB) which bundles all
|
|
56
|
+
> three browser stacks. No browser installation step is needed when using Docker.
|
|
57
|
+
|
|
52
58
|
## Usage
|
|
53
59
|
|
|
54
60
|
```bash
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consent-modal.d.ts","sourceRoot":"","sources":["../../src/scanner/consent-modal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,YAAY,EAAqD,MAAM,aAAa,CAAC;AAEnG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAqE/C;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,IAAI,EACV,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"consent-modal.d.ts","sourceRoot":"","sources":["../../src/scanner/consent-modal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,YAAY,EAAqD,MAAM,aAAa,CAAC;AAEnG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAqE/C;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,IAAI,EACV,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAkCxB;AAcD,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAmFhG"}
|
|
@@ -75,9 +75,15 @@ export async function findPrivacyPolicyUrl(page, scopeSelector) {
|
|
|
75
75
|
const links = root.querySelectorAll("a[href]");
|
|
76
76
|
for (const link of links) {
|
|
77
77
|
const href = link.href ?? "";
|
|
78
|
+
const normalizedHref = href.toLowerCase();
|
|
78
79
|
const text = (link.textContent ?? "").trim();
|
|
79
|
-
if (!href ||
|
|
80
|
+
if (!href ||
|
|
81
|
+
normalizedHref.startsWith("javascript:") ||
|
|
82
|
+
normalizedHref.startsWith("data:") ||
|
|
83
|
+
normalizedHref.startsWith("vbscript:") ||
|
|
84
|
+
href === "#") {
|
|
80
85
|
continue;
|
|
86
|
+
}
|
|
81
87
|
const matchUrl = urlPats.some((p) => new RegExp(p, "i").test(href));
|
|
82
88
|
const matchText = textPats.some((p) => new RegExp(p, "i").test(text));
|
|
83
89
|
if (matchUrl || matchText)
|
|
@@ -95,7 +101,7 @@ const ACCEPT_PATTERNS = [
|
|
|
95
101
|
/\b(accept|accepter|acceptez|tout accepter|accept all|j'accepte|i accept|agree|ok\b|d'accord|continuer|continue|valider|confirmer)\b/i,
|
|
96
102
|
];
|
|
97
103
|
const REJECT_PATTERNS = [
|
|
98
|
-
/\b(refus|refuse|refuser|
|
|
104
|
+
/\b(refus|refuse|refuser|tout refuser|rejet|rejeter|tout rejeter|reject|reject all|deny|decline|non merci|no thanks|continuer sans accepter|skip)\b/i,
|
|
99
105
|
];
|
|
100
106
|
const PREFERENCES_PATTERNS = [
|
|
101
107
|
/\b(param[eè]tres|pr[eé]f[eé]rences|personnaliser|customise|customize|manage|g[eé]rer|options|choose|choisir|configure)\b/i,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consent-modal.js","sourceRoot":"","sources":["../../src/scanner/consent-modal.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,MAAM,eAAe,GAAG;IACtB,kBAAkB;IAClB,kBAAkB;IAClB,eAAe;IACf,uBAAuB;IACvB,uBAAuB;IACvB,sBAAsB;IACtB,yBAAyB;IACzB,uBAAuB;IACvB,cAAc;IACd,oBAAoB;IACpB,gBAAgB;IAChB,oBAAoB;IACpB,QAAQ;IACR,4BAA4B;IAC5B,YAAY;IACZ,YAAY;IACZ,gBAAgB;IAChB,iBAAiB;IACjB,gBAAgB;IAChB,gBAAgB;IAChB,sBAAsB;IACtB,qBAAqB;IACrB,oCAAoC;IACpC,mCAAmC;IACnC,mCAAmC;IACnC,qCAAqC;IACrC,oCAAoC;IACpC,8BAA8B;IAC9B,6BAA6B;IAC7B,iBAAiB;IACjB,0BAA0B;IAC1B,2BAA2B;IAC3B,2BAA2B;IAC3B,yCAAyC;IACzC,sBAAsB;CACvB,CAAC;AAEF,MAAM,2BAA2B,GAAG;IAClC,mBAAmB;IACnB,uCAAuC;IACvC,qCAAqC;IACrC,gBAAgB;IAChB,cAAc;IACd,sBAAsB;IACtB,aAAa;IACb,YAAY;IACZ,qBAAqB;IACrB,kBAAkB;CACnB,CAAC;AAEF,MAAM,4BAA4B,GAAG;IACnC,kBAAkB;IAClB,sCAAsC;IACtC,mCAAmC;IACnC,gBAAgB;IAChB,aAAa;IACb,uBAAuB;IACvB,aAAa;IACb,YAAY;IACZ,oBAAoB;CACrB,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,IAAU,EACV,aAAsB;IAEtB,OAAO,IAAI;SACR,QAAQ,CACP,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC/B,MAAM,IAAI,GAAuB,KAAK;YACpC,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC;YAC7C,CAAC,CAAC,QAAQ,CAAC;QACb,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAC/C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,IAAI,GAAI,IAA0B,CAAC,IAAI,IAAI,EAAE,CAAC;YACpD,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAC7C,
|
|
1
|
+
{"version":3,"file":"consent-modal.js","sourceRoot":"","sources":["../../src/scanner/consent-modal.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -87,8 +87,17 @@ export async function findPrivacyPolicyUrl(
|
|
|
87
87
|
const links = root.querySelectorAll("a[href]");
|
|
88
88
|
for (const link of links) {
|
|
89
89
|
const href = (link as HTMLAnchorElement).href ?? "";
|
|
90
|
+
const normalizedHref = href.toLowerCase();
|
|
90
91
|
const text = (link.textContent ?? "").trim();
|
|
91
|
-
if (
|
|
92
|
+
if (
|
|
93
|
+
!href ||
|
|
94
|
+
normalizedHref.startsWith("javascript:") ||
|
|
95
|
+
normalizedHref.startsWith("data:") ||
|
|
96
|
+
normalizedHref.startsWith("vbscript:") ||
|
|
97
|
+
href === "#"
|
|
98
|
+
) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
92
101
|
const matchUrl = urlPats.some((p) => new RegExp(p, "i").test(href));
|
|
93
102
|
const matchText = textPats.some((p) => new RegExp(p, "i").test(text));
|
|
94
103
|
if (matchUrl || matchText) return href;
|
|
@@ -109,7 +118,7 @@ const ACCEPT_PATTERNS = [
|
|
|
109
118
|
];
|
|
110
119
|
|
|
111
120
|
const REJECT_PATTERNS = [
|
|
112
|
-
/\b(refus|refuse|refuser|
|
|
121
|
+
/\b(refus|refuse|refuser|tout refuser|rejet|rejeter|tout rejeter|reject|reject all|deny|decline|non merci|no thanks|continuer sans accepter|skip)\b/i,
|
|
113
122
|
];
|
|
114
123
|
|
|
115
124
|
const PREFERENCES_PATTERNS = [
|