import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import test from "node:test"; import { imageCDNBases, imageSourceURLs, validProfileImage, } from "../src/lib/media/image-source"; import { decodeImageBytes, decryptImageBytes, imageMime, resolveImage, } from "../src/lib/media/images"; const primary = "https://primary.images.test/assets/"; const backup = "https://backup.images.test/media/"; const signedPath = "v3/image/cover.jpg?ticket=a%2Bb%3D&expires=99&path=%2Ffoo"; const bytesOf = (path: string): Uint8Array => new Uint8Array(readFileSync(new URL(path, import.meta.url))); const png = bytesOf("../public/static/favicon.png"); const fixtures = [ ["PNG", "image/png", png], [ "JPEG", "image/jpeg", bytesOf("../public/static/images/profile/water-margin.jpg"), ], [ "WebP", "image/webp", new Uint8Array( Buffer.from("UklGRhwAAABXRUJQVlA4TBAAAAAvAAAAAAcQ/S9g/wMR0f8A", "base64"), ), ], [ "GIF", "image/gif", new Uint8Array( Buffer.from("R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7", "base64"), ), ], ] as const; const bufferOf = (bytes: Uint8Array): ArrayBuffer => Uint8Array.from(bytes).buffer; test("CDN bases retain deployment paths, deduplicate, and reject unsafe configuration", () => { assert.deepEqual( imageCDNBases( " https://primary.images.test/assets ", primary, "http://backup.images.test/media/", "https://user:secret@private.images.test/", "https://query.images.test/?token=secret", "https://hash.images.test/#fragment", "javascript:alert(1)", "data:image/png;base64,abc", "//relative.images.test/", "https://", "", null, 42, {}, ), [primary, "http://backup.images.test/media/"], ); }); test("relative API images use the CDN base or the site root on every page", () => { for (const source of [signedPath, "/" + signedPath]) { assert.deepEqual(imageSourceURLs(source), ["/" + signedPath]); assert.deepEqual(imageSourceURLs(source, [primary, backup]), [ primary + signedPath, backup + signedPath, ]); } }); test("absolute signed image URLs remain byte-for-byte intact and only configured CDN paths gain fallbacks", () => { const source = primary + signedPath; assert.deepEqual(imageSourceURLs(source, [primary, backup]), [ source, backup + signedPath, ]); assert.deepEqual(imageSourceURLs(backup + signedPath, [primary, backup]), [ backup + signedPath, source, ]); for (const outside of [ "https://external.images.test/" + signedPath, "https://primary.images.test/assets-other/" + signedPath, ]) assert.deepEqual(imageSourceURLs(outside, [primary, backup]), [outside]); }); test("static, inline and blob sources bypass rewriting while executable sources are rejected", () => { for (const source of [ "/static/brand/placeholder.svg?v=1", "data:image/png;base64,iVBORw0KGgo=", "blob:https://site.test/image-id", ]) assert.deepEqual(imageSourceURLs(source, [primary, backup]), [source]); for (const source of [ "javascript:alert(1)", "data:text/html,", "file:///private/image.png", "vbscript:msgbox(1)", "https://", "", ]) assert.deepEqual(imageSourceURLs(source, [primary, backup]), []); }); test("profile avatars accept real API image paths without accepting executable or malformed HTTP URLs", () => { for (const source of [ "https://avatars.images.test/face.jpg?signature=a%2Bb%3D", "http://avatars.images.test/face.png", "/static/images/profile/avatar.png?v=1", signedPath, "/" + signedPath, ]) assert.equal(validProfileImage(source), source); for (const source of [ null, 42, {}, "", "javascript:alert(1)", "data:text/html,unsafe", "https://", "http://[malformed", "https://bad host/image.png", "ordinary-relative-avatar.png", ]) assert.equal(validProfileImage(source), ""); }); test("image decoding accepts complete raw and legacy XOR images without mutating their input", () => { for (const [name, mime, original] of fixtures) { const plainBuffer = bufferOf(original); assert.deepEqual(decodeImageBytes(plainBuffer), original, name + " raw"); assert.equal(imageMime(decodeImageBytes(plainBuffer)), mime, name + " type"); assert.deepEqual(new Uint8Array(plainBuffer), original, name + " raw input"); const encrypted = decryptImageBytes(bufferOf(original)); const encryptedBuffer = bufferOf(encrypted); assert.deepEqual( decodeImageBytes(encryptedBuffer), original, name + " encrypted", ); assert.deepEqual( new Uint8Array(encryptedBuffer), encrypted, name + " encrypted input", ); } }); test("image decoding rejects empty bodies and non-image API error responses", () => { for (const value of [ "", '{"code":404,"data":null,"message":"image missing"}', "CDN unavailable", "upstream unavailable", ]) { const bytes = new TextEncoder().encode(value); assert.throws(() => decodeImageBytes(bufferOf(bytes)), value || "empty"); if (bytes.length) assert.throws(() => decodeImageBytes(bufferOf(decryptImageBytes(bufferOf(bytes)))), ); } }); test("image fetching validates bytes, retries alternate CDNs, and only caches successful images", async (t) => { const originalFetch = globalThis.fetch; const created: string[] = []; const responseFor = (bytes: Uint8Array, contentType = "image/png") => new Response(bufferOf(bytes), { headers: { "Content-Type": contentType } }); const captureBlob = async (url: string, expected: Uint8Array, mime: string) => { assert.match(url, /^blob:/); created.push(url); const response = await originalFetch(url); assert.equal(response.headers.get("content-type"), mime); assert.deepEqual(new Uint8Array(await response.arrayBuffer()), expected); }; try { await t.test("HTTP failure uses the next CDN and retains its successful cache", async () => { const path = "v3/image/http-fallback-20261012.png?signature=x%2By%3D"; const calls: string[] = []; globalThis.fetch = async (input) => { const url = String(input); calls.push(url); return url === primary + path ? new Response("CDN unavailable", { status: 503 }) : responseFor(decryptImageBytes(bufferOf(png))); }; const first = await resolveImage(path, true, [primary, backup]); await captureBlob(first, png, "image/png"); assert.deepEqual(calls, [primary + path, backup + path]); assert.equal(await resolveImage(path, false, [primary, backup]), first); assert.equal(calls.length, 2); }); await t.test("a JSON 200 response is rejected before trying the alternate CDN", async () => { const path = "v3/image/json-fallback-20261012.png"; const calls: string[] = []; globalThis.fetch = async (input) => { const url = String(input); calls.push(url); return url === primary + path ? new Response('{"code":404,"data":null}', { headers: { "Content-Type": "application/json" }, }) : responseFor(png); }; await captureBlob( await resolveImage(primary + path, false, [primary, backup]), png, "image/png", ); assert.deepEqual(calls, [primary + path, backup + path]); }); await t.test("a missing CDN roots the API path before requesting valid bytes", async () => { const path = "v3/image/no-cdn-20261012.png?signature=a%2Bb%3D"; const calls: string[] = []; globalThis.fetch = async (input) => { calls.push(String(input)); return responseFor(png); }; await captureBlob(await resolveImage(path), png, "image/png"); assert.deepEqual(calls, ["/" + path]); }); await t.test("invalid image responses are not cached and the same URL can recover", async () => { const source = "https://unconfigured.images.test/no-cache-20261012.png"; let count = 0; let recovered = false; globalThis.fetch = async () => { count++; return recovered ? responseFor(png) : new Response('{"code":500,"tip":"failed"}', { headers: { "Content-Type": "image/png" }, }); }; await assert.rejects(resolveImage(source)); await assert.rejects(resolveImage(source)); assert.equal(count, 2, "invalid responses must trigger a fresh request"); recovered = true; const resolved = await resolveImage(source); await captureBlob(resolved, png, "image/png"); assert.equal(count, 3); assert.equal(await resolveImage(source), resolved); assert.equal(count, 3, "successful bytes may be cached"); }); await t.test("non-image sources and illegal protocols never enter the image fetcher", async () => { let count = 0; globalThis.fetch = async () => { count++; throw new Error("Unexpected image request"); }; const source = "/static/brand/placeholder.svg?v=image-test"; assert.equal(await resolveImage(source), source); assert.equal(count, 0); await assert.rejects(resolveImage("javascript:alert(1)")); assert.equal(count, 0); }); } finally { globalThis.fetch = originalFetch; for (const url of created) URL.revokeObjectURL(url); } });