security: CSRF on state-changing POSTs when auth is disabled (default) #410
Labels
No labels
backend
bug
chore
duplication
effort:complex
effort:medium
effort:trivial
enhancement
follow-up
frontend
fullstack
priority:high
ready-for-agent
refactor
security
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
dries/ocman#410
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Finding #1 (High) from a security review.
Problem
When auth is off (the default,
s.auth == nil),requireAuthis a pass-through (internal/server/auth.go:221). Only routes wrapped inrequireLocalhostget Origin/Sec-Fetch validation; thes.post/s.requireAuthroutes do not. That leaves every state-changing POST CSRF-able:POST /api/sessions(create)POST /api/session/{id}/...(send message, permission reply)POST /api/project/archivePOST /api/settings/*A hostile web page the user visits while ocman is running can fire cross-site POSTs at
http://127.0.0.1:8229. Only mitigations today are loopback binding +SameSite=Laxcookies.Refs
internal/server/auth.go:221internal/server/routes.go:30-141internal/server/middleware.go:135(isPrivilegedRequesthas the right logic already)Suggested fix
Apply an Origin /
Sec-Fetch-Sitecheck to ALL state-changing POSTs regardless of auth config — factor the browser-origin portion ofisPrivilegedRequest(minus the loopback requirement) into a CSRF guard and compose it intos.post. Alternatively, refuse to start unauthenticated when bound to a non-loopback-addr.Acceptance