csrf.test.ts109 lines · main
1import { describe, expect, test } from 'bun:test';
2
3import { shouldRejectAsCsrf } from './csrf.js';
4
5const trusted = ['https://briven.tech', 'https://api.briven.tech'];
6
7describe('shouldRejectAsCsrf', () => {
8 test('passes safe methods without inspecting Origin', () => {
9 expect(
10 shouldRejectAsCsrf({
11 method: 'GET',
12 hasSession: true,
13 path: '/v1/projects',
14 origin: null,
15 trustedOrigins: trusted,
16 }),
17 ).toBe(false);
18 expect(
19 shouldRejectAsCsrf({
20 method: 'HEAD',
21 hasSession: true,
22 path: '/v1/projects',
23 origin: 'https://evil.example',
24 trustedOrigins: trusted,
25 }),
26 ).toBe(false);
27 });
28
29 test('passes when no session cookie is attached (API-key or anonymous)', () => {
30 expect(
31 shouldRejectAsCsrf({
32 method: 'POST',
33 hasSession: false,
34 path: '/v1/projects',
35 origin: 'https://evil.example',
36 trustedOrigins: trusted,
37 }),
38 ).toBe(false);
39 });
40
41 test('passes /v1/auth/* (Better Auth handles its own CSRF)', () => {
42 expect(
43 shouldRejectAsCsrf({
44 method: 'POST',
45 hasSession: true,
46 path: '/v1/auth/sign-in/email',
47 origin: 'https://evil.example',
48 trustedOrigins: trusted,
49 }),
50 ).toBe(false);
51 });
52
53 test('rejects unsafe-method + session-cookie + missing Origin', () => {
54 expect(
55 shouldRejectAsCsrf({
56 method: 'POST',
57 hasSession: true,
58 path: '/v1/projects',
59 origin: null,
60 trustedOrigins: trusted,
61 }),
62 ).toBe(true);
63 });
64
65 test('rejects unsafe-method + session-cookie + foreign Origin', () => {
66 expect(
67 shouldRejectAsCsrf({
68 method: 'PATCH',
69 hasSession: true,
70 path: '/v1/projects/p_xxx/deployments/latest',
71 origin: 'https://evil.example',
72 trustedOrigins: trusted,
73 }),
74 ).toBe(true);
75 });
76
77 test('passes unsafe-method + session-cookie + trusted Origin', () => {
78 expect(
79 shouldRejectAsCsrf({
80 method: 'POST',
81 hasSession: true,
82 path: '/v1/projects',
83 origin: 'https://briven.tech',
84 trustedOrigins: trusted,
85 }),
86 ).toBe(false);
87 expect(
88 shouldRejectAsCsrf({
89 method: 'DELETE',
90 hasSession: true,
91 path: '/v1/projects/p_xxx',
92 origin: 'https://api.briven.tech',
93 trustedOrigins: trusted,
94 }),
95 ).toBe(false);
96 });
97
98 test('treats methods case-insensitively', () => {
99 expect(
100 shouldRejectAsCsrf({
101 method: 'post',
102 hasSession: true,
103 path: '/v1/projects',
104 origin: null,
105 trustedOrigins: trusted,
106 }),
107 ).toBe(true);
108 });
109});