Skip to content

Commit 8276ba0

Browse files
authored
Make cookies access safer (#2694)
1 parent 37d13d8 commit 8276ba0

File tree

7 files changed

+63
-22
lines changed

7 files changed

+63
-22
lines changed

.changeset/gorgeous-kiwis-check.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'gitbook': patch
3+
---
4+
5+
Make cookies access safer

packages/gitbook/src/components/Insights/InsightsProvider.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22

33
import type * as api from '@gitbook/api';
44
import { OpenAPIOperationContextProvider } from '@gitbook/react-openapi';
5-
import cookies from 'js-cookie';
65
import * as React from 'react';
76
import { useEventCallback, useDebounceCallback } from 'usehooks-ts';
87

8+
import * as cookies from '@/lib/cookies';
9+
910
import { getSession } from './sessions';
1011
import { getVisitorId } from './visitorId';
1112

@@ -197,7 +198,7 @@ export function InsightsProvider(props: InsightsProviderProps) {
197198
return () => {
198199
window.removeEventListener('beforeunload', flushEventsSync);
199200
};
200-
}, []);
201+
}, [flushEventsSync]);
201202

202203
return (
203204
<InsightsContext.Provider value={trackEvent}>
@@ -264,7 +265,7 @@ function transformEvents(input: {
264265
visitorId: input.visitorId,
265266
userAgent: window.navigator.userAgent,
266267
language: window.navigator.language,
267-
cookies: cookies.get(),
268+
cookies: cookies.getAll(),
268269
referrer: document.referrer || null,
269270
visitorAuthToken: input.visitorAuthToken ?? null,
270271
};
Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22

3-
import cookies from 'js-cookie';
3+
import * as cookies from '@/lib/cookies';
44

55
const GRANTED_COOKIE = '__gitbook_cookie_granted';
66

@@ -20,21 +20,13 @@ export function setCookiesTracking(enabled: boolean) {
2020
* Return `undefined` if state is not known.
2121
*/
2222
export function isCookiesTrackingDisabled() {
23-
try {
24-
const state = cookies.get(GRANTED_COOKIE);
23+
const state = cookies.get(GRANTED_COOKIE);
2524

26-
if (state === 'yes') {
27-
return false;
28-
} else if (state === 'no') {
29-
return true;
30-
}
31-
32-
return undefined;
33-
} catch (error) {
34-
// If there is a security error, we consider cookies as disabled
35-
if (error instanceof Error && error.name === 'SecurityError') {
36-
return true;
37-
}
38-
throw error;
25+
if (state === 'yes') {
26+
return false;
27+
} else if (state === 'no') {
28+
return true;
3929
}
30+
31+
return undefined;
4032
}

packages/gitbook/src/lib/analytics.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22

3-
import cookies from 'js-cookie';
3+
import * as cookies from '@/lib/cookies';
44

55
const VISITORID_COOKIE = '__session';
66
const GRANTED_COOKIE = '__gitbook_cookie_granted';

packages/gitbook/src/lib/cookies.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import cookies from 'js-cookie';
2+
3+
import { checkIsSecurityError } from './security-error';
4+
5+
export function getAll(): {
6+
[key: string]: string;
7+
} {
8+
try {
9+
return cookies.get();
10+
} catch (error) {
11+
if (checkIsSecurityError(error)) {
12+
return {};
13+
}
14+
throw error;
15+
}
16+
}
17+
18+
export function get(name: string): string | undefined {
19+
try {
20+
return cookies.get(name);
21+
} catch (error) {
22+
if (checkIsSecurityError(error)) {
23+
return undefined;
24+
}
25+
throw error;
26+
}
27+
}
28+
29+
export const set = cookies.set;

packages/gitbook/src/lib/local-storage.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { checkIsSecurityError } from './security-error';
2+
13
/**
24
* Get an item from local storage safely.
35
*/
@@ -9,7 +11,7 @@ export function getItem<T>(key: string, defaultValue: T): T {
911
}
1012
return defaultValue;
1113
} catch (error) {
12-
if (error instanceof Error && error.name === 'SecurityError') {
14+
if (checkIsSecurityError(error)) {
1315
return defaultValue;
1416
}
1517
throw error;
@@ -25,7 +27,7 @@ export function setItem(key: string, value: unknown) {
2527
localStorage.setItem(key, JSON.stringify(value));
2628
}
2729
} catch (error) {
28-
if (error instanceof Error && error.name === 'SecurityError') {
30+
if (checkIsSecurityError(error)) {
2931
return;
3032
}
3133
throw error;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* Test if the error is a security error returned by the browser when cookies or local storage are blocked.
3+
*/
4+
export function checkIsSecurityError(error: unknown): error is Error {
5+
return (
6+
error instanceof Error &&
7+
// Safari
8+
(error.name === 'SecurityError' ||
9+
// Firefox
10+
error.name === 'NS_ERROR_FAILURE')
11+
);
12+
}

0 commit comments

Comments
 (0)