@duckduckgo/autoconsent 16.41.0 → 16.42.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.
@@ -28,13 +28,10 @@ npm run prepublish # builds dist/autoconsent.playwright.js and rules/rules.json
28
28
 
29
29
  Environment variables:
30
30
 
31
- - `REGIONAL_PROXY_<TWO_LETTER_REGION_CODE>` (for example, `REGIONAL_PROXY_US`, `REGIONAL_PROXY_GB`, `REGIONAL_PROXY_AU`, etc.) - the domain endpoint
32
- - `REGIONAL_PROXY_USERNAME`
33
- - `REGIONAL_PROXY_PASSWORD`
31
+ - `REGIONAL_PROXY_<TWO_LETTER_REGION_CODE>` (for example, `REGIONAL_PROXY_US`, `REGIONAL_PROXY_GB`, `REGIONAL_PROXY_AU`, etc.) - a complete proxy URL with an `http://`, `https://`, or `socks5://` scheme. Examples: `socks5://usc-socks-tr-cluster.duckduckgo.com:80`, `https://proxy.example.com:443`.
32
+ - `REGIONAL_PROXY_USERNAME` and `REGIONAL_PROXY_PASSWORD` (optional) - shared credentials, passed to Playwright for `https://` proxies only. They are ignored for `http://` and `socks5://` proxies.
34
33
 
35
- - Endpoints must be bare hostnames: no scheme, credentials, or port.
36
- - The library adds `https://` and port `443`.
37
- - Credentials are shared across regions.
34
+ Never embed credentials in a proxy URL.
38
35
 
39
36
  ## Usage
40
37
 
