Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions src/components/platformSelector/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
} from 'react';
import {PlatformIcon} from 'sentry-docs/components/platformIcon';
import {Platform, PlatformGuide, PlatformIntegration} from 'sentry-docs/types';
import {uniqByReference} from 'sentry-docs/utils';
import {isLocalStorageAvailable, uniqByReference} from 'sentry-docs/utils';

import {SidebarLink, SidebarSeparator} from '../sidebar/sidebarLink';
import styles from './style.module.scss';
Expand Down Expand Up @@ -116,7 +116,9 @@ export function PlatformSelector({
platform => platform.key === platformKey.replace('-redirect', '')
);
if (platform_) {
localStorage.setItem('active-platform', platform_.key);
if (isLocalStorageAvailable()) {
localStorage.setItem('active-platform', platform_.key);
}
Comment on lines +119 to +121

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The isLocalStorageAvailable() check is unsafe. In environments like Safari private browsing, the typeof localStorage check will itself throw an error, causing a crash instead of preventing one.
Severity: HIGH

Suggested Fix

Update the isLocalStorageAvailable utility to use a try-catch block. The implementation should attempt a real operation, like setting and removing a test item, to reliably determine if localStorage is accessible and writable. For example: try { localStorage.setItem('__test__', '1'); localStorage.removeItem('__test__'); return true; } catch { return false; }.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: src/components/platformSelector/index.tsx#L119-L121

Potential issue: The utility function `isLocalStorageAvailable()` uses `typeof
localStorage !== 'undefined'` to check for the availability of local storage. However,
in certain environments with strict privacy settings, such as Safari's private browsing
mode, accessing the `localStorage` object itself throws a `SecurityError` or
`ReferenceError`. The `typeof` operator does not prevent this, as it must access the
property to evaluate its type, which triggers the error. Consequently, the guard check
`isLocalStorageAvailable()` will crash the application in these environments, defeating
its purpose of preventing crashes when accessing `localStorage`.

Also affects:

  • src/components/platformSelector/index.tsx:150~152
  • src/components/platformSelector/index.tsx:397~399
  • src/components/platformSelector/index.tsx:521~523

Did we get this right? 👍 / 👎 to inform future reviews.

// Use hard navigation for faster page load
window.location.href = platform_.url;
}
Expand Down Expand Up @@ -145,6 +147,9 @@ export function PlatformSelector({
}, []);

useLayoutEffect(() => {
if (!isLocalStorageAvailable()) {
return;
}
if (currentPlatformKey) {
localStorage.setItem('active-platform', currentPlatformKey);
} else {
Expand Down Expand Up @@ -389,7 +394,9 @@ function PlatformItem({
style={{cursor: 'pointer', display: 'flex', alignItems: 'center'}}
onClick={() => {
if (typeof window !== 'undefined') {
localStorage.setItem('active-platform', platform.key);
if (isLocalStorageAvailable()) {
localStorage.setItem('active-platform', platform.key);
}
window.location.href = platform.url;
}
}}
Expand Down Expand Up @@ -511,7 +518,9 @@ function GuideItem({guide, dropdownStyle = false, listOnly = false}: GuideItemPr
}}
onClick={() => {
if (typeof window !== 'undefined') {
localStorage.setItem('active-platform', guide.key);
if (isLocalStorageAvailable()) {
localStorage.setItem('active-platform', guide.key);
}
window.location.href = guide.url;
}
}}
Expand Down
Loading