Add CSRF protection to state-changing POST endpoints

Add gorilla/csrf middleware to protect all HTML-serving routes against
cross-site request forgery attacks. The webhook endpoint is excluded
since it uses secret-based authentication.

Changes:
- Add gorilla/csrf v1.7.3 dependency
- Add CSRF() middleware method using session secret as key
- Apply CSRF middleware to all HTML route groups in routes.go
- Pass CSRF token to all templates via addGlobals helper
- Add {{ .CSRFField }} / {{ $.CSRFField }} hidden inputs to all forms

Closes #11
This commit is contained in:
clawbot
2026-02-15 14:17:55 -08:00
parent d4eae284b5
commit b1dc8fcc4e
17 changed files with 77 additions and 30 deletions

View File

@@ -15,8 +15,8 @@ const (
func (h *Handlers) HandleSetupGET() http.HandlerFunc {
tmpl := templates.GetParsed()
return func(writer http.ResponseWriter, _ *http.Request) {
data := h.addGlobals(map[string]any{})
return func(writer http.ResponseWriter, request *http.Request) {
data := h.addGlobals(map[string]any{}, request)
err := tmpl.ExecuteTemplate(writer, "setup.html", data)
if err != nil {
@@ -54,13 +54,14 @@ func validateSetupForm(formData setupFormData) string {
func (h *Handlers) renderSetupError(
tmpl *templates.TemplateExecutor,
writer http.ResponseWriter,
request *http.Request,
username string,
errorMsg string,
) {
data := h.addGlobals(map[string]any{
"Username": username,
"Error": errorMsg,
})
}, request)
_ = tmpl.ExecuteTemplate(writer, "setup.html", data)
}
@@ -83,7 +84,7 @@ func (h *Handlers) HandleSetupPOST() http.HandlerFunc {
}
if validationErr := validateSetupForm(formData); validationErr != "" {
h.renderSetupError(tmpl, writer, formData.username, validationErr)
h.renderSetupError(tmpl, writer, request, formData.username, validationErr)
return
}
@@ -95,7 +96,7 @@ func (h *Handlers) HandleSetupPOST() http.HandlerFunc {
)
if createErr != nil {
h.log.Error("failed to create user", "error", createErr)
h.renderSetupError(tmpl, writer, formData.username, "Failed to create user")
h.renderSetupError(tmpl, writer, request, formData.username, "Failed to create user")
return
}
@@ -106,6 +107,7 @@ func (h *Handlers) HandleSetupPOST() http.HandlerFunc {
h.renderSetupError(
tmpl,
writer,
request,
formData.username,
"Failed to create session",
)