From ae6eb695f31fa579a2046722ac7240a82edad2f4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 7 Sep 2026 10:24:56 +0000 Subject: [PATCH] Address wallpaper review feedback: curated id validation, referrer policy, GIF, bitmap leak Co-authored-by: mroxso <24775431+mroxso@users.noreply.github.com> --- src/apps/settings/index.tsx | 14 ++++++++++---- src/components/os/Desktop.tsx | 34 ++++++++++++++++++++++++++++++---- src/lib/wallpaper.test.ts | 5 +++++ src/lib/wallpaper.ts | 10 ++++++++-- 4 files changed, 53 insertions(+), 10 deletions(-) diff --git a/src/apps/settings/index.tsx b/src/apps/settings/index.tsx index 8d47758..668a699 100644 --- a/src/apps/settings/index.tsx +++ b/src/apps/settings/index.tsx @@ -164,7 +164,9 @@ function AppearanceSection() { const MAX_WALLPAPER_FILE_BYTES = 5 * 1024 * 1024; const MAX_WALLPAPER_DIMENSION = 6000; -const ALLOWED_WALLPAPER_TYPES = new Set(['image/jpeg', 'image/png', 'image/webp', 'image/gif']); +// GIFs are excluded: the upload path always re-encodes to JPEG, which would +// silently drop animation/transparency, so we don't advertise GIF support. +const ALLOWED_WALLPAPER_TYPES = new Set(['image/jpeg', 'image/png', 'image/webp']); export function WallpaperSection() { const { config, updateConfig } = useAppContext(); @@ -237,7 +239,7 @@ export function WallpaperSection() { if (!file) return; if (!ALLOWED_WALLPAPER_TYPES.has(file.type)) { - toast({ title: 'Unsupported image type', description: 'Use JPEG, PNG, WebP, or GIF.', variant: 'destructive' }); + toast({ title: 'Unsupported image type', description: 'Use JPEG, PNG, or WebP.', variant: 'destructive' }); return; } if (file.size > MAX_WALLPAPER_FILE_BYTES) { @@ -264,7 +266,10 @@ export function WallpaperSection() { canvas.width = bitmap.width; canvas.height = bitmap.height; const ctx = canvas.getContext('2d'); - if (!ctx) throw new Error('This browser cannot process images.'); + if (!ctx) { + bitmap.close(); + throw new Error('This browser cannot process images.'); + } ctx.drawImage(bitmap, 0, 0); bitmap.close(); @@ -355,7 +360,7 @@ export function WallpaperSection() { { void onFileSelected(event.target.files?.[0]); }} @@ -382,6 +387,7 @@ export function WallpaperSection() { Wallpaper preview { updateConfig((current) => ({ ...current, wallpaper: { version: 1, selection: { source: 'curated', id } } })); }, [updateConfig]); @@ -179,15 +204,16 @@ export function Desktop() { src={safeWallpaperImageUrl} alt="" aria-hidden="true" + referrerPolicy="no-referrer" className={cn( 'pointer-events-none absolute inset-0 h-full w-full', - customWallpaper.presentation.fit === 'contain' ? 'object-contain' : 'object-cover', + renderedPresentation.fit === 'contain' ? 'object-contain' : 'object-cover', )} /> - {customWallpaper.presentation.dim > 0 && ( + {renderedPresentation.dim > 0 && (