diff --git a/electron/image-cache.test.cjs b/electron/image-cache.test.cjs index 498b6a3ec9..5cbb396b56 100644 --- a/electron/image-cache.test.cjs +++ b/electron/image-cache.test.cjs @@ -70,6 +70,39 @@ test('importImage copies a valid image and returns an opaque id', async () => { } }); +test('importImage accepts avif and bmp (restored legacy formats)', async () => { + const cache = load(); + const sourceDir = fsModule.realpathSync.native( + await fs.mkdtemp(path.join(os.tmpdir(), 'sp-src-')), + ); + try { + const avif = await mkPng(sourceDir, 'bg.avif', Buffer.from('fakeavif')); + const avifResult = await cache.importImage(avif); + assert.ok(avifResult); + assert.equal(avifResult.mimeType, 'image/avif'); + + const bmp = await mkPng(sourceDir, 'bg.bmp', Buffer.from('fakebmp')); + const bmpResult = await cache.importImage(bmp); + assert.ok(bmpResult); + assert.equal(bmpResult.mimeType, 'image/bmp'); + } finally { + await fs.rm(sourceDir, { recursive: true, force: true }); + } +}); + +test('importImage rejects svg (scriptable format deliberately excluded)', async () => { + const cache = load(); + const sourceDir = fsModule.realpathSync.native( + await fs.mkdtemp(path.join(os.tmpdir(), 'sp-src-')), + ); + try { + const svg = await mkPng(sourceDir, 'bg.svg', Buffer.from('')); + assert.equal(await cache.importImage(svg), null); + } finally { + await fs.rm(sourceDir, { recursive: true, force: true }); + } +}); + test('importImage returns null for a path inside userData (no laundering)', async () => { const cache = load(); const evilPath = await mkPng(userDataDir, 'planted.png'); diff --git a/electron/image-cache.ts b/electron/image-cache.ts index ce8681aa72..05ff88c7bf 100644 --- a/electron/image-cache.ts +++ b/electron/image-cache.ts @@ -33,12 +33,17 @@ import { assertPathOutside } from './file-path-guard'; const MAX_IMAGE_BYTES = 5 * 1024 * 1024; +// SVG is deliberately excluded: it is a scriptable format (can embed +//