Re: [D] Threat model: how should Thread Context (MDC) keys be classified (trusted structural or untrusted content) ? [logging-log4j2]
ramanathan1504 (via GitHub) <[email protected]> Mon, 01 Jun 2026 17:13:15 -0000
| Newsgroups | gmane.comp.jakarta.log4j.devel |
|---|---|
| Message-ID | <ghd-D_kwDOAKJSSM4AmyP1-210c0789-7e66-495e-b14c-77720c4806d9__15514.2141551309$1780334004$gmane$org@gitbox.apache.org> |
GitHub user ramanathan1504 added a comment to the discussion: Threat model: how should Thread Context (MDC) keys be classified (trusted structural or untrusted content)?
To help illustrate the practical impact of treating Thread Context keys as trusted vs. untrusted, here is a concrete example of how key-based injection can occur in structured layouts when keys are populated dynamically (e.g., from HTTP headers):
### Scenario: Logging Dynamic Headers
Suppose an application maps dynamic HTTP header names directly into the `ThreadContext`:
```java
// Unsafe practice, but common in middleware
ThreadContext.put(headerName, headerValue);
logger.info("Processed request");
```
### The Attack Payload
An attacker sends a request with a malicious HTTP header where the **name** contains JSON control characters:
* **Header Name (Key):** `transactionId" : "123", "role" : "admin`, "dummy`
* **Header Value:** `user-value`
---
### 1. If Keys are Classified as Trusted (Unescaped)
If the layout assumes keys are safe developer constants and writes them raw, the resulting JSON log line becomes corrupted:
```json
{
"time": "2026-06-01T12:00:00Z",
"level": "INFO",
"message": "Processed request",
"transactionId" : "123", "role" : "admin", "dummy": "user-value"
}
```
A log parser (e.g., Elasticsearch, Splunk) will parse `"role": "admin"` as a separate, valid field. This allows the attacker to inject arbitrary key-value pairs into the downstream log aggregator.
### 2. If Keys are Classified as Untrusted (Escaped)
If the layout treats keys as untrusted and escapes them, the attack is neutralized:
```json
{
"time": "2026-06-01T12:00:00Z",
"level": "INFO",
"message": "Processed request",
"transactionId\" : \"123\", \"role\" : \"admin\", \"dummy\": "user-value"
}
```
The payload remains safely trapped inside a single, albeit malformed, JSON key. No new structural fields are injected.
---
This example seems to align closely with the points raised by @FreeAndNil and @vy. While copying raw HTTP headers into MDC keys is discouraged, it is a realistic scenario. Treating keys as untrusted content and sanitizing them by default provides strong defense-in-depth and protects developers from these security oversights.
GitHub link: https://github.com/apache/logging-log4j2/discussions/4132#discussioncomment-17139410
----
This is an automatically sent email for [email protected].
To unsubscribe, please send an email to: [email protected]