I was able to replicate the issue with this Caddyfile:
:2015
status 401 /secret/files
With the following folder structure:
Matt at hermes in ~/Projects/test
→ exa -lgTL 3
drwxr-xr-x - Matt staff 7 Sep 9:48 .
.rw-r--r-- 58 Matt staff 7 Sep 9:42 ├── Caddyfile
.rw-r--r-- 20 Matt staff 2 Aug 17:02 ├── index.html
drwxr-xr-x - Matt staff 7 Sep 9:42 └── secret
drwxr-xr-x - Matt staff 7 Sep 9:50 └── files
.rw-r--r-- 20 Matt staff 2 Aug 17:02 └── index.html
When requesting //secret/files
or /secret//files
, I get a 301 to single slashes:
Matt at hermes in ~/Projects/test
→ curl -iL localhost:2015/secret//files
HTTP/1.1 301 Moved Permanently
Location: /secret/files/
Server: Caddy
Date: Wed, 06 Sep 2017 23:51:20 GMT
Content-Length: 49
Content-Type: text/html; charset=utf-8
HTTP/1.1 401 Unauthorized
Content-Type: text/plain; charset=utf-8
Server: Caddy
X-Content-Type-Options: nosniff
Date: Wed, 06 Sep 2017 23:51:20 GMT
Content-Length: 17
401 Unauthorized
Requesting the index.html
directly fails with single slashes, as expected:
Matt at hermes in ~/Projects/test
→ curl -i localhost:2015/secret/files/index.html
HTTP/1.1 401 Unauthorized
Content-Type: text/plain; charset=utf-8
Server: Caddy
X-Content-Type-Options: nosniff
Date: Wed, 06 Sep 2017 23:53:38 GMT
Content-Length: 17
401 Unauthorized
Requesting with double slash in the path matched by status
bypasses that status
directive entirely:
Matt at hermes in ~/Projects/test
→ curl -i localhost:2015/secret//files/index.html
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 20
Content-Type: text/html; charset=utf-8
Etag: "ou1q7xk"
Last-Modified: Wed, 02 Aug 2017 07:02:21 GMT
Server: Caddy
Date: Wed, 06 Sep 2017 23:54:15 GMT
This is /secret/files/index.html.
Not technically a bug, I suppose - since the request path clearly doesn’t match the path specified by status
.
Definitely inconsistent and possibly dangerous, though, requiring ludicrous amounts of Caddyfile syntax to work around. Imagine having to do this for any set of files you care about:
status 401 //path/to/secret/files
status 401 /path//to/secret/files
status 401 /path/to//secret/files
status 401 /path/to/secret//files
status 401 //path//to/secret/files
# ...repeat until 2^n (n = count of path elements)... 11 more permutations!
An excellent candidate for a Github issue if I’ve ever seen one.