//// 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. //// [#threat-common] = Common threat model All the logging frameworks maintained by Apache Logging Services (https://logging.apache.org/log4cxx/index.html[Log4cxx], https://logging.apache.org/log4j/index.html[Log4j] and https://logging.apache.org/log4net/index.html[Log4net]) face similar challenges from malicious actors. The following sections outline the most common threats to logging frameworks and clarify the assumptions regarding the origin and trustworthiness of various data sources and the capabilities assumed of potential adversaries. Vulnerability reports that do not adhere to these assumptions will not be accepted and are **not** eligible for the https://yeswehack.com/programs/log4j-bug-bounty-program[YesWeHack Bug Bounty Program]. [#threat-common-users] == User types Apache Logging Services distinguishes two kinds of users: Trusted Users:: + Application developers and administrators are considered **trusted** users. They have unrestricted access to all the features of the logging framework and the environment it is deployed to. Untrusted Users:: + All the other users are considered untrusted. [#threat-common-sources] == Sources Logging systems read data from multiple sources. Each source is classified by **who controls it**, since that determines whether the frameworks can trust the data and how they must handle it. The three categories below are defined by their controller: the **operator** who deploys the application, the **developer** who writes it, and the **user** whose data the application processes. [#threat-common-sources-configuration] === Configuration (operator-controlled) Configuration is supplied by the **operator** (the deployer or administrator) and is **trusted**. It comprises environment variables, configuration properties, and configuration files. To maintain security, the following responsibilities fall on the deployer: * Ensure that untrusted parties do not have write access to these resources. * Ensure these resources are transmitted only over **confidential** channels (e.g., HTTPS, secure file systems). * Be aware that **non-confidential** channels such as HTTP or JMX are **disabled by default** to prevent accidental exposure. * If configuration files use interpolation features (e.g., https://logging.apache.org/log4j/2.x/manual/lookups.html[Log4j Lookups]), ensure that only trusted data sources are used. In particular, values read from the context map (see https://logging.apache.org/log4j/2.x/manual/thread-context.html[Thread Context in Log4j]) may contain user-provided data, such as HTTP headers; see <>. [#threat-common-sources-structural] === Structural identifiers and control (developer-controlled) Structural identifiers and control inputs are supplied by the **developer** in the application source code and are **trusted**. They are expected to be compile-time constants, or values otherwise chosen by the developer, rather than data derived from end users. Examples include: * Logger names, levels, and markers. * The identifiers and field names of a structured log message, such as the `MSGID` and `SD-ID` fields of an RFC 5424 syslog message. * The format string of a parameterized log statement. Programmers **should** use compile-time constants as format strings to prevent message tampering and log injection. See https://logging.apache.org/log4j/2.x/manual/api.html#best-practice-concat[Don't use string concatenation] for an example. Because these inputs are trusted, the frameworks **may** reject a malformed value (for example, by throwing an exception) instead of silently altering it: a malformed structural identifier is a programming error. Routing untrusted data into one of these inputs is application misuse and is **out of scope**. [#threat-common-sources-content] === Content (user-controlled) Content is the data an application logs on behalf of its **users** and is **not trusted**. The frameworks accept arbitrary content and **must not** reject it: rejecting user-controlled input would turn a malicious value into a denial of service. * Log4cxx, Log4j, and Log4net **do not** trust log messages. No particular input validation for log messages is necessary. * They **do not** trust the string representation of log parameters. * They **do not** trust the **values** stored in the thread context. [NOTE] ==== Although the frameworks accept arbitrary content, they **trust** that the objects passed to a log statement can be safely converted to strings. They **should not** be used to log deserialized data from untrusted sources; see https://owasp.org/www-community/vulnerabilities/Deserialization_of_untrusted_data[the related OWASP guide]. ==== [NOTE] ==== The trust level of thread context **keys** is under discussion in https://github.com/apache/logging-log4j2/discussions/4132[logging-log4j2#4132]. Until that discussion concludes, this document classifies only thread context **values** as content; the classification of keys is a **known open gap**. ==== [#threat-common-sinks] == Sinks Just as they read from sources, logging systems write to **sinks**: the destinations to which an appender delivers a formatted log event, such as files, consoles, sockets, databases, and message brokers. Sinks are defined by the **operator** as part of the configuration and are therefore **trusted**. This is the counterpart of the source classification above: sources range from trusted configuration to untrusted content, but every sink is trusted, because a sink exists only where the operator has configured an appender that writes to it. [#threat-common-sinks-destination] === Destination integrity (operator-controlled) The destination an appender writes to is chosen by the operator and is trusted, including a destination created dynamically at runtime. For example, a https://logging.apache.org/log4j/2.x/manual/appenders/delegating.html#RoutingAppender[Routing appender] may open a file whose path is interpolated from a lookup: selecting that destination is the operator's decision, and the trustworthiness of any value used to build it is the operator's responsibility (see xref:security/faq.adoc#path-traversal[the FAQ entry on path traversal]). It follows that: * Ensuring that untrusted parties do not have write access to a log destination, such as the directory or file a file appender writes to, is a **deployer responsibility**, exactly as it is for configuration resources (see <>). * An adversary who can write to a destination, for example by planting a symbolic link where a file appender expects to create its output, can already tamper with the logs directly by deleting, truncating, or rewriting them. The frameworks therefore do **not** attempt to defend a destination they have been configured to trust, and a report that assumes such write access is **out of scope**. [#threat-common-sinks-passive-active] === Passive and active sinks A logging framework is responsible for producing output that is **well-formed in the format the configured layout emits**: plain text for an unstructured layout such as the Pattern layout, and a structured document for a structured layout such as the XML, JSON, RFC 5424, or HTML layouts. Whether a defect observed at a sink is our responsibility depends on what the destination does with that output. Passive sink:: + A passive sink consumes the output **as the format the layout produced**: it stores the bytes in a file, transmits them over a socket, or renders the document the layout emitted. For structured layouts, the frameworks **must** ensure that untrusted content cannot break the structure of that document; this is the log-injection commitment stated in <>. A failure to escape a metacharacter for the format we emit is a defect we **own**. For instance, https://www.cve.org/CVERecord?id=CVE-2025-54812[CVE-2025-54812] was fixed in Log4cxx because its HTML layout produced malformed HTML: the layout emits HTML, so it must emit **safe** HTML. Active sink:: + An active sink **re-interprets** our output in a language we did not produce and acts on that interpretation: a terminal that executes ANSI escape sequences embedded in plain text, a spreadsheet that evaluates formula syntax in a field, or a shell that expands metacharacters. The frameworks do not emit terminal control language, spreadsheet formulas, or shell scripts, and they cannot enumerate, let alone neutralize, every way a downstream consumer might re-interpret well-formed output. Defending against an active sink is therefore **out of scope**. This is why we do not treat the console ANSI-escape-sequence issue, the class of https://www.cve.org/CVERecord?id=CVE-2025-55754[CVE-2025-55754] as reported against Apache Tomcat, as a vulnerability in our projects: our Pattern layout emits correct plain text, and an ANSI-interpreting console is an active sink whose behavior, and the choice to view logs through it, belong to the operator. [NOTE] ==== The boundary is whether the framework emitted output that is malformed **in its own format** (a defect we own) or well-formed output that a downstream sink chose to re-interpret in another language (out of scope). Unstructured layouts such as the Pattern layout make **no** injection guarantee even for a passive sink, because they are meant for human consumption; see <>. ==== [#threat-common-adversary] == Adversary capabilities The threats listed below are evaluated against an adversary with a well-defined and limited set of capabilities. Defining these capabilities clarifies which reports are in scope: a report that requires a capability not listed here is **not** considered a vulnerability. In-scope adversary:: + An in-scope adversary is any party whose data reaches the logging framework **exclusively** through the user-controlled content described in <>. Such an adversary is assumed to be able to: + * Submit arbitrary byte sequences, including malformed text encodings and control characters (such as `CR`, `LF` and `NUL`), through log messages, the string representation of log parameters, and the values of the thread context. * Submit excessively long inputs, within whatever limits the calling application enforces. * Submit input that resembles the framework's own interpolation or lookup syntax, including input that triggers recursive interpolation. Out-of-scope adversary:: + The following adversaries are explicitly **out of scope**; a report relying on any of these capabilities will not be accepted: + * An adversary able to modify environment variables, configuration properties, or configuration files: these are trusted sources (see <>). * An adversary able to control the structural identifiers or control inputs of a log statement, such as logger names, levels, markers, structured-message identifiers, or format strings: these are developer-controlled, trusted inputs (see <>). Populating them from untrusted data is application misuse. * An adversary able to execute arbitrary code in the same process as the logging framework. Code running in the same process shares the same trust level as the logging framework itself; there is no boundary to enforce. This includes code introduced through plugins, custom appenders, or other application extensions. * An adversary able to cause a self-referential or otherwise non-terminating object structure to be passed to a log statement. The logging frameworks trust that logged objects can be safely converted to a string; converting such a structure is the responsibility of the calling code. * An adversary observing side channels, such as the timing or memory behavior of the logging framework. * A malicious destination of an appender (e.g. a hostile database, message broker, or mail server). Appender destinations are configured by trusted users and are treated as an extension of the deployer. * An adversary with write access to a log destination, such as the directory or file a file appender writes to, or the ability to plant a symbolic link there: log destinations are operator-controlled and trusted (see <>). * An adversary who relies on an **active sink** re-interpreting well-formed log output, such as a terminal that executes injected ANSI escape sequences (see <>). [#threat-common-threat] == Threats These are the most commonly encountered threats for users of Log4cxx, Log4j and Log4net: Log Injection (https://cwe.mitre.org/data/definitions/117.html[CWE-117]):: + Log injection is a common attack vector to hide malicious activity in an application. Regarding this threat: * **Unstructured layouts** such as https://logging.apache.org/log4j/2.x/manual/pattern-layout.html[Pattern Layout in Log4j] do **not** protect users from log injection. These layouts are meant for **human** and not computer consumption. * Log4cxx, Log4j and Log4net **must** prevent log injection in **structured** layouts, such as the XML, JSON, RFC 5424, and HTML layouts, when they are consumed by a passive sink; see <>. Supply chain attacks (https://cwe.mitre.org/data/definitions/1357.html[CWE-1357]):: * Apache Logging Services projects **do** check the quality of our dependencies. * Deprecated components such as the https://logging.apache.org/log4j/2.x/manual/appenders/database.html#CassandraAppender[Cassandra], https://logging.apache.org/log4j/2.x/manual/appenders/message-queue.html#KafkaAppender[Kafka] and https://logging.apache.org/log4j/2.x/manual/appenders/database.html#CouchDbProvider[CouchDB] appenders are provided for backward compatibility purposes only. While we actively check for vulnerabilities in those components, they are _de facto_ unmaintained, and we discourage their usage in production. * All Apache Logging Services are signed with one of the keys in the Logging Services PMC https://downloads.apache.org/logging/KEYS[KEYS file]. We do **not** support artifacts that do not have a valid signature, and we encourage users to always check the integrity of the downloaded components. Additional information on how to verify releases signatures is available on the xref:download.adoc[Download page] Information disclosure (https://cwe.mitre.org/data/definitions/200.html[CWE-200]):: + Since logging frameworks implement information disclosure by design: * It is up to the deployer to prevent unauthorized access to log files and to ensure that the appropriate log levels are configured. * It is up to the programmer to document which log levels and markers _might_ contain sensitive data. Attention should be brought to the fact that libraries on which an application depends might have a different log level and marker convention. * **Log masking** techniques are out-of-scope for Log4cxx, Log4j, and Log4net. It is up to the developer to ensure that sensitive data is properly masked **before** it is passed to the logging implementation. For this purpose, **third-party** frameworks like https://github.com/palantir/safe-logging[Safe-Logging] should be used. Log reliability (e.g. https://cwe.mitre.org/data/definitions/778.html[CVE-778]):: + Log4j is designed with **reliability** in mind: * By **default**, Log4j **should** deliver log events to the appropriate resource even during a reconfiguration event or will log an error. * While log events will be delivered to a resource, not all resources provide a confirmation mechanism. To ensure reliability along the entire logging pipeline, it is up to the deployer to use reliable transmission components: files, loopback network sockets or https://logging.apache.org/log4j/2.x/manual/appenders/message-queue.html[message-queue-based systems] for example. * Log4j provides configuration options that discard log events if the load on the application is high. Using these options invalidates the reliability guarantees. Denial of service (https://cwe.mitre.org/data/definitions/779.html[CVE-779]):: + Since our logging frameworks are designed with reliability in mind: * Our frameworks go to great lengths to minimize performance overhead, minimize latency and maximizing throughput. Since a universal solution does not exist, many configuration options exist to adapt the performance characteristics to a specific application. See https://logging.apache.org/log4j/2.x/manual/performance.html[Performance] for more information. * It is up to the deployer to ensure that the appenders can keep up with the logs written by using the appropriate appenders and configuring the appropriate level of logs. * It is up to the developer to ensure that log statements, which are not enabled, generate minimal overhead. See the https://logging.apache.org/log4j/2.x/manual/api.html#best-practice-concat[Log4j API Best Practices], for example. 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. [#threat-common-revision] == Revising this threat model This threat model reflects the current design of Log4cxx, Log4j, and Log4net. It is **not** immutable: a revision is required whenever a change to one of the frameworks invalidates an assumption stated above. In particular, this document must be revisited when any of the following becomes true: * A new public API is added that accepts a kind of input not yet covered by <>. * An existing entry point begins to accept input from a new source, changing whether that input is trusted or untrusted. * A security-relevant default changes, or a configuration option that affects the security posture is added or removed. * A framework gains a network listener or any other inbound surface of its own. * A vulnerability report cannot be cleanly classified as either in scope or out of scope using the assumptions above. Internal refactors that do not change any of the above do **not** require a revision. Proposed changes to this document are reviewed by the Apache Logging Services PMC.