import { createHmac } from "node:crypto";
import { afterEach, describe, expect, it, vi } from "vitest";
import worker from "./index.js";
const SANDBOX_CSP = "default-src 'none'; style-src 'unsafe-inline'; sandbox";
const env = { CAMO_SHARED_SECRET: "s3cret" };
const signed = (url) =>
`https://camo.test/${createHmac("sha256", "s3cret").update(Buffer.from(url, "utf8")).digest("hex")}/${Buffer.from(url, "utf8").toString("hex")}`;
const serve = (url, fetch, match = async () => undefined, put = async () => {}) => {
vi.stubGlobal("fetch", fetch);
vi.stubGlobal("caches", { default: { match, put } });
return worker.fetch(new Request(signed(url)), env);
};
afterEach(() => vi.unstubAllGlobals());
describe("fetch", () => {
it("sandboxes an SVG with scripts in it", async () => {
const svg =
'<svg xmlns="http://www.w3.org/2000/svg"><script>alert(1)</script></svg>';
const fresh = await serve(
"https://ebilupstream.test/logo.svg",
vi.fn(async () =>
new Response(svg, { headers: { "Content-Type": "image/svg+xml" } }),
),
);
expect(fresh.status).toBe(200);
expect(fresh.headers.get("Content-Type")).toBe("image/svg+xml");
expect(fresh.headers.get("Content-Security-Policy")).toBe(SANDBOX_CSP);
expect(fresh.headers.get("X-Content-Type-Options")).toBe("nosniff");
const stored = new Response(svg, {
headers: {
"Content-Type": "image/svg+xml",
"Cache-Control": "public, max-age=86400, immutable",
},
});
const cached = await serve(
"https://ebilupstream.test/logo.svg",
vi.fn(),
async () => stored,
);
expect(cached.status).toBe(200);
expect(cached.headers.get("Content-Security-Policy")).toBe(SANDBOX_CSP);
expect(cached.headers.get("X-Content-Type-Options")).toBe("nosniff");
});
it("returns 415 for a type off the allowlist", async () => {
const res = await serve(
"https://ebilupstream.test/page",
vi.fn(async () =>
new Response("<html></html>", {
headers: { "Content-Type": "text/html" },
}),
),
);
expect(res.status).toBe(415);
});
});