Files
openclaw/src/browser/csrf.test.ts

81 lines
1.9 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { shouldRejectBrowserMutation } from "./csrf.js";
describe("browser CSRF loopback mutation guard", () => {
it("rejects mutating methods from non-loopback origin", () => {
expect(
shouldRejectBrowserMutation({
method: "POST",
origin: "https://evil.example",
}),
).toBe(true);
});
it("allows mutating methods from loopback origin", () => {
expect(
shouldRejectBrowserMutation({
method: "POST",
origin: "http://127.0.0.1:18789",
}),
).toBe(false);
expect(
shouldRejectBrowserMutation({
method: "POST",
origin: "http://localhost:18789",
}),
).toBe(false);
});
it("allows mutating methods without origin/referer (non-browser clients)", () => {
expect(
shouldRejectBrowserMutation({
method: "POST",
}),
).toBe(false);
});
it("rejects mutating methods with origin=null", () => {
expect(
shouldRejectBrowserMutation({
method: "POST",
origin: "null",
}),
).toBe(true);
});
it("rejects mutating methods from non-loopback referer", () => {
expect(
shouldRejectBrowserMutation({
method: "POST",
referer: "https://evil.example/attack",
}),
).toBe(true);
});
it("rejects cross-site mutations via Sec-Fetch-Site when present", () => {
expect(
shouldRejectBrowserMutation({
method: "POST",
secFetchSite: "cross-site",
}),
).toBe(true);
});
it("does not reject non-mutating methods", () => {
expect(
shouldRejectBrowserMutation({
method: "GET",
origin: "https://evil.example",
}),
).toBe(false);
expect(
shouldRejectBrowserMutation({
method: "OPTIONS",
origin: "https://evil.example",
}),
).toBe(false);
});
});