Ops-dashboard/lib/csrf.ts
Scrum4Me Agent aa1fd41bec 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>
2026-05-13 20:01:43 +02:00

21 lines
635 B
TypeScript

'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 })
}