////
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//       https://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
////

= Frequently Reported Vulnerabilities

This page documents issues that are **frequently reported** in Logging Services software but are **not considered vulnerabilities** according to our xref:security.adoc#threat-model[threat model].

These reports often stem from valid concerns in specific contexts, but reflect common misunderstandings about how logging systems are designed to operate and what security guarantees they provide.

The goal of this FAQ is to:

* Clarify common misconceptions
* Explain why these reports fall outside our threat model
* Help you make informed decisions when configuring logging

[NOTE]
====
This document is not intended to dismiss security concerns, but to provide context and guidance.
Depending on your environment, some of these topics may still warrant **defensive configuration**.
====

[#crlf-injection]
== https://cwe.mitre.org/data/definitions/93.html[CWE-93: CRLF Injection]

Apache Logging Services libraries (Log4cxx, Log4j, and Log4net) allow users to customize log output through a variety of layouts.
A frequently reported issue is that CR (`\r`) and LF (`\n`) characters present in a log event can appear in the output,
making it difficult to reliably delimit individual events when parsing.

In most configurations, this behavior is intentional and not considered a vulnerability within the defined threat model.
The sections below cover the layouts for which this has most commonly been reported.

[#crlf-injection-pattern-layout]
=== Pattern layout

**Claim**: Pattern layout is vulnerable to CRLF injection because it does not escape CRLF characters.

Pattern layout is an **unstructured** text format.
It defines no fields, no delimiters, and no escaping rules, so it makes no attempt to neutralize control characters, including CRLF sequences.
This means:

* Log output will contain CRLF characters if they are present in the input.
* The layout itself provides **no output sanitization** guarantees.

This behavior is by design and consistent with the layout's purpose.

[#crlf-injection-pattern-layout-why-not]
==== Why this is not a vulnerability

CRLF injection is a concern only when both of the following conditions apply:

* Log output is consumed as **structured data** (for example, by an ingestion pipeline), _and_
* Downstream consumers assume that the output has been sanitized.

Pattern layout guarantees only formatting, not safety or parseability.
Tools such as https://www.elastic.co/docs/reference/enrich-processor/grok-processor[Grok] can parse Pattern layout output automatically, but only when the output consistently matches the expected pattern.
Unescaped CRLF sequences can break that assumption.

[IMPORTANT]
====
If your logs are consumed in any of these ways:

* Parsed automatically by a downstream tool
* Ingested into a structured storage or SIEM system
* Used in security-sensitive workflows

then **avoid Pattern layout** and use a **structured layout** instead, such as JSON or RFC 5424.
====

[TIP]
====
If you must use Pattern layout, **sanitize all inputs explicitly**, not just the log message.
Common oversights include:

* Sanitizing only `%m` (e.g. `%enc{%m}\{CRLF}` in Log4j Core) while leaving other fields unescaped
* The implicit `%ex` pattern specifier (exception stack traces), which are a frequent and overlooked source of CRLF characters
* Seemingly "safe" values such as logger names, thread names, and log levels, which may contain unexpected data depending on your application
====

[#crlf-injection-rfc5424-layout]
=== Syslog and RFC 5424 layouts

**Claim**: The Syslog and RFC 5424 layouts are vulnerable to CRLF injection because they do not escape CRLF characters by default.

Log4j Core provides two syslog-oriented layouts:

* the **RFC 5424 layout**, which follows https://datatracker.ietf.org/doc/html/rfc5424[RFC 5424] (the modern syslog protocol), and
* the **Syslog layout**, which follows https://datatracker.ietf.org/doc/html/rfc3164[RFC 3164] (the legacy BSD syslog format).

RFC 5424 layout is a **structured format** with well-defined fields and delimiters, enabling reliable and unambiguous parsing.
RFC 3164 is weaker: it is an _informational_ document that describes observed BSD syslog behavior rather than mandating a strict format.

Neither spec, however, requires escaping of control characters (including CRLF) in the message body.
Per https://datatracker.ietf.org/doc/html/rfc5424#section-8.2[Section 8.2 of RFC 5424], the spec does **not** require escaping such characters in the `PARAM-VALUE` or `MSG` fields, and RFC 3164 leaves their handling unspecified altogether.
In both cases, responsibility for handling those characters is delegated to the **transport binding** in use.

For this reason, neither layout escapes CRLF characters by default, and this is **not** considered a vulnerability.

[NOTE]
====
The {site-url}/log4j/2.x/manual/appenders.html#SyslogAppender[Syslog appender] can be configured with either layout: the RFC 5424 layout (`format="RFC5424"`) or the Syslog layout (`format="BSD"`, the default).
The considerations described here apply to the appender regardless of which of the two layouts it uses.
====

[#crlf-injection-rfc5424-layout-why-not]
==== Why this is not a vulnerability

The appropriate handling of CRLF characters depends on which transport protocol carries the log messages.
These layouts are used with several protocol bindings, each with different framing semantics:

UDP (https://datatracker.ietf.org/doc/html/rfc5426[RFC 5426])::
Each message is transmitted as a self-contained datagram, so CRLF characters carry no special meaning and require no escaping.

TLS-encrypted TCP (https://datatracker.ietf.org/doc/html/rfc5425[RFC 5425])::
The recommended transport for new deployments.
Uses length-prefixed framing, so message boundaries are established independently of content.
CRLF escaping is not required.

Legacy TCP (https://datatracker.ietf.org/doc/html/rfc6587[RFC 6587])::
Uses LF as a message delimiter, so LF characters within a message must be escaped.
This protocol is **discouraged** for new deployments due to known limitations.

Applying CRLF escaping unconditionally at the layout level would silently alter log content for transport bindings that do not need it.
Defaulting to no escaping preserves the original log data while allowing each transport binding to apply the appropriate treatment.

[TIP]
====
Both layouts support optional CRLF escaping, which you can enable explicitly when using a transport that requires it (such as legacy TCP over RFC 6587).
Refer to the layout configuration reference for details.

If you are starting a new deployment, prefer TLS-encrypted TCP (RFC 5425), which avoids this concern entirely through length-prefixed framing.
====

[#path-traversal]
== https://cwe.mitre.org/data/definitions/35.html[CWE-35: Path Traversal]

A frequently reported issue is the presence of unvalidated file paths in configuration files, such as file appender file names.

**Claim**: File appenders are vulnerable to path traversal because they accept unvalidated file paths.

[#path-traversal-why-not]
=== Why this is not a vulnerability

Configuration files are **trusted** resources according to our xref:security.adoc#threat-model[threat model] and must be protected accordingly.
Given that trust, constraining the file paths they may contain provides no meaningful security benefit.

Limiting file paths to a specific directory would also introduce a **chicken-and-egg problem**: doing so would require an additional configuration resource to define the allowed directory, which itself would need to be trusted and protected.
We do not establish a hierarchy of trust between configuration resources (environment variables, system properties, configuration files, and so on): they are all considered equally trusted.

[#path-traversal-problematic-contexts]
=== Problematic contexts

While unvalidated file paths in configuration are not a vulnerability in themselves, they can become one when **interpolation** features (arbiters, lookups, etc.) are used to construct file paths dynamically.

This risk is compounded when interpolation occurs at **runtime** rather than at configuration time: for example, when appenders are created dynamically by Log4j Core's
{site-url}/log4j/2.x/manual/appenders/delegating.html#RoutingAppender[Routing appender].
In those cases, the interpolated values originate outside the configuration file itself and may originate from untrusted or attacker-controlled sources.

It is the user's responsibility to ensure that the sources of any interpolated values used in file paths are trustworthy.

[IMPORTANT]
====
The trustworthiness of an interpolation source cannot be determined a priori by the Logging Services libraries, because it depends on the specific application and how it uses that source.

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.
====

[#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.
====
