summaryrefslogtreecommitdiff
path: root/modules/caddyhttp/caddyhttp_test.go
diff options
context:
space:
mode:
authorMatt Holt <mholt@users.noreply.github.com>2021-06-17 09:59:08 -0600
committerGitHub <noreply@github.com>2021-06-17 09:59:08 -0600
commit9d4ed3a3236df06e54c80c4f6633b66d68ad3673 (patch)
treef516a98ff44465f2434a03c4625dc969d87857e2 /modules/caddyhttp/caddyhttp_test.go
parentfbd6560976dc73052bd5d3277869912de68f6731 (diff)
caddyhttp: Refactor and export SanitizedPathJoin for use in fastcgi (#4207)
Diffstat (limited to 'modules/caddyhttp/caddyhttp_test.go')
-rw-r--r--modules/caddyhttp/caddyhttp_test.go94
1 files changed, 94 insertions, 0 deletions
diff --git a/modules/caddyhttp/caddyhttp_test.go b/modules/caddyhttp/caddyhttp_test.go
new file mode 100644
index 0000000..09011fe
--- /dev/null
+++ b/modules/caddyhttp/caddyhttp_test.go
@@ -0,0 +1,94 @@
+package caddyhttp
+
+import (
+ "net/url"
+ "path/filepath"
+ "testing"
+)
+
+func TestSanitizedPathJoin(t *testing.T) {
+ // For reference:
+ // %2e = .
+ // %2f = /
+ // %5c = \
+ for i, tc := range []struct {
+ inputRoot string
+ inputPath string
+ expect string
+ }{
+ {
+ inputPath: "",
+ expect: ".",
+ },
+ {
+ inputPath: "/",
+ expect: ".",
+ },
+ {
+ inputPath: "/foo",
+ expect: "foo",
+ },
+ {
+ inputPath: "/foo/",
+ expect: "foo" + separator,
+ },
+ {
+ inputPath: "/foo/bar",
+ expect: filepath.Join("foo", "bar"),
+ },
+ {
+ inputRoot: "/a",
+ inputPath: "/foo/bar",
+ expect: filepath.Join("/", "a", "foo", "bar"),
+ },
+ {
+ inputPath: "/foo/../bar",
+ expect: "bar",
+ },
+ {
+ inputRoot: "/a/b",
+ inputPath: "/foo/../bar",
+ expect: filepath.Join("/", "a", "b", "bar"),
+ },
+ {
+ inputRoot: "/a/b",
+ inputPath: "/..%2fbar",
+ expect: filepath.Join("/", "a", "b", "bar"),
+ },
+ {
+ inputRoot: "/a/b",
+ inputPath: "/%2e%2e%2fbar",
+ expect: filepath.Join("/", "a", "b", "bar"),
+ },
+ {
+ inputRoot: "/a/b",
+ inputPath: "/%2e%2e%2f%2e%2e%2f",
+ expect: filepath.Join("/", "a", "b") + separator,
+ },
+ {
+ inputRoot: "C:\\www",
+ inputPath: "/foo/bar",
+ expect: filepath.Join("C:\\www", "foo", "bar"),
+ },
+ {
+ inputRoot: "C:\\www",
+ inputPath: "/D:\\foo\\bar",
+ expect: filepath.Join("C:\\www", "D:\\foo\\bar"),
+ },
+ } {
+ // we don't *need* to use an actual parsed URL, but it
+ // adds some authenticity to the tests since real-world
+ // values will be coming in from URLs; thus, the test
+ // corpus can contain paths as encoded by clients, which
+ // more closely emulates the actual attack vector
+ u, err := url.Parse("http://test:9999" + tc.inputPath)
+ if err != nil {
+ t.Fatalf("Test %d: invalid URL: %v", i, err)
+ }
+ actual := SanitizedPathJoin(tc.inputRoot, u.Path)
+ if actual != tc.expect {
+ t.Errorf("Test %d: SanitizedPathJoin('%s', '%s') => %s (expected '%s')",
+ i, tc.inputRoot, tc.inputPath, actual, tc.expect)
+ }
+ }
+}