filebrowser/http/utils_test.go

45 lines
1.6 KiB
Go

package fbhttp
import "testing"
// cleanSeparators takes the host separator explicitly so the Windows behaviour
// can be asserted from any platform. See GHSA-fgm5-pw99-w2p7: on Windows a
// backslash is a path separator the filesystem resolves but the rule checker
// used to treat as an ordinary character, so "/allow\..\Secret.txt" evaded a
// rule for "/Secret.txt" and still opened it.
func TestCleanSeparators(t *testing.T) {
t.Parallel()
cases := []struct {
name string
in string
sep string
want string
}{
// Windows: a backslash is a separator and must be resolved before the
// path is matched against a rule.
{"windows traversal", `/allow\..\Secret.txt`, `\`, "/Secret.txt"},
{"windows leading backslash", `\Secret.txt`, `\`, "/Secret.txt"},
{"windows mixed separators", `/a/b\..\..\c`, `\`, "/c"},
{"windows already canonical", "/Secret.txt", `\`, "/Secret.txt"},
{"windows relative", `allow\..\Secret.txt`, `\`, "/Secret.txt"},
{"windows empty", "", `\`, "/"},
// POSIX: a backslash is a legal filename character and must survive, or
// files named with one become unreachable.
{"posix backslash is a filename character", `/a\b.txt`, "/", `/a\b.txt`},
{"posix traversal", "/allow/../Secret.txt", "/", "/Secret.txt"},
{"posix relative", "Secret.txt", "/", "/Secret.txt"},
{"posix multiple slashes", "//a///b", "/", "/a/b"},
{"posix empty", "", "/", "/"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
if got := cleanSeparators(tc.in, tc.sep); got != tc.want {
t.Errorf("cleanSeparators(%q, %q) = %q; want %q", tc.in, tc.sep, got, tc.want)
}
})
}
}