Skip to content

Commit 38bd809

Browse files
committed
warn and fallback when cookieOptions.domain is a Public Suffix List entry
1 parent 811e701 commit 38bd809

3 files changed

Lines changed: 32 additions & 0 deletions

File tree

packages/script/src/base.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@
1010
// Common script attributes
1111
const API_HOST = script.getAttribute('data-api-host') || 'https://api.dub.co';
1212
const PUBLISHABLE_KEY = script.getAttribute('data-publishable-key');
13+
// Domains on the Public Suffix List that browsers treat as TLDs.
14+
// Cookies cannot be set on these domains — the browser silently drops them.
15+
const KNOWN_PSL_DOMAINS = [
16+
'vercel.app', 'vercel.dev', 'vercel.run', 'now.sh', 'v0.build',
17+
'vusercontent.net', 'netlify.app', 'pages.dev', 'github.io', 'fly.dev',
18+
'railway.app', 'onrender.com', 'web.app', 'firebaseapp.com',
19+
'surge.sh', 'azurewebsites.net', 'amplifyapp.com',
20+
];
21+
1322
const COOKIE_OPTIONS = (() => {
1423
const defaultOptions = {
1524
domain:
@@ -32,6 +41,19 @@
3241
delete parsedOpts.expiresInDays;
3342
}
3443

44+
if (parsedOpts.domain) {
45+
const bare = parsedOpts.domain.replace(/^\./, '');
46+
if (KNOWN_PSL_DOMAINS.includes(bare)) {
47+
console.warn(
48+
`[dubAnalytics] cookieOptions.domain "${parsedOpts.domain}" is on the Public Suffix List. ` +
49+
`Browsers silently reject cookies set on PSL domains. ` +
50+
`Falling back to the default domain "${defaultOptions.domain}". ` +
51+
`Cross-subdomain cookie sharing under a PSL domain is not possible via client-side cookies.`,
52+
);
53+
delete parsedOpts.domain;
54+
}
55+
}
56+
3557
return { ...defaultOptions, ...parsedOpts };
3658
})();
3759

packages/web/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ The `cookieOptions` prop accepts the following keys:
7070
| `expiresInDays` | `90` | Specifies the number (in days) to be the value for the `Expires` Set-Cookie attribute. | `90` |
7171
| `path` | `/` | Specifies the value for the `Path` Set-Cookie attribute. By default, the path is considered the "default path". | `/` |
7272

73+
> **Note:** Domains on the [Public Suffix List](https://publicsuffix.org/) (PSL) — such as `.vercel.app`, `.netlify.app`, `.github.io`, or `.pages.dev`**cannot** be used as cookie domains. Browsers silently reject cookies set on PSL entries because these suffixes are treated like top-level domains (`.com`, `.io`). If you pass a PSL domain, the script will log a `console.warn` and fall back to the current hostname. Cross-subdomain cookie sharing under a PSL domain is not achievable via client-side cookies.
74+
7375
For example, to set a 60-day cookie window, you can use the following code:
7476

7577
```tsx

packages/web/src/types.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,14 @@ export interface AnalyticsProps {
5959
* By default, the domain is set to the current hostname (including all subdomains).
6060
*
6161
* @default `.` + window.location.hostname
62+
*
63+
* **Warning:** Domains listed on the {@link https://publicsuffix.org/|Public Suffix List} (PSL) —
64+
* such as `.vercel.app`, `.netlify.app`, `.github.io`, or `.pages.dev` — cannot be used as
65+
* cookie domains. Browsers silently reject `document.cookie` writes that target a PSL entry,
66+
* because these suffixes are treated equivalently to top-level domains like `.com`.
67+
* If you provide a PSL domain, the script will log a warning and fall back to the default
68+
* hostname-derived domain. Cross-subdomain cookie sharing under a PSL domain is not achievable
69+
* via client-side cookies.
6270
*/
6371
domain?: string | undefined;
6472

0 commit comments

Comments
 (0)