import { describe, expect, mock, test } from "bun:test";
mock.module("cloudflare:workers", () => ({
env: { SECRETS_KEY: "test-secret", PUBLIC_URL: "https://forge.example.com" },
}));
const { camoUrl, proxiableImageUrl, verifyCamoPath } = await import("./camo-sign");
describe("camo signing", () => {
test("signs http(s) URLs and verifies them back", () => {
const path = camoUrl("https://img.example.com/a.png?x=1#frag");
expect(path).toMatch(/^\/camo\/[0-9a-f]{64}\/[0-9a-f]+$/);
expect(verifyCamoPath(path ?? "")).toBe("https://img.example.com/a.png?x=1");
});
test("never proxies the forge itself and only accepts lowercase hex", () => {
expect(camoUrl("https://forge.example.com/acme/app/raw/main/x.png")).toBeNull();
expect(camoUrl("https://forge.example.com./x.png")).toBeNull();
const path = camoUrl("https://img.example.com/a.png") ?? "";
expect(verifyCamoPath(path.toUpperCase().replace("/CAMO/", "/camo/"))).toBeNull();
});
test("rejects non-http schemes, credentials and overlong URLs", () => {
expect(camoUrl("javascript:alert(1)")).toBeNull();
expect(camoUrl("data:image/png;base64,AAAA")).toBeNull();
expect(camoUrl("file:///etc/passwd")).toBeNull();
expect(camoUrl("https://user:pw@img.example.com/a.png")).toBeNull();
expect(camoUrl(`https://img.example.com/${"a".repeat(3000)}`)).toBeNull();
expect(proxiableImageUrl("/relative.png")).toBeNull();
});
test("tampered signature or URL fails verification", () => {
const path = camoUrl("https://img.example.com/a.png") ?? "";
const [, , signature, urlHex] = path.split("/");
const flipped = (signature.startsWith("0") ? "1" : "0") + signature.slice(1);
expect(verifyCamoPath(`/camo/${flipped}/${urlHex}`)).toBeNull();
expect(verifyCamoPath(`/camo/${signature}/${urlHex}00`)).toBeNull();
expect(verifyCamoPath(`/camo/${signature}/${urlHex}/extra`)).toBeNull();
expect(verifyCamoPath(`/camo/${signature}/zz`)).toBeNull();
expect(verifyCamoPath("/camo/")).toBeNull();