Mar 9, 2026·7 min read·7 visits
A double-expansion vulnerability in Caddy's `vars_regexp` matcher allows unauthenticated remote attackers to leak sensitive server-side data, including environment variables and local files, by injecting Caddy placeholders into HTTP request headers.
CVE-2026-30852 is a moderate-severity information disclosure vulnerability in the Caddy web server. The flaw originates in the `vars_regexp` matcher within the `caddyhttp` module, where improper neutralization of special elements leads to a double-expansion of placeholders. Attackers can exploit this behavior by crafting specific HTTP request headers that, when evaluated by the vulnerable matcher, expose sensitive environment variables, local file contents, and system information.
Caddy is a widely used, highly extensible web server known for its automatic HTTPS capabilities and flexible configuration system. The caddyhttp module handles the core HTTP request routing and processing logic. Within this module, the vars_regexp matcher is responsible for evaluating specific variables against regular expressions to dictate request flow and access control.
CVE-2026-30852 is classified as an improper neutralization of special elements (CWE-74), leading directly to the exposure of sensitive information (CWE-200). The vulnerability surfaces when Caddy processes user-controlled input through a specific sequence of internal placeholder evaluations. The system inadvertently processes the same input multiple times, violating the expectation that user data should remain literal strings after initial extraction.
The core issue affects Caddy versions starting from v2.7.5 up to, but not including, v2.11.2. The exposure requires a specific configuration pattern where the vars_regexp matcher operates on user-supplied input, most commonly HTTP request headers. When these conditions are met, unauthenticated remote attackers can query internal system state without triggering standard access violations.
Successful exploitation results in the leakage of sensitive internal data. This includes environment variables housing database credentials or cloud provider keys, local file contents accessible to the Caddy process, and underlying system architecture details. The vulnerability does not provide direct code execution capabilities, but the exposed secrets often facilitate subsequent critical attacks.
The vulnerability stems from an architectural decision introduced in pull request #5408, which aimed to fix placeholder key resolution in the MatchVarsRE function. The implementation relies on the Caddy replacer mechanism, specifically the repl.ReplaceAll function, to evaluate dynamic configuration values at runtime.
When a request triggers the vars_regexp matcher, the system first extracts the value associated with the configured placeholder. For example, a configuration matching against {http.request.header.X-Security-ID} prompts the server to extract the literal string provided by the client in that header field. The system correctly identifies the user-supplied string as the target for the regular expression match.
The flaw occurs immediately after this extraction. The developer implementation passes the resulting user-supplied string back into repl.ReplaceAll(varStr, ""). This function is designed to evaluate and expand Caddy placeholders into their corresponding system values. Because the user input is passed into this evaluation function without sanitization, any placeholder syntaxes within the user input are actively executed by the server context.
This double-expansion creates a critical data flow violation. The boundary between configuration logic and user data dissolves, treating external input as trusted server-side execution instructions. The resulting expanded string, which now contains the sensitive system data, is subsequently used in the regular expression match evaluation, placing it in a position to be logged or reflected.
The execution path begins in modules/caddyhttp/vars.go around line 337. The MatchVarsRE function is invoked during the HTTP request routing phase. The function processes a map of configured placeholders and their corresponding regular expression patterns.
// Conceptual representation of the vulnerable logic in MatchVarsRE
func (m MatchVarsRE) Match(req *http.Request) bool {
repl := req.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
for key, re := range m {
// Step 1: Resolve the initial key (e.g., header extraction)
varStr := repl.ReplaceAll(key, "")
// Step 2: VULNERABILITY - Double expansion of the resolved value
// If varStr contains "{env.SECRET}", it gets evaluated here
expandedVarStr := repl.ReplaceAll(varStr, "")
// Step 3: Regex match against the leaked data
if !re.MatchString(expandedVarStr) {
return false
}
}
return true
}The vulnerability is isolated to Step 2 in the logic flow above. The initial call to ReplaceAll on the configuration key correctly fetches the HTTP header value. The subsequent call takes that untrusted header value and processes it as if it were a trusted configuration string.
The patch in version 2.11.2 removes the secondary evaluation step. By passing the literal extracted value directly to the regular expression matcher, the system preserves the integrity of the user input. Placeholders injected by the attacker remain inert strings, neutralizing the CWE-74 injection vector completely.
Exploitation requires identifying a Caddy endpoint utilizing the vars_regexp matcher on a user-controllable input field. Attackers typically map the application's routing behavior by sending benign payloads to infer which headers or query parameters influence routing decisions. Once a target field is identified, the attacker crafts a specialized payload utilizing standard Caddy placeholder syntax.
The attack vector relies entirely on standard HTTP requests. No specialized tooling or non-standard network protocols are required. An attacker constructs a request mapping the target placeholder to a system value they wish to extract. For example, injecting {env.DATABASE_URL} into the targeted header instructs the Caddy replacer to swap the placeholder with the actual environment variable during the second evaluation pass.
The final stage of exploitation depends on the server's response handling. If the regular expression match result dictates a specific error message, HTTP response header, or is written to an accessible log file, the attacker can extract the evaluated secret. The exploit relies on the server's own configuration to exfiltrate the data, making the attack highly dependent on specific routing behaviors.
The impact of CVE-2026-30852 is strictly limited to information disclosure, scoring a 5.5 on the CVSS v4.0 scale. The vulnerability does not compromise system integrity or availability directly. However, the nature of the disclosed information often leads to total system compromise via secondary attack vectors.
Attackers can leverage the {env.*} placeholder to extract comprehensive environment configurations. Modern deployment patterns heavily utilize environment variables for database connection strings, API tokens, and cryptographic seeds. Exposure of these secrets allows attackers to bypass the web tier entirely and authenticate directly to backend data stores or cloud provider control planes.
The {file.*} placeholder introduces severe local file inclusion capabilities. An attacker can instruct the server to read any file accessible to the Caddy process user. This mechanism maps to MITRE ATT&CK technique T1005 (Data from Local System), enabling the extraction of private keys, configuration files, and system password hashes (e.g., /etc/passwd).
The probability of mass exploitation remains low, reflected in the EPSS score of 0.00045. The requirement for a specific, non-default configuration pattern (using vars_regexp on user input) limits the globally exposed attack surface. However, targeted attacks against known vulnerable configurations carry a high probability of success.
The primary and most effective remediation for CVE-2026-30852 is updating the Caddy server binary. Administrators must deploy Caddy version v2.11.2 or later. This release fundamentally alters the MatchVarsRE logic, removing the vulnerable secondary evaluation step entirely and permanently resolving the root cause.
For environments where immediate patching is unfeasible, administrators must conduct a thorough review of the Caddyfile or JSON configuration. Any usage of the vars_regexp matcher that operates on fields directly controllable by external users, particularly HTTP headers and query parameters, should be temporarily disabled or replaced with exact string matchers (vars) where possible.
Network-level mitigations provide an additional layer of defense during the patching window. Security teams should deploy Web Application Firewall (WAF) rules targeting the Caddy placeholder syntax. Specifically, dropping requests where headers or query parameters contain the substrings {env., {file., or {system. prevents the exploit payload from reaching the vulnerable Caddy routing logic.
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N/E:P| Product | Affected Versions | Fixed Version |
|---|---|---|
Caddy Caddy | >= 2.7.5, < 2.11.2 | 2.11.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-74, CWE-200 |
| Attack Vector | Network |
| CVSS v4.0 | 5.5 (Medium) |
| EPSS Score | 0.00045 |
| Impact | Information Disclosure |
| Exploit Status | Proof of Concept |
| KEV Status | Not Listed |
Improper Neutralization of Special Elements in Output Used by a Downstream Component ('Injection')