@slashgear/gdpr-cookie-scanner 3.8.0 → 3.8.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 +17 -11
- package/.github/workflows/release.yml +6 -7
- package/.github/workflows/update-cookie-db.yml +9 -10
- package/.github/workflows/update-trackers.yml +8 -9
- package/.github/workflows/website.yml +18 -60
- package/CHANGELOG.md +37 -0
- package/CONTRIBUTING.md +1 -1
- package/Dockerfile +14 -16
- package/README.md +3 -3
- package/bun.lock +322 -0
- package/dist/cli.js +0 -0
- package/dist/report/generator.d.ts.map +1 -1
- package/dist/report/generator.js +9 -4
- package/dist/report/generator.js.map +1 -1
- package/dist/report/html.js +12 -3
- package/dist/report/html.js.map +1 -1
- package/dist/scanner/consent-modal.d.ts.map +1 -1
- package/dist/scanner/consent-modal.js +17 -5
- package/dist/scanner/consent-modal.js.map +1 -1
- package/dist/scanner/index.d.ts.map +1 -1
- package/dist/scanner/index.js +12 -2
- package/dist/scanner/index.js.map +1 -1
- package/package.json +22 -25
- package/src/report/generator.ts +10 -4
- package/src/report/html.ts +13 -3
- package/src/scanner/consent-modal.ts +16 -5
- package/src/scanner/index.ts +12 -2
- package/tests/analyzers/colour.test.ts +1 -1
- package/tests/analyzers/compliance.test.ts +50 -1
- package/tests/analyzers/tcf-decoder.test.ts +1 -1
- package/tests/analyzers/wording.test.ts +1 -1
- package/tests/classifiers/cookie-classifier.test.ts +1 -1
- package/tests/classifiers/network-classifier.test.ts +1 -1
- package/tests/e2e/scanner.test.ts +35 -47
- package/tests/scanner/button-classification.test.ts +1 -1
- package/tests/scanner/contrast-ratio.test.ts +1 -1
- package/tests/unit/compliance.test.ts +1 -1
- package/tests/unit/cookie-classifier.test.ts +1 -1
- package/tests/unit/network-classifier.test.ts +1 -1
- package/tests/unit/wording.test.ts +1 -1
- package/pnpm-workspace.yaml +0 -3
- package/vitest.config.ts +0 -9
- package/website/Dockerfile +0 -55
- package/website/node_modules/.bin/oxfmt +0 -21
- package/website/node_modules/.bin/oxlint +0 -21
- package/website/node_modules/.bin/tsc +0 -21
- package/website/node_modules/.bin/tsserver +0 -21
- package/website/node_modules/.bin/tsx +0 -21
- package/website/package.json +0 -29
- package/website/src/index.ts +0 -15
- package/website/src/security.ts +0 -26
- package/website/tsconfig.json +0 -14
package/.github/workflows/ci.yml
CHANGED
|
@@ -15,38 +15,44 @@ jobs:
|
|
|
15
15
|
steps:
|
|
16
16
|
- uses: actions/checkout@v6
|
|
17
17
|
|
|
18
|
-
- uses:
|
|
18
|
+
- uses: oven-sh/setup-bun@v2
|
|
19
19
|
with:
|
|
20
|
-
version:
|
|
20
|
+
bun-version: 1.3.14
|
|
21
21
|
|
|
22
|
-
- uses: actions/setup-node@
|
|
22
|
+
- uses: actions/setup-node@v6
|
|
23
23
|
with:
|
|
24
24
|
node-version: 24
|
|
25
|
-
cache: pnpm
|
|
26
25
|
|
|
27
26
|
- name: Install dependencies
|
|
28
|
-
run:
|
|
27
|
+
run: bun install --frozen-lockfile
|
|
29
28
|
|
|
30
29
|
- name: Format check
|
|
31
|
-
run:
|
|
30
|
+
run: bun run format:check
|
|
32
31
|
|
|
33
32
|
- name: Lint
|
|
34
|
-
run:
|
|
33
|
+
run: bun run lint
|
|
35
34
|
|
|
36
35
|
- name: Type check
|
|
37
|
-
run:
|
|
36
|
+
run: bun run typecheck
|
|
38
37
|
|
|
39
38
|
- name: Build
|
|
40
|
-
run:
|
|
39
|
+
run: bun run build
|
|
40
|
+
|
|
41
|
+
- name: Cache Playwright browsers
|
|
42
|
+
uses: actions/cache@v4
|
|
43
|
+
with:
|
|
44
|
+
path: ~/.cache/ms-playwright
|
|
45
|
+
key: playwright-${{ runner.os }}-${{ hashFiles('bun.lock') }}
|
|
41
46
|
|
|
42
47
|
- name: Install Playwright browsers
|
|
43
|
-
|
|
48
|
+
timeout-minutes: 10
|
|
49
|
+
run: npx playwright install chromium-headless-shell
|
|
44
50
|
|
|
45
51
|
- name: Test
|
|
46
52
|
id: test
|
|
47
53
|
run: |
|
|
48
54
|
start=$(date +%s)
|
|
49
|
-
|
|
55
|
+
bun run test
|
|
50
56
|
echo "duration=$(( $(date +%s) - start ))" >> "$GITHUB_OUTPUT"
|
|
51
57
|
|
|
52
58
|
- name: Record test suite duration
|
|
@@ -15,27 +15,26 @@ jobs:
|
|
|
15
15
|
steps:
|
|
16
16
|
- uses: actions/checkout@v6
|
|
17
17
|
|
|
18
|
-
- uses:
|
|
18
|
+
- uses: oven-sh/setup-bun@v2
|
|
19
19
|
with:
|
|
20
|
-
version:
|
|
20
|
+
bun-version: 1.3.14
|
|
21
21
|
|
|
22
|
-
- uses: actions/setup-node@
|
|
22
|
+
- uses: actions/setup-node@v6
|
|
23
23
|
with:
|
|
24
24
|
node-version: 24
|
|
25
|
-
cache: pnpm
|
|
26
25
|
registry-url: https://registry.npmjs.org
|
|
27
26
|
|
|
28
27
|
- name: Install dependencies
|
|
29
|
-
run:
|
|
28
|
+
run: bun install --frozen-lockfile
|
|
30
29
|
|
|
31
30
|
- name: Build
|
|
32
|
-
run:
|
|
31
|
+
run: bun run build
|
|
33
32
|
|
|
34
33
|
- name: Create release PR or publish to npm
|
|
35
34
|
id: changesets
|
|
36
35
|
uses: changesets/action@v1
|
|
37
36
|
with:
|
|
38
|
-
publish:
|
|
37
|
+
publish: bunx changeset publish
|
|
39
38
|
title: "chore: release new version"
|
|
40
39
|
commit: "chore: release new version"
|
|
41
40
|
createGithubReleases: true
|
|
@@ -16,20 +16,19 @@ jobs:
|
|
|
16
16
|
steps:
|
|
17
17
|
- uses: actions/checkout@v6
|
|
18
18
|
|
|
19
|
-
- uses:
|
|
19
|
+
- uses: oven-sh/setup-bun@v2
|
|
20
20
|
with:
|
|
21
|
-
version:
|
|
21
|
+
bun-version: 1.3.14
|
|
22
22
|
|
|
23
|
-
- uses: actions/setup-node@
|
|
23
|
+
- uses: actions/setup-node@v6
|
|
24
24
|
with:
|
|
25
25
|
node-version: 24
|
|
26
|
-
cache: pnpm
|
|
27
26
|
|
|
28
27
|
- name: Install dependencies
|
|
29
|
-
run:
|
|
28
|
+
run: bun install --frozen-lockfile
|
|
30
29
|
|
|
31
30
|
- name: Fetch Open Cookie Database
|
|
32
|
-
run:
|
|
31
|
+
run: bun run update:ocd
|
|
33
32
|
|
|
34
33
|
- name: Detect changes
|
|
35
34
|
id: diff
|
|
@@ -40,11 +39,11 @@ jobs:
|
|
|
40
39
|
|
|
41
40
|
- name: Type-check
|
|
42
41
|
if: steps.diff.outputs.changed == 'true'
|
|
43
|
-
run:
|
|
42
|
+
run: bun run typecheck
|
|
44
43
|
|
|
45
44
|
- name: Format
|
|
46
45
|
if: steps.diff.outputs.changed == 'true'
|
|
47
|
-
run:
|
|
46
|
+
run: bun run format
|
|
48
47
|
|
|
49
48
|
- name: Create PR
|
|
50
49
|
if: steps.diff.outputs.changed == 'true'
|
|
@@ -84,8 +83,8 @@ jobs:
|
|
|
84
83
|
|
|
85
84
|
## Test plan
|
|
86
85
|
|
|
87
|
-
- [ ] `
|
|
88
|
-
- [ ] `
|
|
86
|
+
- [ ] `bun run typecheck` passes (validated by CI)
|
|
87
|
+
- [ ] `bun run build` produces `dist/data/open-cookie-database.json`
|
|
89
88
|
- [ ] Spot-check a few cookie descriptions in the updated file
|
|
90
89
|
|
|
91
90
|
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
|
@@ -16,20 +16,19 @@ jobs:
|
|
|
16
16
|
steps:
|
|
17
17
|
- uses: actions/checkout@v6
|
|
18
18
|
|
|
19
|
-
- uses:
|
|
19
|
+
- uses: oven-sh/setup-bun@v2
|
|
20
20
|
with:
|
|
21
|
-
version:
|
|
21
|
+
bun-version: 1.3.14
|
|
22
22
|
|
|
23
|
-
- uses: actions/setup-node@
|
|
23
|
+
- uses: actions/setup-node@v6
|
|
24
24
|
with:
|
|
25
25
|
node-version: 24
|
|
26
|
-
cache: pnpm
|
|
27
26
|
|
|
28
27
|
- name: Install dependencies
|
|
29
|
-
run:
|
|
28
|
+
run: bun install --frozen-lockfile
|
|
30
29
|
|
|
31
30
|
- name: Fetch & merge tracker lists
|
|
32
|
-
run:
|
|
31
|
+
run: bun run update-trackers
|
|
33
32
|
|
|
34
33
|
- name: Detect changes
|
|
35
34
|
id: diff
|
|
@@ -40,11 +39,11 @@ jobs:
|
|
|
40
39
|
|
|
41
40
|
- name: Format
|
|
42
41
|
if: steps.diff.outputs.changed == 'true'
|
|
43
|
-
run:
|
|
42
|
+
run: bun run format
|
|
44
43
|
|
|
45
44
|
- name: Type-check
|
|
46
45
|
if: steps.diff.outputs.changed == 'true'
|
|
47
|
-
run:
|
|
46
|
+
run: bun run typecheck
|
|
48
47
|
|
|
49
48
|
- name: Create PR
|
|
50
49
|
if: steps.diff.outputs.changed == 'true'
|
|
@@ -85,7 +84,7 @@ jobs:
|
|
|
85
84
|
|
|
86
85
|
## Test plan
|
|
87
86
|
|
|
88
|
-
- [ ] `
|
|
87
|
+
- [ ] `bun run typecheck` passes (validated by CI)
|
|
89
88
|
- [ ] Review the diff in `tracker-list.ts` for obviously incorrect category assignments
|
|
90
89
|
- [ ] Spot-check 2–3 new domains against their actual tracker type
|
|
91
90
|
|
|
@@ -4,77 +4,35 @@ on:
|
|
|
4
4
|
push:
|
|
5
5
|
branches: [main]
|
|
6
6
|
paths:
|
|
7
|
-
- "website/**"
|
|
8
|
-
- "pnpm-workspace.yaml"
|
|
7
|
+
- "website/public/**"
|
|
9
8
|
- ".github/workflows/website.yml"
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
pages: write
|
|
13
|
+
id-token: write
|
|
14
|
+
|
|
15
|
+
concurrency:
|
|
16
|
+
group: pages
|
|
17
|
+
cancel-in-progress: true
|
|
13
18
|
|
|
14
19
|
jobs:
|
|
15
|
-
|
|
20
|
+
deploy:
|
|
16
21
|
runs-on: ubuntu-latest
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
outputs:
|
|
22
|
-
image: ${{ steps.meta.outputs.image }}
|
|
22
|
+
environment:
|
|
23
|
+
name: github-pages
|
|
24
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
23
25
|
|
|
24
26
|
steps:
|
|
25
27
|
- uses: actions/checkout@v6
|
|
26
28
|
with:
|
|
27
29
|
lfs: true
|
|
28
30
|
|
|
29
|
-
-
|
|
30
|
-
uses: docker/login-action@v3
|
|
31
|
-
with:
|
|
32
|
-
registry: ghcr.io
|
|
33
|
-
username: ${{ github.actor }}
|
|
34
|
-
password: ${{ secrets.GITHUB_TOKEN }}
|
|
35
|
-
|
|
36
|
-
- name: Set up QEMU
|
|
37
|
-
uses: docker/setup-qemu-action@v3
|
|
38
|
-
|
|
39
|
-
- name: Set up Docker Buildx
|
|
40
|
-
uses: docker/setup-buildx-action@v3
|
|
31
|
+
- uses: actions/configure-pages@v5
|
|
41
32
|
|
|
42
|
-
-
|
|
43
|
-
id: meta
|
|
44
|
-
run: |
|
|
45
|
-
echo "image=ghcr.io/$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')-website" >> "$GITHUB_OUTPUT"
|
|
46
|
-
|
|
47
|
-
- name: Build and push
|
|
48
|
-
uses: docker/build-push-action@v6
|
|
33
|
+
- uses: actions/upload-pages-artifact@v3
|
|
49
34
|
with:
|
|
50
|
-
|
|
51
|
-
file: website/Dockerfile
|
|
52
|
-
push: true
|
|
53
|
-
platforms: linux/amd64,linux/arm64
|
|
54
|
-
tags: |
|
|
55
|
-
${{ steps.meta.outputs.image }}:latest
|
|
56
|
-
${{ steps.meta.outputs.image }}:${{ github.sha }}
|
|
57
|
-
cache-from: type=gha
|
|
58
|
-
cache-to: type=gha,mode=max
|
|
59
|
-
|
|
60
|
-
deploy:
|
|
61
|
-
needs: build-and-push
|
|
62
|
-
runs-on: ubuntu-latest
|
|
63
|
-
environment: production
|
|
64
|
-
|
|
65
|
-
steps:
|
|
66
|
-
- name: Install Scaleway CLI
|
|
67
|
-
run: |
|
|
68
|
-
curl -fsSL https://raw.githubusercontent.com/scaleway/scaleway-cli/master/scripts/get.sh | sh
|
|
35
|
+
path: website/public
|
|
69
36
|
|
|
70
|
-
-
|
|
71
|
-
|
|
72
|
-
scw container container update ${{ secrets.SCW_CONTAINER_ID }} \
|
|
73
|
-
registry-image=${{ needs.build-and-push.outputs.image }}:${{ github.sha }} \
|
|
74
|
-
region=${{ env.SCW_DEFAULT_REGION }} \
|
|
75
|
-
redeploy=true
|
|
76
|
-
env:
|
|
77
|
-
SCW_ACCESS_KEY: ${{ secrets.SCW_ACCESS_KEY }}
|
|
78
|
-
SCW_SECRET_KEY: ${{ secrets.SCW_SECRET_KEY }}
|
|
79
|
-
SCW_DEFAULT_ORGANIZATION_ID: ${{ secrets.SCW_ORGANIZATION_ID }}
|
|
80
|
-
SCW_DEFAULT_PROJECT_ID: ${{ secrets.SCW_PROJECT_ID }}
|
|
37
|
+
- uses: actions/deploy-pages@v4
|
|
38
|
+
id: deployment
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
# @slashgear/gdpr-cookie-scanner
|
|
2
2
|
|
|
3
|
+
## 3.8.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 70d5692: chore: switch Docker runtime base to oven/bun:slim
|
|
8
|
+
|
|
9
|
+
Replaces `node:24-slim` (~200 MB) with `oven/bun:slim` (~90 MB) as the runtime stage base image, saving ~110 MB. The build stage keeps `node:24-slim` (needed for `tsc`). Playwright's `chromium-headless-shell` and its system dependencies are installed normally via `--with-deps` in the runtime stage. Verified locally: `docker run --rm gdpr-bun-test --help` works correctly.
|
|
10
|
+
|
|
11
|
+
- a8cb2b6: Switch Playwright browser from `chromium` to `chromium-headless-shell` in Docker and CI.
|
|
12
|
+
|
|
13
|
+
The headless-shell binary is a stripped-down Chromium build without UI layers, reducing the Docker image size by ~150–200 MB. All scanner features (cookie capture, network interception, DOM interaction, screenshots, bounding boxes) are fully supported. The scanner already runs in headless mode exclusively.
|
|
14
|
+
|
|
15
|
+
## 3.8.1
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- 3204616: Fix cookie capture after accept/reject on sites with non-unique button CSS classes
|
|
20
|
+
|
|
21
|
+
Two bugs prevented cookies from being captured after interacting with the consent modal:
|
|
22
|
+
|
|
23
|
+
1. **Non-unique button selector** — on sites built with a design system (e.g. Scaleway), all CMP buttons share identical CSS classes. The generated selector matched multiple elements and Playwright resolved to the first one, which was often hidden. The selector generator now checks that the class-based selector is unique in the DOM; if not, it falls back to Playwright's `:has-text()` pseudo-selector so each button is targeted individually.
|
|
24
|
+
|
|
25
|
+
2. **Page navigation not awaited** — some CMPs trigger a full page reload when the user accepts or rejects. The scanner was capturing cookies after a fixed delay, before the server had time to set them via `Set-Cookie`. The delay is now replaced by `waitForLoadState("networkidle")` so cookies are captured once the page (and any post-navigation requests) has settled.
|
|
26
|
+
|
|
27
|
+
- 032376e: Fix false non-compliance indicators for sites using only consent-exempt analytics (Plausible, Fathom, etc.)
|
|
28
|
+
|
|
29
|
+
Sites that use privacy-respecting, cookieless analytics tools (exempt under the CNIL exemption) and have no consent banner should score 100 with no non-compliance flags. Two bugs in the HTML report were causing the opposite:
|
|
30
|
+
|
|
31
|
+
1. The HTML network section was showing a red "before consent" badge for all trackers fired before interaction, regardless of whether they require consent — Plausible was being flagged as a violation even though it is explicitly marked `consentRequired: false`.
|
|
32
|
+
2. The HTML checklist "No tracker before consent" rule was not filtering by `requiresConsent`, so it displayed ❌ Non-compliant for sites that only use Plausible.
|
|
33
|
+
|
|
34
|
+
Fixes:
|
|
35
|
+
|
|
36
|
+
- HTML network section: consent-exempt trackers fired before interaction now show a green "exempt" badge instead of the red "before consent" badge. The header count badge only counts consent-requiring trackers.
|
|
37
|
+
- HTML checklist: "No tracker before consent" now correctly filters by `requiresConsent`.
|
|
38
|
+
- Markdown network section: added a "Consent req." column so readers can immediately see which trackers require consent and which are exempt.
|
|
39
|
+
|
|
3
40
|
## 3.8.0
|
|
4
41
|
|
|
5
42
|
### Minor Changes
|
package/CONTRIBUTING.md
CHANGED
package/Dockerfile
CHANGED
|
@@ -1,37 +1,35 @@
|
|
|
1
1
|
# ── Stage 1: build ────────────────────────────────────────────────────────────
|
|
2
|
+
# node:24-slim is kept here because tsc (TypeScript compiler) requires Node.js
|
|
2
3
|
FROM node:24-slim AS builder
|
|
3
4
|
WORKDIR /app
|
|
4
5
|
|
|
5
|
-
RUN npm install -g
|
|
6
|
+
RUN npm install -g bun
|
|
6
7
|
|
|
7
|
-
COPY package.json
|
|
8
|
-
RUN
|
|
8
|
+
COPY package.json bun.lock ./
|
|
9
|
+
RUN bun install --frozen-lockfile
|
|
9
10
|
|
|
10
11
|
COPY tsconfig.json ./
|
|
11
12
|
COPY scripts ./scripts
|
|
12
13
|
COPY src ./src
|
|
13
|
-
RUN
|
|
14
|
+
RUN bun run build
|
|
14
15
|
|
|
15
16
|
# ── Stage 2: runtime ──────────────────────────────────────────────────────────
|
|
16
|
-
# node:24-slim
|
|
17
|
-
#
|
|
18
|
-
FROM
|
|
17
|
+
# oven/bun:slim (~90 MB) vs node:24-slim (~200 MB) — saves ~110 MB.
|
|
18
|
+
# Playwright runs fine under Bun (verified by e2e test suite).
|
|
19
|
+
FROM oven/bun:slim
|
|
19
20
|
WORKDIR /app
|
|
20
21
|
ENV NODE_ENV=production
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
COPY package.json bun.lock ./
|
|
24
|
+
RUN bun install --production --frozen-lockfile
|
|
23
25
|
|
|
24
|
-
#
|
|
25
|
-
|
|
26
|
-
RUN pnpm install --prod --frozen-lockfile
|
|
27
|
-
|
|
28
|
-
# Install Chromium + its system dependencies, then clean up apt caches
|
|
29
|
-
RUN pnpm exec playwright install chromium --with-deps \
|
|
26
|
+
# --with-deps installs Chromium system libraries via apt (safe in Docker, unlike CI runners)
|
|
27
|
+
RUN bunx playwright install chromium-headless-shell --with-deps \
|
|
30
28
|
&& rm -rf /var/lib/apt/lists/*
|
|
31
29
|
|
|
32
30
|
COPY --from=builder /app/dist ./dist
|
|
33
31
|
|
|
34
32
|
VOLUME ["/reports"]
|
|
35
33
|
|
|
36
|
-
ENTRYPOINT ["
|
|
37
|
-
CMD ["--help"]
|
|
34
|
+
ENTRYPOINT ["bun", "dist/cli.js"]
|
|
35
|
+
CMD ["--help"]
|
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ Manually verifying that a consent banner behaves correctly — no cookies droppe
|
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
27
|
npm install -g @slashgear/gdpr-cookie-scanner
|
|
28
|
-
npx playwright install chromium
|
|
28
|
+
npx playwright install chromium-headless-shell
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
Or run without installing:
|
|
@@ -33,7 +33,7 @@ Or run without installing:
|
|
|
33
33
|
```bash
|
|
34
34
|
npx @slashgear/gdpr-cookie-scanner scan https://example.com
|
|
35
35
|
# Playwright is still required the first time:
|
|
36
|
-
npx playwright install chromium
|
|
36
|
+
npx playwright install chromium-headless-shell
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
## Docker
|
|
@@ -221,7 +221,7 @@ The package can be used as a Node.js library — no CLI required.
|
|
|
221
221
|
|
|
222
222
|
```bash
|
|
223
223
|
npm install @slashgear/gdpr-cookie-scanner
|
|
224
|
-
npx playwright install chromium
|
|
224
|
+
npx playwright install chromium-headless-shell
|
|
225
225
|
```
|
|
226
226
|
|
|
227
227
|
### Quick scan
|