Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 11, 06:00 UTC
admin: fix origin allow-list host comparison to be case-insensitive (#7973)
The admin origin allow-list compared origin.Host against the allowed URL's Host with byte-for-byte equality. url.Parse does not normalize host case, so an allowed 'http://Example.com:8080' rejected a client origin of 'http://example.com:8080' even though RFC 3986 §3.2.2 says host names are case-insensitive. Use strings.EqualFold. Signed-off-by: Mohammed Al Sahaf <msaa1990@gmail.com>
Mohammed Al Sahaf committed
Sep 3, 2026 at 00:46 UTC
af29f9ea919603408faf33c0f45af53d61db89a5
2 files changed
+62
-1
admin.go
+3
-1
@@ -994,7 +994,9 @@ func (h adminHandler) originAllowed(origin *url.URL) bool {
994
if allowedOrigin.Scheme != "" && origin.Scheme != allowedOrigin.Scheme {
995
continue
996
}
997
- if origin.Host == allowedOrigin.Host {
997
+ // Host comparison is case-insensitive per RFC 3986 §3.2.2; url.Parse
998
+ // does not normalize host case, so fold it here.
999
+ if strings.EqualFold(origin.Host, allowedOrigin.Host) {
1000
return true
1001
}
1002
}
admin_origin_case_test.go
new
+59
@@ -0,0 +1,59 @@
1
+// Copyright 2015 Matthew Holt and The Caddy Authors
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License");
4
+// you may not use this file except in compliance with the License.
5
+// You may obtain a copy of the License at
6
+//
7
+// http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS,
11
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+// See the License for the specific language governing permissions and
13
+// limitations under the License.
14
+
15
+package caddy
16
+
17
+import (
18
+ "net/url"
19
+ "testing"
20
+)
21
+
22
+// TestAdminHandlerOriginAllowed_CaseInsensitiveHost is the regression
23
+// test for the host allow-list comparison being case-sensitive. Per
24
+// RFC 3986 §3.2.2, host names are case-insensitive.
25
+func TestAdminHandlerOriginAllowed_CaseInsensitiveHost(t *testing.T) {
26
+ mustParse := func(raw string) *url.URL {
27
+ u, err := url.Parse(raw)
28
+ if err != nil {
29
+ t.Fatalf("invalid URL %q: %v", raw, err)
30
+ }
31
+ return u
32
+ }
33
+
34
+ cases := []struct {
35
+ name string
36
+ allowed *url.URL
37
+ origin *url.URL
38
+ }{
39
+ {
40
+ name: "allow-list uppercase, origin lowercase",
41
+ allowed: mustParse("http://Example.com:8080"),
42
+ origin: mustParse("http://example.com:8080"),
43
+ },
44
+ {
45
+ name: "allow-list lowercase, origin uppercase",
46
+ allowed: mustParse("http://example.com:8080"),
47
+ origin: mustParse("http://EXAMPLE.com:8080"),
48
+ },
49
+ }
50
+
51
+ for _, tc := range cases {
52
+ t.Run(tc.name, func(t *testing.T) {
53
+ h := adminHandler{allowedOrigins: []*url.URL{tc.allowed}}
54
+ if !h.originAllowed(tc.origin) {
55
+ t.Errorf("originAllowed(%v) with allowed %v = false, want true", tc.origin, tc.allowed)
56
+ }
57
+ })
58
+ }
59
+}