From c4e11a52df5d9df69cd577b5e872e972cfda8b1d Mon Sep 17 00:00:00 2001 From: jom-sq <148157197+jom-sq@users.noreply.github.com> Date: Mon, 3 Nov 2025 11:00:30 -0500 Subject: [PATCH] fix(ui): add validation for custom colors from localStorage Add security validation to prevent malicious or invalid hex colors from being applied when loaded from localStorage. Security improvements: - Validate custom color in ThemeSelector before setting to state - Validate custom color in index.html before applying theme - Prevent potential XSS vulnerabilities from malicious localStorage content Code quality improvements: - Add explanatory comments for HSL to RGB conversion magic numbers - Improve code clarity with inline documentation Addresses feedback from code review regarding input validation and security best practices. Signed-off-by: jom-sq <148157197+jom-sq@users.noreply.github.com> --- ui/desktop/index.html | 12 ++++++++---- .../src/components/GooseSidebar/ThemeSelector.tsx | 12 ++++++++++-- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/ui/desktop/index.html b/ui/desktop/index.html index 2f03d59269..fc58a5900e 100644 --- a/ui/desktop/index.html +++ b/ui/desktop/index.html @@ -25,7 +25,11 @@ // Apply custom theme colors if enabled const customThemeEnabled = localStorage.getItem('custom_theme_enabled') === 'true'; if (customThemeEnabled) { - const customColor = localStorage.getItem('custom_theme_color') || '#32353b'; + let customColor = localStorage.getItem('custom_theme_color') || '#32353b'; + // Validate the color before applying it + if (!hexToRgb(customColor)) { + customColor = '#32353b'; + } applyCustomThemeColors(customColor, isDark); } } else { @@ -78,9 +82,9 @@ const hue2rgb = (p, q, t) => { if (t < 0) t += 1; if (t > 1) t -= 1; - if (t < 1/6) return p + (q - p) * 6 * t; - if (t < 1/2) return q; - if (t < 2/3) return p + (q - p) * (2/3 - t) * 6; + if (t < 1/6) return p + (q - p) * 6 * t; // Hue in red-yellow range + if (t < 1/2) return q; // Hue in yellow-green range + if (t < 2/3) return p + (q - p) * (2/3 - t) * 6; // Hue in green-blue range return p; }; const q = l < 0.5 ? l * (1 + s) : l + s - l * s; diff --git a/ui/desktop/src/components/GooseSidebar/ThemeSelector.tsx b/ui/desktop/src/components/GooseSidebar/ThemeSelector.tsx index de1a50bb04..9c3c0422d8 100644 --- a/ui/desktop/src/components/GooseSidebar/ThemeSelector.tsx +++ b/ui/desktop/src/components/GooseSidebar/ThemeSelector.tsx @@ -3,7 +3,12 @@ import { Moon, Sliders, Sun, Palette, type LucideIcon } from 'lucide-react'; import { Button } from '../ui/button'; import { Switch } from '../ui/switch'; import { CustomColorPicker } from './CustomColorPicker'; -import { applyCustomTheme, resetThemeColors, DEFAULT_THEME_COLOR } from '../../utils/colorUtils'; +import { + applyCustomTheme, + resetThemeColors, + DEFAULT_THEME_COLOR, + isValidHexColor, +} from '../../utils/colorUtils'; import { cn } from '../../utils'; interface ThemeSelectorProps { @@ -68,7 +73,10 @@ export function ThemeSelector({ } if (e.key === 'custom_theme_color' && e.newValue) { - setCustomColor(e.newValue); + // Validate the color before setting it to state + if (isValidHexColor(e.newValue)) { + setCustomColor(e.newValue); + } } if (e.key === 'custom_theme_enabled') {