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]