Files
HiveGrid-Wireframes/03 Quellen und Referenzen/hivegrid-cloud/server/request-origin.test.ts
T

55 lines
2.4 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { validateMutationOrigin } from "./request-origin";
describe("web mutation origin gate", () => {
it.each(["GET", "HEAD", "OPTIONS"])("allows safe %s requests", (method) => {
expect(validateMutationOrigin(new Request("https://app.example.test/acme", { method }))).toMatchObject({ allowed: true, reason: "safe-method" });
});
it("allows same-origin browser mutations", () => {
const request = new Request("https://app.example.test/acme/settings", {
method: "POST",
headers: { origin: "https://app.example.test", "sec-fetch-site": "same-origin" },
});
expect(validateMutationOrigin(request)).toEqual({ allowed: true, reason: "same-origin" });
});
it("rejects cross-site browser mutations before route actions", () => {
const request = new Request("https://app.example.test/acme/settings", {
method: "POST",
headers: { origin: "https://evil.example", "sec-fetch-site": "cross-site" },
});
expect(validateMutationOrigin(request)).toEqual({ allowed: false, reason: "cross-site" });
});
it("rejects sibling-subdomain cookie tossing and CSRF", () => {
const request = new Request("https://admin.example.test/settings", {
method: "POST",
headers: { origin: "https://compromised.example.test", "sec-fetch-site": "same-site" },
});
expect(validateMutationOrigin(request)).toEqual({ allowed: false, reason: "origin-mismatch" });
});
it("uses the referer origin when Origin is unavailable", () => {
const request = new Request("https://app.example.test/acme/settings", {
method: "POST",
headers: { referer: "https://app.example.test/acme/profile" },
});
expect(validateMutationOrigin(request)).toEqual({ allowed: true, reason: "same-origin" });
});
it("allows signed non-browser integrations to reach route authentication", () => {
const request = new Request("https://app.example.test/internal/webhook", { method: "POST" });
expect(validateMutationOrigin(request)).toEqual({ allowed: true, reason: "non-browser" });
});
it("fails closed for browser mutations that omit all origin evidence", () => {
const request = new Request("https://app.example.test/acme/settings", {
method: "POST",
headers: { "sec-fetch-site": "same-site" },
});
expect(validateMutationOrigin(request)).toEqual({ allowed: false, reason: "browser-origin-missing" });
});
});