mirror of
https://github.com/penpot/penpot.git
synced 2026-11-03 08:30:40 +00:00
Address the review findings on the DOMPurify SVG sanitization. F1: sanitizeSvg was synchronous and blocked the service's only event loop: a ~30 MiB SVG (the old cap) froze media-processor for ~20 s and peaked at ~3.4 GiB. The sanitizer now runs in a worker_threads pool (sanitizeSvgSync is the CPU-bound core), each worker has a resourceLimits heap cap so an OOM kills the worker and not the process, and a stuck job is terminated by a timeout and respawned. The default SVG cap drops to 2 MiB and is enforced in both modes (the backend validates the declared and the real size on upload, and the real bytes on import), so a file is accepted or rejected the same way with and without media-processor. F2: an unexpected sanitizer failure is logged and reported as 503 svg-sanitization-failed instead of 400 invalid-svg-file, so a service fault is not blamed on the user's file and no internal detail leaks in the hint. F4: the remote backend rejects a 2xx response that is not an SVG instead of storing it. Also pin the backend/service wire contract with a test that posts the exact multipart the JVM builds, and pin the data: URI behavior. AI-assisted-by: deepseek-v4.1-flash
18 lines
401 B
JavaScript
18 lines
401 B
JavaScript
import { build } from "esbuild";
|
|
|
|
await build({
|
|
entryPoints: ["src/index.ts", "src/svg-worker.ts"],
|
|
bundle: true,
|
|
platform: "node",
|
|
target: "node24",
|
|
format: "esm",
|
|
outdir: "dist",
|
|
external: ["sharp", "pino", "pino-pretty", "pino-loki", "dompurify", "jsdom"],
|
|
banner: {
|
|
js: `
|
|
import { createRequire } from 'node:module';
|
|
const require = createRequire(import.meta.url);
|
|
`,
|
|
},
|
|
});
|