GITHUB.COM/CADDYSERVER/CADDY/V2 · GHSA-r766-rf9f-588h · Package
FIX → 2.11.8
A Caddy site whose root uses the request host lets a client pick the document root with a crafted Host or :authority value, such as '..' or '../../etc'. An unauthenticated attacker can then read any file the Caddy process can read and, with php_fastcgi or FrankenPHP, run any .php file on the filesystem.
first public Nov 4, 2026 · 1 source
Could this affect your app?
Free first check from your website. Connect your repo for the full answer.
Only sites whose root path is built from the request host, typically catch-all or on-demand TLS sites using a placeholder like {host}. Sites that list their host names explicitly are not affected, and so are those that do not serve files from a host-derived path.
Not affected if explicit-host-names, managed-hosting, static-root
Who cares caddy, frankenphp, go, php, self-hosted
root directives that contain {host} or another request-derived placeholder.caddy version; affected builds are 2.11.7 and earlier.Upgrade to 2.11.8
A site whose root uses the request host (root /srv/sites/{host}) lets the client choose the document root. HTTP/1.1 accepts Host: .., and the HTTP/2 and HTTP/3 servers accept / and \ in :authority, so ../../etc moves the root anywhere on the filesystem. file_server serves files and php_fastcgi runs .php files outside the intended tree.
What reaches Caddy, per protocol (Go 1.27, quic-go v0.63.0):
| Host value | HTTP/1.1 (Host or absolute-form) | HTTP/2 :authority |
|---|
Check it with your coding agent
It reads this page and tells you if your code is affected.
Are you affected?
Ask from here. InfraStack checks the affected versions against your stack and answers in your inbox.
InfraStack checks the affected versions against your stack and answers in Slack, with the evidence and the fix.
2.11.8.HTTP/3 :authority |
|---|
., .., ... | accepted | accepted | accepted |
contains /, \ or a space | 400 | accepted | accepted |
| contains NUL | 400 | stream error | stream error |
httpguts.ValidHostHeader covers only HTTP/1. The HTTP/2 and HTTP/3 servers check :authority with ValidHeaderFieldValue alone, which rejects control bytes but allows /, \ and spaces. The expanded root then goes through FastAbs, which cleans the dot segments instead of rejecting them. On Windows, FastAbs calls GetFullPathNameW, which also trims trailing dots and spaces from the last segment, so ... can resolve like . and .. like ...
Fix: Server.serveHTTP applies httpguts.ValidHostHeader to every protocol, and responds 400 when the host, port stripped, is made only of dots. Hosts such as example.com. keep working. Patch: public PR from dunglas:caddyhttp-reject-path-like-host.
Discovered by Anthropic's OSS Scanner, as vulnerability ANT-2026-YKIEF8GR.
{
servers {
protocols h1 h2c
}
}
:8080 {
root /srv/sites/{host}
file_server
}
# HTTP/1.1: the root becomes /srv, serving /srv/secret.txt
curl -H 'Host: ..' http://localhost:8080/secret.txt
# HTTP/2: curl sends the Host value as :authority; the root becomes /etc
curl --http2-prior-knowledge -H 'Host: ../../etc' http://localhost:8080/passwd
Both return 200 on master. The same works over TLS with HTTP/2 and HTTP/3.
On catch-all or on-demand TLS sites with a host-derived root, unauthenticated clients read any file the Caddy process can read and, with php_fastcgi or FrankenPHP, run any .php file on the filesystem. Sites that list their host names are not affected.