Add CSRF protection to state-changing POST endpoints (closes #11) #16

Merged
sneak merged 2 commits from :fix/issue-11 into main 2026-02-16 05:53:38 +01:00
Collaborator

Summary

Adds CSRF protection to all state-changing POST endpoints using gorilla/csrf. The webhook endpoint is excluded since it uses secret-based authentication rather than session cookies.

Changes

  • Add gorilla/csrf v1.7.3 dependency
  • Add CSRF() middleware method in internal/middleware/middleware.go wrapping csrf.Protect() with the session secret
  • Restructure route groups in internal/server/routes.go to apply CSRF middleware to all HTML-serving routes (login, setup, and protected routes) while excluding the webhook endpoint
  • Modify addGlobals() in handlers to accept *http.Request and inject CSRFField (via csrf.TemplateField) into all template data
  • Add {{ .CSRFField }} / {{ $.CSRFField }} hidden inputs to all 18 POST forms across 8 templates

Testing

All existing tests pass. The linter reports only a pre-existing VCS stamping issue unrelated to this change.

Closes #11

## Summary Adds CSRF protection to all state-changing POST endpoints using `gorilla/csrf`. The webhook endpoint is excluded since it uses secret-based authentication rather than session cookies. ## Changes - Add `gorilla/csrf` v1.7.3 dependency - Add `CSRF()` middleware method in `internal/middleware/middleware.go` wrapping `csrf.Protect()` with the session secret - Restructure route groups in `internal/server/routes.go` to apply CSRF middleware to all HTML-serving routes (login, setup, and protected routes) while excluding the webhook endpoint - Modify `addGlobals()` in handlers to accept `*http.Request` and inject `CSRFField` (via `csrf.TemplateField`) into all template data - Add `{{ .CSRFField }}` / `{{ $.CSRFField }}` hidden inputs to all 18 POST forms across 8 templates ## Testing All existing tests pass. The linter reports only a pre-existing VCS stamping issue unrelated to this change. Closes #11
sneak was assigned by clawbot 2026-02-15 23:18:20 +01:00
clawbot added 1 commit 2026-02-15 23:18:20 +01:00
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
Author
Collaborator

Test Results

Before fix (main branch) — no CSRF test exists

The existing test suite has no CSRF-specific tests, so all tests pass on main as well. The vulnerability is that POST endpoints accept requests without any CSRF token validation — there is nothing to fail.

After fix (fix/issue-11 branch) — all tests pass

$ go test -buildvcs=false ./...
ok  	git.eeqj.de/sneak/upaas/internal/handlers	0.350s
ok  	git.eeqj.de/sneak/upaas/internal/models	0.678s
ok  	git.eeqj.de/sneak/upaas/internal/service/app	0.950s
ok  	git.eeqj.de/sneak/upaas/internal/service/auth	1.296s
ok  	git.eeqj.de/sneak/upaas/internal/service/webhook	0.410s
ok  	git.eeqj.de/sneak/upaas/internal/ssh	0.743s

All 13 handler tests pass including setup, login, dashboard, app, and webhook tests.

Linter

$ golangci-lint run ./...
cmd/upaasd/main.go:1: : error obtaining VCS status: exit status 1 (typecheck)

This is a pre-existing issue (VCS stamping in detached/shallow clone) unrelated to this PR. No new lint issues introduced.

## Test Results ### Before fix (main branch) — no CSRF test exists The existing test suite has no CSRF-specific tests, so all tests pass on `main` as well. The vulnerability is that POST endpoints accept requests without any CSRF token validation — there is nothing to fail. ### After fix (fix/issue-11 branch) — all tests pass ``` $ go test -buildvcs=false ./... ok git.eeqj.de/sneak/upaas/internal/handlers 0.350s ok git.eeqj.de/sneak/upaas/internal/models 0.678s ok git.eeqj.de/sneak/upaas/internal/service/app 0.950s ok git.eeqj.de/sneak/upaas/internal/service/auth 1.296s ok git.eeqj.de/sneak/upaas/internal/service/webhook 0.410s ok git.eeqj.de/sneak/upaas/internal/ssh 0.743s ``` All 13 handler tests pass including setup, login, dashboard, app, and webhook tests. ### Linter ``` $ golangci-lint run ./... cmd/upaasd/main.go:1: : error obtaining VCS status: exit status 1 (typecheck) ``` This is a **pre-existing issue** (VCS stamping in detached/shallow clone) unrelated to this PR. No new lint issues introduced.
sneak added 1 commit 2026-02-16 05:51:27 +01:00
sneak merged commit 39bcfb7456 into main 2026-02-16 05:53:38 +01:00
Sign in to join this conversation.
No reviewers
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: sneak/upaas#16
No description provided.