import { describe, expect, it } from "vitest"; import { validateImageDataUrl } from "../lib/image-validation.js"; const PNG_HEADER = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]; const PNG_IEND = [0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82]; const JPEG_HEADER = [0xff, 0xd8, 0xff, 0xe0]; const JPEG_EOI = [0xff, 0xd9]; function dataUrl(mime: string, bytes: number[]): string { const base64 = Buffer.from(Uint8Array.from(bytes)).toString("base64"); return `data:${mime};base64,${base64}`; } describe("validateImageDataUrl", () => { it("accepts a minimal well-formed PNG", () => { const bytes = [...PNG_HEADER, 0x00, 0x00, 0x00, 0x00, ...PNG_IEND]; expect(validateImageDataUrl(dataUrl("image/png", bytes))).toEqual({ valid: true }); }); it("accepts a minimal well-formed JPEG", () => { const bytes = [...JPEG_HEADER, 0x00, 0x00, ...JPEG_EOI]; expect(validateImageDataUrl(dataUrl("image/jpeg", bytes))).toEqual({ valid: true }); }); it("rejects SVG uploads explicitly", () => { const svgBytes = Buffer.from("", "utf8"); const base64 = svgBytes.toString("base64"); const result = validateImageDataUrl(`data:image/svg+xml;base64,${base64}`); expect(result.valid).toBe(false); if (!result.valid) expect(result.reason).toMatch(/SVG/i); }); it("rejects a polyglot PNG with an HTML tail after IEND", () => { const html = Buffer.from("", "utf8"); const bytes = [...PNG_HEADER, 0x00, 0x00, 0x00, 0x00, ...PNG_IEND, ...Array.from(html)]; const result = validateImageDataUrl(dataUrl("image/png", bytes)); expect(result.valid).toBe(false); // Either the IEND-trailer check or the polyglot scan is acceptable — both // reject the payload before it reaches storage. A tail after IEND naturally // fails the trailer check first. if (!result.valid) expect(result.reason).toMatch(/IEND|polyglot/i); }); it("rejects a PNG that does not end with IEND", () => { // Declare PNG and include header but truncate before IEND const bytes = [...PNG_HEADER, 0x00, 0x00, 0x00, 0x00]; const result = validateImageDataUrl(dataUrl("image/png", bytes)); expect(result.valid).toBe(false); if (!result.valid) expect(result.reason).toMatch(/IEND/); }); it("rejects a JPEG that does not end with the EOI marker", () => { const bytes = [...JPEG_HEADER, 0x00, 0x00]; const result = validateImageDataUrl(dataUrl("image/jpeg", bytes)); expect(result.valid).toBe(false); if (!result.valid) expect(result.reason).toMatch(/EOI/); }); it("rejects a MIME/content mismatch", () => { const bytes = [...PNG_HEADER, 0x00, ...PNG_IEND]; const result = validateImageDataUrl(dataUrl("image/jpeg", bytes)); expect(result.valid).toBe(false); if (!result.valid) expect(result.reason).toMatch(/mismatch/i); }); it("rejects a javascript: URL embedded in an EXIF-like comment", () => { const marker = Buffer.from("javascript:alert(1)", "utf8"); const bytes = [...JPEG_HEADER, ...Array.from(marker), ...JPEG_EOI]; const result = validateImageDataUrl(dataUrl("image/jpeg", bytes)); expect(result.valid).toBe(false); if (!result.valid) expect(result.reason).toMatch(/polyglot/i); }); it("rejects a non-data-URL string", () => { expect(validateImageDataUrl("not a data url").valid).toBe(false); }); it("rejects an empty decoded buffer", () => { const result = validateImageDataUrl("data:image/png;base64,"); expect(result.valid).toBe(false); }); });