Files
WRNexusJS/packages/uploader/test/uploader.test.ts
T
2026-07-27 12:42:18 +05:30

64 lines
2.1 KiB
TypeScript

import { expect, test } from "bun:test";
import { mkdtempSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import {
configureStorage,
createSignedFileToken,
getStore,
safeObjectKey,
serveStoredFile,
upload,
verifySignedFileToken,
} from "../src/index.ts";
function configure() {
configureStorage(
{ stores: { public: { driver: "local", access: "public", dir: "files" } } },
mkdtempSync(join(tmpdir(), "wrnexus-upload-")),
);
}
test("rejects unsafe upload prefixes before writing", async () => {
configure();
const form = new FormData();
form.set("file", new File(["hello"], "hello.txt", { type: "text/plain" }));
const request = new Request("http://local/upload", { method: "POST", body: form });
await expect(upload("public", request, { prefix: "../escape" })).rejects.toThrow(
"unsafe upload prefix",
);
});
test("public active content is attachment-only and cannot be MIME-sniffed", async () => {
configure();
await getStore("public").driver.put(
"safe/page.html",
new TextEncoder().encode("<script>x</script>"),
{
contentType: "text/html",
},
);
const response = await serveStoredFile("/__wrnexus/uploads/public/safe/page.html");
expect(response?.headers.get("x-content-type-options")).toBe("nosniff");
expect(response?.headers.get("content-disposition")).toStartWith("attachment");
});
test("safe object keys discard traversal-like prefixes", () => {
expect(safeObjectKey("report.pdf", "../../private/reports")).toMatch(/^private\/reports\//);
expect(safeObjectKey("report.pdf", "../..")).toMatch(/^uploads\//);
});
test("signed file tokens reject tampering and expired payloads", async () => {
const secret = "a-long-test-secret-for-files";
const token = await createSignedFileToken(
{ store: "private", key: "reports/a.pdf", expiresAt: 2_000 },
secret,
);
expect(await verifySignedFileToken(token, secret, 1_000)).toMatchObject({
store: "private",
key: "reports/a.pdf",
});
expect(await verifySignedFileToken(`${token}x`, secret, 1_000)).toBeNull();
expect(await verifySignedFileToken(token, secret, 2_000)).toBeNull();
});