Replies: 5 comments 6 replies
-
|
The MDC is not something that I have used often, but I seem to recall reading at some point that the MDC could be used for something along the lines of HTTP headers. What would the difference between trusted and untrusted values be? If they're trusted, does that mean that we can do certain operations on them(e.g. replacement)? |
Beta Was this translation helpful? Give feedback.
-
|
My position is that keys should be classified as untrusted content, on the same level as values. |
Beta Was this translation helpful? Give feedback.
-
|
For safe vs. unsafe strings, I'll take an idea from Joel Spolsky and propose something like the following: The idea is that all strings in the MDC are unsafe by default, but you could wrap them in a Note: I'm not suggesting implementing this at the moment, as looking at Jan's comments I would tend to agree that both the keys and values should be unsafe by default. If there is a demand for safe strings in the MDC, something like the above could provide a good implementation. |
Beta Was this translation helpful? Give feedback.
-
|
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 HeadersSuppose an application maps dynamic HTTP header names directly into the // Unsafe practice, but common in middleware
ThreadContext.put(headerName, headerValue);
logger.info("Processed request");The Attack PayloadAn attacker sends a request with a malicious HTTP header where the name contains JSON control characters:
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: {
"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 2. If Keys are Classified as Untrusted (Escaped)If the layout treats keys as untrusted and escapes them, the attack is neutralized: {
"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. |
Beta Was this translation helpful? Give feedback.
-
|
In todays world maybe my view is naive, but my approach would be to say that while Log4j supports the use of the MDC/ThreadContext all responsibility for its content belongs to the user of Log4j. While we may include them in logs, or use them to manipulate how logging is performed, Log4j simply cannot validate the content to the extent necessary. Since the user determines what keys should be present and what the appropriate values should be it is up to them to perform proper validation. If we can make that easier by providing integrations with validation frameworks where there is a way for the user to define keys and validation rules for them we should do that. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Background
I am revising the common threat model (
_threat-model-common.adoc) to define data sources by who controls them: configuration (operator-controlled, trusted), structural identifiers / control (developer-controlled, trusted), and content (user-controlled, untrusted).Most inputs fit one category cleanly. Thread Context (the Log4j
ThreadContextMDC/NDC, and the equivalent context maps in Log4net and Log4cxx) does not. We have discussed this in private and now want to settle it in a public venue.The question
Thread Context values are clearly user-controlled content, hence untrusted. Thread Context keys are ambiguous:
requestIdkey. That would make them trusted, and key-based injection a case of application misuse.How we classify keys decides whether key-based injection or validation-DoS reports are in scope, and what the correct remediation is: neutralize untrusted content, validate and reject trusted input, or document the case as application misuse.
Points to decide
Note
Everyone is welcome to contribute. As usual, opinions expressed by Logging Services PMC members are binding for the project's security policy.
In the meantime, the threat-model refactor will document Thread Context values as untrusted content and mark keys as a known open gap pointing to this discussion.
Beta Was this translation helpful? Give feedback.
All reactions