Pin the body cap's order in every page route group (closes #93)
check / check (push) Successful in 3m18s

Follow-ups from an August review of the body cap, each checked against the current tree. One route test now requires an oversized POST, with no session and no CSRF token, to be refused with 413 before CSRF runs, in every page route group with a POST route and in /settings/, so moving a group's body cap after CSRF fails it. The three test router helpers build the server through New with a lifecycle that is never started, so no field is set by hand. The middleware test comment names runMaxBodySize, and the MaxBodySize doc comment says methods other than POST, PUT and PATCH pass uncapped on purpose. The README item was already settled.

Model: opus-5-5
This commit was merged in pull request #449.
This commit is contained in:
2026-10-02 17:53:21 +02:00
parent e67fffb05d
commit d084f4f912
7 changed files with 107 additions and 39 deletions
+44 -2
View File
@@ -136,7 +136,7 @@ func newTestEnvWithConfig(
t.Cleanup(app.RequireStop)
return &testEnv{
router: server.NewRouterForTest(log.Get(), cfg, mw, hnd),
router: server.NewRouterForTest(t, log, cfg, mw, hnd),
sess: sess,
db: db,
dbMgr: dbMgr,
@@ -531,6 +531,48 @@ func TestStaticServesOnlyGetAndHead(t *testing.T) {
}
}
// --- every page route group ---
// TestPageRouteGroups_OversizeBody_RejectedBeforeCSRF pins the body
// cap ahead of CSRF and RequireAuth in every page route group. The
// requests carry no session and no CSRF token, so if either ran first
// the answer would be a 403 or a redirect to the login page rather
// than 413, and CSRF would issue its cookie (see
// TestPagesLogin_UnderLimit_NoToken_CSRFRejects). /settings has no
// POST route, but its group's middleware runs before the method is
// matched, so a POST there still reaches CSRF's form parsing if the
// cap moves after it. The user and webhook in the paths need not
// exist: nothing after the cap runs.
func TestPageRouteGroups_OversizeBody_RejectedBeforeCSRF(
t *testing.T,
) {
t.Parallel()
env := newTestEnv(t)
form := url.Values{}
form.Set("name", oversizeValue())
for _, path := range []string{
"/pages/login",
"/user/nobody/password",
"/settings/",
"/hooks/new",
"/hook/nonexistent/edit",
} {
w := env.post(path, form, nil)
assert.Equal(
t, http.StatusRequestEntityTooLarge, w.Code, path,
)
assert.False(
t, csrfCookieSet(w),
"CSRF middleware must not run for an oversized body to %s",
path,
)
}
}
// --- /pages group ---
// TestPagesLogin_OversizeBody_RejectedBeforeCSRF proves the cap runs
@@ -1610,7 +1652,7 @@ func TestTwoMetricsRoutersInOneProcess(t *testing.T) {
)
third := &testEnv{
router: server.NewRouterForTest(
first.log.Get(), first.cfg, first.mw, first.hnd,
t, first.log, first.cfg, first.mw, first.hnd,
),
}