From 526a8742688ed58ae40ba1f254c2e7f1f7bbd866 Mon Sep 17 00:00:00 2001 From: grm Date: Fri, 18 Sep 2026 13:48:27 +0300 Subject: Security: Check the CSRF token on logout /logout was the one management POST without the token. A blog lives on a subdomain of the root domain, which is same-site, so SameSite=Lax does not keep the cookie off a form a blog page submits: any blogger's custom HTML could log the superadmin out at will. The logout form already carried _csrf; the handler now checks it through guardPOST. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Sd8UPWrvyYCLj97JexNw3A --- internal/web/web_test.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'internal/web/web_test.go') diff --git a/internal/web/web_test.go b/internal/web/web_test.go index 7f66085..74c0fb7 100644 --- a/internal/web/web_test.go +++ b/internal/web/web_test.go @@ -1014,3 +1014,15 @@ func TestSafeNext(t *testing.T) { } } } + +// Logging out while not logged in just goes to the login page (nothing to protect). +func TestLogoutAnonymous(t *testing.T) { + s := NewServer(&config.Config{BaseDomain: "example.com", JWTSecret: []byte("x")}, nil) + rec := httptest.NewRecorder() + req := httptest.NewRequest("POST", "/logout", nil) + req.Host = "example.com" + s.ServeHTTP(rec, req) + if rec.Code != http.StatusSeeOther || rec.Header().Get("Location") != "/webadmin" { + t.Errorf("got %d → %q", rec.Code, rec.Header().Get("Location")) + } +} -- cgit v1.2.3