From 66e50e22ccb66d8eba12e06da2d6ae4967c32870 Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Thu, 22 Oct 2026 00:24:41 -0700 Subject: [PATCH] fix(images): avoid backtracking in data URI parameter parsing (#31882) --- src/shared/image-data-uri.test.ts | 23 +++++++++++++++++++++++ src/shared/image-data-uri.ts | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/shared/image-data-uri.test.ts b/src/shared/image-data-uri.test.ts index 7e62cb0b3df..eec2de14713 100644 --- a/src/shared/image-data-uri.test.ts +++ b/src/shared/image-data-uri.test.ts @@ -1,3 +1,4 @@ +import { runInNewContext } from 'node:vm' import { describe, expect, it } from 'vitest' import { buildImageDataUri, validateRasterImageDataUri } from './image-data-uri' @@ -58,6 +59,28 @@ describe('buildImageDataUri', () => { }) describe('validateRasterImageDataUri', () => { + it('preserves malformed parameter lists without exponential backtracking', () => { + const input = `data:image/png;${';'.repeat(32_768)}` + const result = runInNewContext( + 'validate(input)', + { validate: validateRasterImageDataUri, input }, + { + timeout: 250 + } + ) + expect(result).toBe(input) + }) + + it('finds base64 among multiple parameters and preserves payload commas', () => { + const content = pngBase64() + expect(validateRasterImageDataUri(`data:image/png;charset=utf-8;;BASE64;,${content}`)).toBe( + `data:image/png;base64,${content}` + ) + expect(validateRasterImageDataUri('data:text/plain;charset=utf-8,one,two')).toBe( + 'data:text/plain;charset=utf-8,one,two' + ) + }) + it('accepts a safe inline raster and rejects an oversized one', () => { const safe = `data:image/png;base64,${pngBase64()}` expect(validateRasterImageDataUri(safe)).toBe(safe) diff --git a/src/shared/image-data-uri.ts b/src/shared/image-data-uri.ts index 2d0e351c847..5974c4d6dca 100644 --- a/src/shared/image-data-uri.ts +++ b/src/shared/image-data-uri.ts @@ -29,7 +29,7 @@ export function buildImageDataUri( /** Preserves non-raster data URIs and rejects unsafe known-raster data URIs. */ export function validateRasterImageDataUri(dataUri: string): string | null { - const match = /^data:([^;,]+)((?:;[^,]*)*),([\s\S]*)$/i.exec(dataUri) + const match = /^data:([^;,]+)((?:;[^,]*)?),([\s\S]*)$/i.exec(dataUri) if (!match || !isKnownRasterImageMimeType(match[1])) { return dataUri }