@@ -91,7 +88,7 @@ export default defineConfig({
91
88
  - `ALL_REGIONS` — all supported regions.
92
89
  - `testPage(page, url, regionKey, options?)` — run a full test on a page you created yourself (you own the browser/context); returns a `TestResult`.
93
90
  - `injectAutoconsent(page, options?)` — set up isolated-world injection; call before `page.goto()`. Returns a context (`received`, `hasMessage`, `waitForCompletion`, `waitForMessage`, `collectResult`).
94
- - `buildProxyConfig(regionKey)` — build the Playwright `{ server, username, password }` proxy object for a region from its env vars.
91
+ - `buildProxyConfig(regionKey)` — build the Playwright proxy object for a region from its env vars; returns `{ server, username, password }` for `https://` proxies when credentials are set, otherwise `{ server }`.
95
92
  - `launchRegionalProxyBrowser(regionKey, options?)` — launch a Chromium browser routed through the region's proxy.
96
93
  - `formatResult(result)` — format a `TestResult` as a human-readable summary line.
97
94
 
@@ -128,7 +125,7 @@ await browser.close();
128
125
 
129
126
  ## Gotchas
130
127
 
131
- - Use Playwright's proxy auth object: `{ server, username, password }`.
128
+ - HTTPS proxy credentials go in Playwright's proxy auth object (`{ server, username, password }`); Chromium cannot authenticate to SOCKS proxies.
132
129
  - Never embed proxy credentials in URLs, command lines, logs, traces, or source.
133
130
  - Call `injectAutoconsent(page)` before `page.goto()` so the init script is installed before page scripts run.
134
131
  - 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.
@@ -1,15 +1,14 @@
1
1
  /**
2
- * Playwright HTTPS regional proxy utilities for multi-region autoconsent testing.
2
+ * Playwright regional proxy utilities for multi-region autoconsent testing.
3
3
  *
4
- * Launches a local Chromium browser with an HTTPS proxy selected by region, injects
4
+ * Launches a local Chromium browser with a proxy selected by region, injects
5
5
  * autoconsent into an isolated world (via CDP), and evaluates opt-out/opt-in flows.
6
6
  * Chromium only - isolated worlds are reached through CDP, which Playwright exposes for
7
7
  * Chromium alone.
8
8
  *
9
9
  * Requires env vars:
10
- * - REGIONAL_PROXY_<REGION> (REGION is the uppercased two-letter region code)
11
- * - REGIONAL_PROXY_USERNAME
12
- * - REGIONAL_PROXY_PASSWORD
10
+ * - REGIONAL_PROXY_<REGION> (REGION is the uppercased two-letter region code): a complete proxy URL
11
+ * - REGIONAL_PROXY_USERNAME and REGIONAL_PROXY_PASSWORD (optional, used for https:// proxies only)
13
12
  */
14
13
 
15
14
  /**
@@ -95,7 +94,7 @@ export const EXPANDED_REGIONS = ['us', 'gb', 'de', 'fr', 'nl', 'pl', 'au', 'ca',
95
94
  * Build the Playwright proxy object for a region.
96
95
  * @param {string} regionKey - Two-letter region code (e.g. 'us', 'gb').
97
96
  * @param {NodeJS.ProcessEnv} [env]
98
- * @returns {{ server: string, username: string, password: string }}
97
+ * @returns {{ server: string, username?: string, password?: string }}
99
98
  */
100
99
  export function buildProxyConfig(regionKey, env = process.env) {
101
100
  const envVar = `REGIONAL_PROXY_${regionKey.toUpperCase()}`;
@@ -103,27 +102,28 @@ export function buildProxyConfig(regionKey, env = process.env) {
103
102
  const username = env.REGIONAL_PROXY_USERNAME;
104
103
  const password = env.REGIONAL_PROXY_PASSWORD;
105
104
 
106
- if (!endpoint || !username || !password) {
107
- throw new Error(
108
- `Missing proxy environment variables for region "${regionKey}". ` +
109
- `Expected ${envVar}, REGIONAL_PROXY_USERNAME, and REGIONAL_PROXY_PASSWORD.`,
110
- );
105
+ if (!endpoint) {
106
+ throw new Error(`Missing proxy environment variable for region "${regionKey}". Expected ${envVar}.`);
111
107
  }
112
- if (endpoint.includes('://') || endpoint.includes('@') || /:\d+$/.test(endpoint)) {
113
- throw new Error(
114
- `${envVar} should be a bare hostname without scheme, credentials, or port. ` + 'The library adds https:// and port 443.',
115
- );
108
+ if (!endpoint.includes('://')) {
109
+ throw new Error(`${envVar} must be a complete proxy URL (http://, https://, or socks5://).`);
116
110
  }
117
-
118
- return {
119
- server: `https://${endpoint}:443`,
120
- username,
121
- password,
122
- };
111
+ const parsed = new URL(endpoint);
112
+ if (!['http:', 'https:', 'socks5:'].includes(parsed.protocol)) {
113
+ throw new Error(`${envVar} has unsupported proxy protocol "${parsed.protocol}".`);
114
+ }
115
+ if (parsed.username || parsed.password) {
116
+ throw new Error(`${envVar} must not contain embedded proxy credentials.`);
117
+ }
118
+ // Credentials are only used for HTTPS proxies; Chromium cannot authenticate to SOCKS proxies.
119
+ if (parsed.protocol === 'https:' && username && password) {
120
+ return { server: endpoint, username, password };
121
+ }
122
+ return { server: endpoint };
123
123
  }
124
124
 
125
125
  /**
126
- * Launch a local Playwright browser through the HTTPS proxy for a region.
126
+ * Launch a local Playwright browser through the proxy for a region.
127
127
  * @param {string} regionKey
128
128
  * @param {Partial<TestOptions>} [options]
129
129
  * @returns {Promise<Browser>}
@@ -0,0 +1,61 @@
1
+ import assert from 'node:assert/strict';
2
+ import { describe, it } from 'node:test';
3
+
4
+ import { buildProxyConfig } from './regional-proxy.mjs';
5
+
6
+ const credentials = {
7
+ REGIONAL_PROXY_PASSWORD: 'password',
8
+ REGIONAL_PROXY_USERNAME: 'username',
9
+ };
10
+
11
+ describe('regional proxy config', () => {
12
+ it('uses complete credential-free SOCKS URLs directly', () => {
13
+ assert.deepEqual(
14
+ buildProxyConfig('us', {
15
+ REGIONAL_PROXY_US: 'socks5://usc-socks-tr-cluster.duckduckgo.com:80',
16
+ }),
17
+ { server: 'socks5://usc-socks-tr-cluster.duckduckgo.com:80' },
18
+ );
19
+ });
20
+
21
+ it('passes credentials for HTTPS proxies', () => {
22
+ assert.deepEqual(buildProxyConfig('de', { REGIONAL_PROXY_DE: 'https://proxy.example:443', ...credentials }), {
23
+ password: 'password',
24
+ server: 'https://proxy.example:443',
25
+ username: 'username',
26
+ });
27
+ });
28
+
29
+ it('allows HTTPS proxies without credentials', () => {
30
+ assert.deepEqual(buildProxyConfig('de', { REGIONAL_PROXY_DE: 'https://proxy.example:443' }), {
31
+ server: 'https://proxy.example:443',
32
+ });
33
+ });
34
+
35
+ it('does not pass credentials for non-HTTPS proxies', () => {
36
+ assert.deepEqual(buildProxyConfig('us', { REGIONAL_PROXY_US: 'socks5://proxy.example:80', ...credentials }), {
37
+ server: 'socks5://proxy.example:80',
38
+ });
39
+ assert.deepEqual(buildProxyConfig('us', { REGIONAL_PROXY_US: 'http://proxy.example:3128', ...credentials }), {
40
+ server: 'http://proxy.example:3128',
41
+ });
42
+ });
43
+
44
+ it('rejects credentials embedded in URLs', () => {
45
+ assert.throws(
46
+ () => buildProxyConfig('us', { REGIONAL_PROXY_US: 'socks5://user:password@proxy.example:80' }),
47
+ /must not contain embedded proxy credentials/,
48
+ );
49
+ });
50
+
51
+ it('requires a protocol', () => {
52
+ assert.throws(
53
+ () => buildProxyConfig('gb', { REGIONAL_PROXY_GB: 'uks.socks.duckduckgo.com', ...credentials }),
54
+ /must be a complete proxy URL/,
55
+ );
56
+ });
57
+
58
+ it('rejects unsupported protocols', () => {
59
+ assert.throws(() => buildProxyConfig('gb', { REGIONAL_PROXY_GB: 'socks4://proxy.example:1080' }), /unsupported proxy protocol/);
60
+ });
61
+ });
package/CHANGELOG.md CHANGED
@@ -1,3 +1,22 @@
1
+ # v16.42.0 (Fri Sep 25 2026)
2
+
3
+ #### Rules
4
+
5
+ - Rule update: CPM crawl cluster #90: mediaset.it (iubenda|inert, 13 sites) [#1484](https://github.com/duckduckgo/autoconsent/pull/1484) ([@cursoragent](https://github.com/cursoragent) [@daxtheduck](https://github.com/daxtheduck))
6
+
7
+ #### AI / Agent Workflow
8
+
9
+ - update proxy skill to support internal access [#1577](https://github.com/duckduckgo/autoconsent/pull/1577) ([@ladamski](https://github.com/ladamski) [@muodov](https://github.com/muodov))
10
+
11
+ #### Authors: 4
12
+
13
+ - Cursor Agent ([@cursoragent](https://github.com/cursoragent))
14
+ - Dax ([@daxtheduck](https://github.com/daxtheduck))
15
+ - Lucas Adamski ([@ladamski](https://github.com/ladamski))
16
+ - Maxim Tsoy ([@muodov](https://github.com/muodov))
17
+
18
+ ---
19
+
1
20
  # v16.41.0 (Tue Sep 22 2026)
2
21
 
3
22
  #### Rules