@duckduckgo/autoconsent 16.31.0 → 16.33.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/.agents/skills/proxy-testing/SKILL.md +1 -0
- package/.github/labeler.yml +6 -0
- package/AGENTS.md +27 -11
- package/CHANGELOG.md +31 -0
- package/dist/addon-firefox/compact-rules.json +1 -1
- package/dist/addon-firefox/manifest.json +1 -1
- package/dist/addon-firefox/rule-index.json +1 -1
- package/dist/addon-firefox/rules.json +1 -1
- package/dist/addon-mv3/compact-rules.json +1 -1
- package/dist/addon-mv3/manifest.json +1 -1
- package/dist/addon-mv3/rule-index.json +1 -1
- package/dist/addon-mv3/rules.json +1 -1
- package/dist/autoconsent.standalone.js +1 -1
- package/package.json +7 -1
- package/rules/autoconsent/doordash-storefront.json +34 -0
- package/rules/autoconsent/paypal-cookieprefs.json +29 -0
- package/rules/autoconsent/paypal-us.json +5 -32
- package/rules/compact-rules.json +1 -1
- package/rules/rule-index.json +1 -1
- package/rules/rules.json +1 -1
- package/tests/doordash-storefront.spec.ts +6 -0
- package/tests/paypal-cookieprefs.spec.ts +7 -0
|
@@ -134,3 +134,4 @@ await browser.close();
|
|
|
134
134
|
- The content script runs in an isolated world (via CDP) and `eval` snippets run in the page's main world, matching the extension. Chromium only.
|
|
135
135
|
- Use a fresh browser per region to avoid leaking proxy state, cookies, cache, or DNS.
|
|
136
136
|
- Some sites localize by more than IP; only add locale/geolocation settings intentionally.
|
|
137
|
+
- Some sites block proxy traffic outright (captcha, 403, endless challenge page). If every region's proxy is blocked for a site, retest it over a direct connection and state explicitly in the report that the result is unproxied. If direct access is blocked too, ask the triager for the popup's HTML pasted from their own browser as a last resort, and note that the rule was written from pasted markup rather than a live run.
|
package/.github/labeler.yml
CHANGED
package/AGENTS.md
CHANGED
|
@@ -47,6 +47,12 @@ npm run watch # auto-rebuild on changes to lib/, addon/, rules/
|
|
|
47
47
|
|
|
48
48
|
## Working with autoconsent rules
|
|
49
49
|
|
|
50
|
+
### Scope: what autoconsent handles
|
|
51
|
+
|
|
52
|
+
Only cookie/consent/privacy/GDPR/tracking-consent dialogs are in scope. Age-verification gates (e.g. "I am 18+" / "Enter" adult-content confirmations), login walls, paywalls, newsletter and app-install prompts, and other non-consent overlays are **out of scope**. Do not write a rule or a site exception that dismisses them, and do not treat clicking through such a gate as the fix.
|
|
53
|
+
|
|
54
|
+
An out-of-scope overlay often sits in front of a real consent popup. Click through it yourself while investigating — that is the way to find out whether a consent dialog is behind it — and write the rule against the consent dialog you uncover. Only conclude that the report is out of scope once you have looked behind the gate.
|
|
55
|
+
|
|
50
56
|
### Rule syntax
|
|
51
57
|
For the complete rule syntax reference (all step types, element selectors, conditionals, etc.), see [docs/rule-syntax.md](docs/rule-syntax.md).
|
|
52
58
|
|
|
@@ -64,8 +70,9 @@ Use `if`/`then`/`else` to handle regional variants within a single rule.
|
|
|
64
70
|
|
|
65
71
|
### Generic vs Site-Specific Rules
|
|
66
72
|
|
|
67
|
-
Site-specific rules are rules scoped to specific sites with a `urlPattern`. Rules without a urlPattern are called generic.
|
|
68
|
-
|
|
73
|
+
Site-specific rules are rules scoped to specific sites with a `urlPattern`. Rules without a `urlPattern` are called generic.
|
|
74
|
+
|
|
75
|
+
**Always prefer a generic CMP rule over a `urlPattern`-scoped one.** One CMP rule can cover multiple sites; a `urlPattern` is a last resort when the popup cannot be expressed as a shared CMP. Before writing a site-specific rule, identify the CMP (see "Identifying a Consent Management Platform" below) and extend an existing generic rule if one applies. If the popup is custom-built but shared across sibling sites, still write a generic rule. Only use a `urlPattern` when the popup is unique to that site (or a small sibling set) and a generic rule would be too broad — and even then, prefer a heuristic-pattern fix over a new site-specific rule (see Updating existing rules).
|
|
69
76
|
|
|
70
77
|
### JSON Rules vs Code-based rules
|
|
71
78
|
|
|
@@ -103,9 +110,10 @@ Single-string selectors cannot pierce — use arrays whenever the target is insi
|
|
|
103
110
|
shadow root or same-origin iframe.
|
|
104
111
|
|
|
105
112
|
### General Guidelines and Gotchas
|
|
106
|
-
- **Paywalls do not need to be handled.** If the
|
|
113
|
+
- **Paywalls do not need to be handled, and should not be mitigated.** If the site presents a choice to pay or agree to cookies, do not write a rule, do not click through, and do not add a site exception (unless autoconsent is causing breakage).
|
|
114
|
+
- **Never click TIER2 buttons in the `optOut` rule.** TIER2 is the heuristic classification for a popup whose only actionable button is a single Accept (`classifyPopup` in `lib/heuristics.ts`). Clicking that button from a JSON rule is an opt-in disguised as a fix. If the popup has no reject, dismiss, or acknowledge control, do not "handle" it by accepting.
|
|
107
115
|
- `detectCmp` and `detectPopup` must be fast. Do NOT use waiting steps — the engine retries automatically.
|
|
108
|
-
- Keep regexes in `urlPattern` as simple as possible to avoid unnecessary performance overhead. In most cases, a simple "^https?://(\w+\.)?domain\.com/" is sufficient.
|
|
116
|
+
- Keep regexes in `urlPattern` as simple as possible to avoid unnecessary performance overhead. In most cases, a simple "^https?://(\w+\.)?domain\.com/" is sufficient. Always end the pattern at the hostname boundary with a trailing `/`.
|
|
109
117
|
- **`prehideSelectors` do not affect autoconsent visibility checks.** Prehide selectors are injected early to prevent flicker, and are intentionally implemented using opacity, which hides elements from the user, but not from built-in steps such as `waitForVisible` and `visible`. That said, _prehide selectors should be narrow_: overly broad selectors (e.g. `body`) could hide the entire page.
|
|
110
118
|
- If you cover a new CMP or a new flavor of the existing CMP, ALWAYS try to look for more examples of that case, and add to the spec file.
|
|
111
119
|
- Prefer DOM-based steps when possible — `eval` steps are a last resort.
|
|
@@ -115,24 +123,28 @@ shadow root or same-origin iframe.
|
|
|
115
123
|
- Code comments: keep them brief (max one line), explain why not what, no references to specific sites in library code
|
|
116
124
|
|
|
117
125
|
### Updating existing rules
|
|
126
|
+
- **For site-specific popups, prefer a heuristic-pattern fix over a new rule, and check whether a rule is needed at all.** If the popup is unique to a site (not a shared CMP) and already has a reject, dismiss, or acknowledge button that the heuristic should match, extend `lib/heuristic-patterns.ts` instead of adding a `urlPattern`-scoped JSON rule. Do not use a heuristic fix in place of a generic CMP rule. A heuristic change must not cause false positives on other sites.
|
|
118
127
|
- If an existing generic rule fails on a specific site: first look for other sites with the same failure (spec sites, data/coverage.json, publicwww). If the issue applies to more sites, update the generic rule; if the issue is truly site-specific, prefer making a site-specific rule or a config exception. Never change a generic rule to fix a site-specific implementation problem.
|
|
119
128
|
- After updating an existing generic rule, do a heavy testing run: all known sites (specs + data/coverage.json + publicwww) across the expanded set. Inspect both API results AND screenshots.
|
|
120
|
-
-
|
|
121
|
-
- if a popup does not provide an opt-out button, `optOut` _may_ click "dismiss"/"acknowledge" instead. Check with the existing heuristic patterns in /lib/heuristic-patterns.ts for reference.
|
|
129
|
+
- **When adding or fixing a rule for a site, remove stale site-specific rules covering the same site.** If a site-specific rule is obsolete in all regions (the site switched CMP), remove it rather than leaving it alongside the new or updated rule.
|
|
130
|
+
- if a popup does not provide an opt-out button, `optOut` _may_ click "dismiss"/"acknowledge" instead. Check with the existing heuristic patterns in /lib/heuristic-patterns.ts for reference. Do **not** click a TIER2 (single Accept) button — see General Guidelines.
|
|
122
131
|
- do not keep outdated selectors in changed rules, unless they are actually used in some conditions
|
|
123
|
-
- If the pop-up has an explicit "reject"-like button, you should first consider why HEURISTIC rule didn't handle it. A fix to the heuristic rule is always preferred to a new rule, as long as it doesn't cause potential false-positives on other sites.
|
|
124
132
|
|
|
125
133
|
### Verification guidelines
|
|
126
134
|
- **Regional testing is mandatory** for any rule change — CMPs behave differently under GDPR (EU), CCPA (US), and other jurisdictions. Run the rule against different regions using `proxy-testing` skill before considering the change done. Iterate on the fix in the single most relevant region and run the verification according to the skill's policy.
|
|
127
135
|
- **Mobile policy**: by default test desktop across the current set's regions, plus one mobile sanity check in the region where the popup reproduces. If the mobile sanity check differs from desktop (different popup, rule, or outcome), expand mobile across the current set's regions. If the original report is from a mobile OS, test both desktop and mobile from the start.
|
|
128
136
|
- When verifying a rule, **look at the screenshots** on top of the API results — sometimes a rule reports success, but the popup is not actually handled - a screenshot will detect this.
|
|
129
|
-
- **
|
|
130
|
-
- **Watch out for false positive detections**.
|
|
137
|
+
- **Handling timing and DOM races.** A common pitfall is clicking before the site's JS handlers are ready. Prefer a state-based wait (`waitForVisible`, `waitForThenClick`) over an unconditional `wait`, and cap any unconditional `wait` at 1s — unconditional waits are a last resort because they hurt UX. When a click lands before handlers are attached, use `retry` / `retryInterval` on `waitForThenClick` (see `lib/rules.ts` and [docs/rule-syntax.md](docs/rule-syntax.md)) rather than padding a wait. `retry` only suits elements expected to **disappear** once the click is handled; extra clicks on a persistent control (e.g. a toggle) are wasted or harmful.
|
|
138
|
+
- **Watch out for false positive detections**. Verify that the rule does NOT match after the popup is dismissed and the page is reloaded. A cosmetic rule is the exception: it stores no consent state, so it matches every load by design — there the thing to rule out is the repeated handling making the page reload. Over-detection can lead to reload loops.
|
|
131
139
|
- **selfTests are optional.** It is okay to NOT have a self-test, or have it failing as long as the popup is handled correctly. Confirm this with screenshots.
|
|
132
140
|
- Generic rules without a urlPattern MUST have at least two sites in the spec file.
|
|
133
141
|
- If the popup comes in different DOM structures, cover all of them in the spec file.
|
|
134
142
|
|
|
135
|
-
###
|
|
143
|
+
### Breakage in cosmetic rules
|
|
144
|
+
**Prefer a non-cosmetic rule.** A cosmetic (`hide`) rule is a last resort when there is no reject/dismiss path. If cosmetic is unavoidable, verify that hiding the element does not break the page and **report that evidence**. Cosmetic rule without breakage-check evidence is incomplete.
|
|
145
|
+
|
|
146
|
+
Check each breakage type separately and report a verdict on each, rather than a general "looks fine": **leftover overlay** (a banner remnant or backdrop still covering the page), **blocked scrolling** (a scroll or overflow lock left on html/body or the dialog), **blocked interaction** (clicks or taps not reaching the page), and **reload loop** (the rule still matching after the popup is dismissed and the page is reloaded).
|
|
147
|
+
|
|
136
148
|
When using `hide`, the CMP may lock scrolling or add overlays. Add fixes AFTER the `hide` step, marked `"optional": true`:
|
|
137
149
|
|
|
138
150
|
| Problem | Fix |
|
|
@@ -166,11 +178,15 @@ Requires `PUBLICWWW_KEY` environment variable.
|
|
|
166
178
|
|
|
167
179
|
## Checking for Existing Site Exceptions in `privacy-configuration`
|
|
168
180
|
|
|
169
|
-
Some sites have autoconsent disabled
|
|
181
|
+
Some sites have autoconsent disabled via the `duckduckgo/privacy-configuration` repo. Before investigating a reported popup, check whether an **exception** already exists for the domain in:
|
|
170
182
|
|
|
171
183
|
- `features/autoconsent.json`
|
|
172
184
|
- `overrides/{android,ios,macos,windows,extension}-override.json` and any files under `overrides/browsers/`
|
|
173
185
|
|
|
186
|
+
**Know what you are looking at.** `features/autoconsent.json` carries both site exceptions *and* `settings.compactRuleList` rule bundle — a rule appearing there is **not** an exception. An autoconsent exception is not interchangeable with other privacy-config mitigations (content blocking, `unprotectedTemporary`, and similar); stay inside the `autoconsent` feature scope.
|
|
187
|
+
|
|
188
|
+
**Exceptions are only for breakage**, paywalls without breakage should not be mitigated.
|
|
189
|
+
|
|
174
190
|
**Do NOT rely on `gh search code` for this lookup.** GitHub's code search index has a per-file size limit and `features/autoconsent.json` is excluded — searches for the domain there silently return zero hits even when an exception exists.
|
|
175
191
|
|
|
176
192
|
Instead, fetch the file directly and grep locally, and/or list PRs by title.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,34 @@
|
|
|
1
|
+
# v16.33.0 (Tue Sep 01 2026)
|
|
2
|
+
|
|
3
|
+
#### Rules
|
|
4
|
+
|
|
5
|
+
- Rule update: CPM feedback: paypal.com [#1532](https://github.com/duckduckgo/autoconsent/pull/1532) ([@cursoragent](https://github.com/cursoragent) [@daxtheduck](https://github.com/daxtheduck))
|
|
6
|
+
|
|
7
|
+
#### AI / Agent Workflow
|
|
8
|
+
|
|
9
|
+
- Agent tweaks [#1530](https://github.com/duckduckgo/autoconsent/pull/1530) ([@muodov](https://github.com/muodov))
|
|
10
|
+
|
|
11
|
+
#### Authors: 3
|
|
12
|
+
|
|
13
|
+
- Cursor Agent ([@cursoragent](https://github.com/cursoragent))
|
|
14
|
+
- Dax ([@daxtheduck](https://github.com/daxtheduck))
|
|
15
|
+
- Maxim Tsoy ([@muodov](https://github.com/muodov))
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# v16.32.0 (Sat Aug 29 2026)
|
|
20
|
+
|
|
21
|
+
#### Rules
|
|
22
|
+
|
|
23
|
+
- Rule update: doordash-storefront [#1527](https://github.com/duckduckgo/autoconsent/pull/1527) ([@cursoragent](https://github.com/cursoragent) [@daxtheduck](https://github.com/daxtheduck))
|
|
24
|
+
|
|
25
|
+
#### Authors: 2
|
|
26
|
+
|
|
27
|
+
- Cursor Agent ([@cursoragent](https://github.com/cursoragent))
|
|
28
|
+
- Dax ([@daxtheduck](https://github.com/daxtheduck))
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
1
32
|
# v16.31.0 (Fri Aug 28 2026)
|
|
2
33
|
|
|
3
34
|
#### ⚠️ Pushed to `main`
|