feat(security): rate-limit /api/flows/start, CSRF double-submit cookie, CSP headers
- Rate-limit /api/flows/start to 10 req/min per user (in-memory, matches login pattern) - Add middleware.ts: validates x-csrf-token header against csrf_token cookie on all API POST requests; issues the cookie on GET if missing; sets CSP, X-Frame-Options, X-Content-Type-Options, and Referrer-Policy on all responses - Add lib/csrf.ts: client-side apiFetch() wrapper that injects the CSRF header - Update all client components (login, useFlowRun, docker, caddy, git, systemd) to use apiFetch() for POST requests - Cookie config in login route already correct (NODE_ENV check, httpOnly, sameSite=strict) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
1e31e3b584
commit
aa1fd41bec
11 changed files with 108 additions and 8 deletions
21
lib/csrf.ts
Normal file
21
lib/csrf.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
'use client'
|
||||
|
||||
function getCsrfToken(): string {
|
||||
if (typeof document === 'undefined') return ''
|
||||
return (
|
||||
document.cookie
|
||||
.split('; ')
|
||||
.find((c) => c.startsWith('csrf_token='))
|
||||
?.split('=')[1] ?? ''
|
||||
)
|
||||
}
|
||||
|
||||
/** Drop-in replacement for fetch() that automatically injects the CSRF token on POST requests. */
|
||||
export function apiFetch(url: string, init: RequestInit = {}): Promise<Response> {
|
||||
if ((init.method ?? 'GET').toUpperCase() !== 'POST') {
|
||||
return fetch(url, init)
|
||||
}
|
||||
const headers = new Headers(init.headers)
|
||||
headers.set('x-csrf-token', getCsrfToken())
|
||||
return fetch(url, { ...init, headers })
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue