Blocks 1.0: no CSRF protection on the cookie-authenticated POST / and POST /generate forms #93
Reference in New Issue
Block a user
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?
From the audit against the canonical
REPO_POLICIES.md. Independently verified againstmainat61f42e6— a case-insensitive grep forcsrfacrossinternal/andcmd/returns zero matches, including in the templates.The policy requires:
> CSRF tokens on all state-mutating HTML forms. API endpoints authenticated via
Authorizationheader (Bearer token, API key) are exempt because the browser does not attach these automatically.pixa has two state-mutating HTML form posts, and neither qualifies for the exemption:
POST /(internal/server/routes.go:49→handleLoginPost,internal/handlers/auth.go:37-66) callsr.ParseForm()and on successs.sessMgr.CreateSession(w)— it creates session state.POST /generate(routes.go:51→HandleGenerateURL,auth.go:77) gates ons.sessMgr.IsAuthenticated(r)— i.e. it is cookie-authenticated, notAuthorization-header authenticated. The exemption explicitly does not apply.The concrete exposure on
POST /is login CSRF: an attacker forces a victim's browser into a session under the attacker's signing key, so anything the victim then generates is attributable to, and visible in, a session the attacker controls. OnPOST /generate, a cross-origin post can mint signed image URLs using the victim's authenticated session.Note that
SameSite=Stricton the session cookie (added in #47) blunts the second case in modern browsers, but it is a defense-in-depth mitigation, not the control the policy requires — and it does nothing for login CSRF, where no session cookie exists yet.Definition of done
POST /andPOST /generate, rendered as a hidden field ininternal/templates/login.htmlandgenerator.html.POST /must be bound to a pre-session value (e.g. a cookie set when the form is rendered), not to a session that does not yet exist.crypto/rand.gorilla/csrfor the chi ecosystem's equivalent). Check~/.claude/GO_PACKAGE_DEFAULTS.mdfirst and record the decision there.internal/handlers, which currently has no auth-flow tests at all — coordinate with that coverage issue.make checkgreen.Priority
Blocks 1.0.0. The policy states this requirement unconditionally, and both affected routes are cookie-authenticated.