This is an automated email from the ASF dual-hosted git repository. ppkarwasz pushed a commit to branch feat/deserialization in repository https://gitbox.apache.org/repos/asf/logging-site.git
commit b80594e2660eb05b41703f7fb20a2c7b29af7977 Author: Piotr P. Karwasz <[email protected]> AuthorDate: Mon May 4 22:11:31 2026 +0200 Add threat model and FAQ entry about deserialization This change adds a section about deserialization of untrusted data to both the threat model and security FAQ. --- .../modules/ROOT/pages/_threat-model-common.adoc | 14 +++++ .../antora/modules/ROOT/pages/security/faq.adoc | 61 +++++++++++++++++++++- 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/src/site/antora/modules/ROOT/pages/_threat-model-common.adoc b/src/site/antora/modules/ROOT/pages/_threat-model-common.adoc index 64baf472..2cdfaaf8 100644 --- a/src/site/antora/modules/ROOT/pages/_threat-model-common.adoc +++ b/src/site/antora/modules/ROOT/pages/_threat-model-common.adoc @@ -141,3 +141,17 @@ https://logging.apache.org/log4j/2.x/manual/api.html#best-practice-concat[Log4j Improper neutralization of Special Elements (https://cwe.mitre.org/data/definitions/138.html[CWE-138]):: + * Log4cxx, Log4j, and Log4net **do** allow users to pass untrusted strings to log statements and thread context, except in the format string of parameterized logging, as mentioned above. + +Deserialization of untrusted data (https://cwe.mitre.org/data/definitions/502.html[CWE-502]):: ++ +Log4cxx, Log4j, and Log4net **do not** deserialize data from any source as part of their normal operation. +For backward compatibility, several classes in Log4j 2 and Log4net 2 still implement `Serializable` (in Java) or carry the `[Serializable]` attribute (in .NET); Log4j's `log4j-api` also ships an allowlist-based `FilteredObjectInputStream` utility to assist applications that nonetheless deserialize log event streams. ++ +Regarding this threat: + +* We provide **no guarantee** that deserializing a stream containing classes from these projects is safe, regardless of the source of the stream. +* Filtering such a stream by the `org.apache.logging` Java package, the `log4net` .NET namespace, or any allowlist derived from project-owned types is **not** sufficient to make deserialization safe. +* The hardening utilities we ship are **partial** and **not exhaustive**; bypasses are treated as opportunities for further hardening, not as vulnerabilities in the project. +* The application performing the deserialization is responsible for ensuring that the byte stream originates from a **trusted source**. ++ +See xref:security/faq.adoc#deserialization[the FAQ entry on CWE-502] for the recommended alternatives. diff --git a/src/site/antora/modules/ROOT/pages/security/faq.adoc b/src/site/antora/modules/ROOT/pages/security/faq.adoc index 05f5e5a5..e834f80a 100644 --- a/src/site/antora/modules/ROOT/pages/security/faq.adoc +++ b/src/site/antora/modules/ROOT/pages/security/faq.adoc @@ -163,4 +163,63 @@ The trustworthiness of an interpolation source cannot be determined a priori by Consider `${ctx:...}` lookups as an example: some applications populate the thread context map exclusively with internally generated values (such as request IDs), while others may include user-provided data (such as HTTP headers). In practice, trustworthiness often varies even at the per-key level: some context map keys may be safe to use in file paths, while others may not. -==== \ No newline at end of file +==== + +[#deserialization] +== https://cwe.mitre.org/data/definitions/502.html[CWE-502: Deserialization of Untrusted Data] in Log4j + +A frequently reported issue concerns Log4j's `Serializable` classes and the allowlist-based `FilteredObjectInputStream` utility shipped in `log4j-api`. +Reports typically claim that, taken together, these expose Log4j to deserialization-based remote code execution when an attacker reaches a deserialization sink. + +**Claim**: Log4j is vulnerable to deserialization of untrusted data because some of its classes are `Serializable` without hardening logic that guarantees secure deserialization, allowing an attacker who reaches a deserialization sink to construct a gadget chain through them. + +[#deserialization-why-not] +=== Why this is not a vulnerability + +Log4j Core **does not** deserialize data from any source as part of its normal operation. +There is no code path in current Log4j Core production code that reads bytes from a network socket, a message queue, or any other input and passes them to `ObjectInputStream.readObject()`. + +For a deserialization vulnerability to exist, an application must: + +* Obtain a stream of bytes from an untrusted source, _and_ +* Pass those bytes to `ObjectInputStream.readObject()` (or an equivalent API). + +Both of these steps occur **outside** Log4j. +The fact that Log4j classes happen to appear in such a stream does not make Log4j the source of the vulnerability, any more than the presence of `java.util.HashMap` in a gadget chain makes the JDK responsible for it. + +Log4j provides **no guarantee** that deserializing a stream containing its classes from an untrusted source is safe, and reports premised on the assumption that such a guarantee exists fall outside our xref:security.adoc#threat-model[threat model]. + +[#deserialization-historical-context] +=== Historical context + +Log4j 1 shipped a `SocketServer` and a `SocketAppender` that exchanged log events over the network using Java serialization. + +In Log4j 2: + +* The `SocketServer` receiver was never reintroduced into the production codebase. +* `SerializedLayout`, originally provided for Log4j 1 compatibility, has been **deprecated since version 2.9** and should not be used. +See the {site-url}/log4j/2.x/manual/layouts.html#SerializedLayout[SerializedLayout documentation] for details. +* Several Log4j 2 classes, most notably `Logger`, `Message` and `LogEvent`, remain `Serializable` for backward compatibility. +The `Serializable` interface cannot be removed in a minor release without breaking applications that rely on it. + +In Log4j Core 3, the `Serializable` interface has been removed from these classes. + +[#deserialization-filtered-object-input-stream] +=== About `FilteredObjectInputStream` + +The Log4j API provides a `FilteredObjectInputStream` utility that enforces a class allowlist when deserializing log event streams. +This class exists as a **defense-in-depth helper** for applications that, despite the guidance above, still consume serialized log events. + +`FilteredObjectInputStream` is **not** a security boundary, and the project makes no guarantee that its allowlist is exhaustive or bypass-proof: + +* Reports of allowlist bypasses are evaluated as **hardening opportunities**, not as vulnerabilities in Log4j. +* The underlying unsafe operation, deserializing untrusted bytes against a classpath that exposes arbitrary `Serializable` classes, is performed by the consuming application, not by Log4j. + +[IMPORTANT] +==== +If your application deserializes log event streams from any source you do not fully control, you are performing an operation that the Logging Services PMC does not endorse and cannot make safe. +Recommended alternatives include: + +* Migrating to a structured layout such as JSON or RFC 5424, transported over TLS. +* If serialized transport must be retained for legacy reasons, configuring a JVM-wide serialization filter via `jdk.serialFilter` and ensuring the producer and consumer endpoints are mutually authenticated and not exposed to untrusted networks. +====
