Assert the traversal redirect by property, not by status code
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/build Pipeline was successful

net/http's mux answers a literal ../ in the path with a redirect whose
exact code differs between Go 1.25 (301) and 1.26 (307), so pinning the
code failed CI while passing locally. Assert what the test is actually
about: the request is redirected rather than handled, and no kids-tree
entry is created.
This commit is contained in:
2026-08-29 21:30:35 +10:00
parent c129cb99fc
commit b15aa1a340
+16 -3
View File
@@ -273,9 +273,6 @@ func TestMutationRejectsBadSectionAndName(t *testing.T) {
{"/api/library/movies/Ghost/mark", http.StatusNotFound},
{"/api/library/movies/..%2f..%2fetc/mark", http.StatusBadRequest},
{`/api/library/movies/..\..\etc/mark`, http.StatusBadRequest},
// A literal ../ never reaches a handler: net/http's mux normalises the
// path and redirects, so no mutation runs.
{"/api/library/movies/../mark", http.StatusTemporaryRedirect},
}
for _, c := range cases {
rec := e.do(t, http.MethodPost, c.path)
@@ -283,6 +280,22 @@ func TestMutationRejectsBadSectionAndName(t *testing.T) {
t.Errorf("POST %s = %d, want %d (%s)", c.path, rec.Code, c.want, rec.Body)
}
}
// A literal ../ never reaches a handler at all: net/http's mux normalises
// the path and redirects instead. The exact redirect code has varied across
// Go releases, so assert the property that matters — it is a redirect and
// no mutation ran.
rec := e.do(t, http.MethodPost, "/api/library/movies/../mark")
if rec.Code < 300 || rec.Code >= 400 {
t.Errorf("POST with a literal ../ = %d, want a redirect (%s)", rec.Code, rec.Body)
}
if _, err := os.Stat(filepath.Join(e.root, library.KidsTree, "movies")); err != nil {
t.Fatalf("kids movies dir disturbed: %v", err)
}
entries, err := os.ReadDir(filepath.Join(e.root, library.KidsTree, "movies"))
if err != nil || len(entries) != 0 {
t.Fatalf("traversal attempt created kids entries: %v %v", entries, err)
}
}
func TestArtProxyStreamsAndHidesTheKey(t *testing.T) {