fix(auth): bind current local registry and CORS

This commit is contained in:
2026-08-17 00:34:58 +02:00
parent c34e01e9b9
commit 94c2cd3709
15 changed files with 514 additions and 87 deletions
+33 -9
View File
@@ -47,19 +47,30 @@ afterAll(async () => {
test.each(stateChangingRoutes)(
"$family $method $url rejects every production CSRF/session-boundary failure before downstream code",
async ({ method, url }) => {
const failures = [
fixture.sessionHeaders({ "x-thothii-csrf": undefined }),
fixture.sessionHeaders({ "x-thothii-csrf": "malformed" }),
fixture.sessionHeaders({ origin: undefined }),
fixture.sessionHeaders({ origin: "http://wrong.example.test" }),
fixture.sessionHeaders({ "sec-fetch-site": "cross-site" }),
const failures: Array<{ expectedStatus: number; headers: Record<string, string> }> = [
{ expectedStatus: 403, headers: fixture.sessionHeaders({ "x-thothii-csrf": undefined }) },
{ expectedStatus: 403, headers: fixture.sessionHeaders({ "x-thothii-csrf": "malformed" }) },
{ expectedStatus: 403, headers: fixture.sessionHeaders({ "x-thothii-csrf": `${fixture.csrfToken}, ${fixture.csrfToken}` }) },
{ expectedStatus: 403, headers: fixture.sessionHeaders({ "x-thothii-csrf": "x".repeat(4097) }) },
{ expectedStatus: 401, headers: fixture.sessionHeaders({ cookie: undefined }) },
{ expectedStatus: 401, headers: fixture.sessionHeaders({ cookie: "thothii_session=not-a-token" }) },
{ expectedStatus: 401, headers: fixture.sessionHeaders({ cookie: `${fixture.cookie}; ${fixture.cookie}` }) },
{ expectedStatus: 401, headers: fixture.sessionHeaders({ cookie: `${fixture.cookie}; padding=${"x".repeat(4097)}` }) },
{ expectedStatus: 403, headers: fixture.sessionHeaders({ origin: undefined }) },
{ expectedStatus: 403, headers: fixture.sessionHeaders({ origin: "http://wrong.example.test" }) },
{ expectedStatus: 403, headers: fixture.sessionHeaders({ origin: `${localPublicUrl}, ${localPublicUrl}` }) },
{ expectedStatus: 403, headers: fixture.sessionHeaders({ origin: `${localPublicUrl}${"x".repeat(4097)}` }) },
{ expectedStatus: 403, headers: fixture.sessionHeaders({ "sec-fetch-site": "cross-site" }) },
{ expectedStatus: 403, headers: fixture.sessionHeaders({ "sec-fetch-site": "same-origin, same-origin" }) },
];
for (const headers of failures) {
for (const { expectedStatus, headers } of failures) {
fixture.resetDownstreamHits();
const response = await fixture.app.inject({ method, url, headers, payload: {} });
expect(response.statusCode).toBe(403);
expect(response.json()).toEqual({ code: "csrf_failed", error: "Request origin validation failed" });
expect(response.statusCode).toBe(expectedStatus);
expect(response.json()).toEqual(expectedStatus === 403
? { code: "csrf_failed", error: "Request origin validation failed" }
: { code: "authentication_required", error: "Authentication is required" });
expect(fixture.downstreamHits()).toBe(0);
}
},
@@ -78,3 +89,16 @@ test("a valid real local session cookie and derived CSRF token cross the same pr
expect(fixture.downstreamHits()).toBe(1);
expect(localPublicUrl).toBe("http://127.0.0.1:8787");
});
test("a valid control may omit optional Fetch Metadata while retaining its exact Origin and CSRF pair", async () => {
fixture.resetDownstreamHits();
const response = await fixture.app.inject({
method: "PUT",
url: "/settings",
headers: fixture.sessionHeaders({ "sec-fetch-site": undefined }),
payload: {},
});
expect(response.statusCode).toBe(200);
expect(fixture.downstreamHits()).toBe(1);
});