first commit
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
import { afterEach, expect, test } from "bun:test";
|
||||
import { s3Driver } from "../src/index.ts";
|
||||
|
||||
const originalFetch = globalThis.fetch;
|
||||
afterEach(() => {
|
||||
globalThis.fetch = originalFetch;
|
||||
});
|
||||
|
||||
const config = {
|
||||
driver: "s3" as const,
|
||||
access: "public" as const,
|
||||
bucket: "bucket",
|
||||
region: "auto",
|
||||
accessKeyId: "key",
|
||||
secretAccessKey: "secret",
|
||||
endpoint: "https://storage.example.com/base/",
|
||||
};
|
||||
|
||||
test("S3 driver preserves endpoint path prefixes and signs encoded keys", async () => {
|
||||
let url = "";
|
||||
let init: RequestInit | undefined;
|
||||
globalThis.fetch = (async (input: string | URL | Request, options?: RequestInit) => {
|
||||
url = String(input);
|
||||
init = options;
|
||||
return new Response(null, { status: 204 });
|
||||
}) as unknown as typeof fetch;
|
||||
await s3Driver(config).put("folder/a b.txt", new TextEncoder().encode("x"), {
|
||||
contentType: "text/plain",
|
||||
});
|
||||
expect(url).toBe("https://storage.example.com/base/bucket/folder/a%20b.txt");
|
||||
expect(new Headers(init?.headers).get("authorization")).toStartWith("AWS4-HMAC-SHA256");
|
||||
});
|
||||
|
||||
test("S3 driver rejects unsafe configuration early", () => {
|
||||
expect(() => s3Driver({ ...config, bucket: "../bucket" })).toThrow("bucket");
|
||||
expect(() => s3Driver({ ...config, endpoint: "ftp://storage.example.com" })).toThrow(
|
||||
"http or https",
|
||||
);
|
||||
expect(() =>
|
||||
s3Driver({ ...config, endpoint: "https://storage.example.com/base", forcePathStyle: false }),
|
||||
).toThrow("path prefix");
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
import { expect, test } from "bun:test";
|
||||
import { mkdtempSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { configureStorage, getStore, serveStoredFile, upload } 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");
|
||||
});
|
||||
Reference in New Issue
Block a user