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

@@ -3,9 +3,11 @@ package handlers
import (
"encoding/json"
"html/template"
"log/slog"
"net/http"
"github.com/gorilla/csrf"
"go.uber.org/fx"
"git.eeqj.de/sneak/upaas/internal/database"
@@ -64,11 +66,18 @@ func New(_ fx.Lifecycle, params Params) (*Handlers, error) {
}, nil
}
// addGlobals adds version info to template data map.
func (h *Handlers) addGlobals(data map[string]any) map[string]any {
// addGlobals adds version info and CSRF token to template data map.
func (h *Handlers) addGlobals(
data map[string]any,
request *http.Request,
) map[string]any {
data["Version"] = h.globals.Version
data["Appname"] = h.globals.Appname
if request != nil {
data["CSRFField"] = template.HTML(csrf.TemplateField(request)) //nolint:gosec // csrf.TemplateField produces safe HTML
}
return data
}