Caddy forward_auth copy_headers Does Not Strip Client-Supplied Headers, Allowing Identity Injection and Privilege Escalation
Date: 2026-03
Affected: go/github.com/caddyserver/caddy/v2/modules/caddyhttp/reverseproxy
Attack vector: auth-bypass
Category: vulnerability-disclosure
Severity: High
CVE: CVE-2026-30851
CWE: CWE-287
CWE-345
CVSS: 8.1 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N)

## Summary Caddy's `forward_auth` directive with `copy_headers` generates conditional header-set operations that only fire when the upstream auth service includes the named header in its response. No delete or remove operation is generated for the original client-supplied request header with the same name. When an auth service returns `200 OK` without one of the configured `copy_headers` headers, the client-supplied header passes through unchanged to the backend. Any requester holding a valid authentication token can inject arbitrary values for trusted identity headers, resulting in privilege escalation. This is a regression introduced by PR #6608 in November 2024. All stable releases from v2.10.0 onward are affected. --- ## Scope Argument This is a bug in the source code of this repository, not a misconfiguration. The operator uses `forward_auth` with `copy_headers` exactly as documented. The documentation contains no warning that client-supplied headers with the same names as `copy_headers` entries must also be stripped manually. The `forward_auth` directive is a security primitive whose stated purpose is to gate backend access behind an external auth service. A user of this directive reasonably expects that the backend cannot receive a client-controlled value for a header listed in `copy_headers`. The bug is traceable to a specific commit: PR #6608 (merged November 4, 2024), which added a `MatchNot` guard to skip the `Set` operation when the auth response header is


Mitigations:

Architectural layers (MAESTRO):