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() {
{
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 && (