This is an automated email from the ASF dual-hosted git repository.

ramanathan1504 pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git


The following commit(s) were added to refs/heads/2.x by this push:
     new 33c8236d88 docs: Routing Appender security considerations for 
high-cardinality keys (#4217)
33c8236d88 is described below

commit 33c8236d880ab05539e18ec3d7c45fe941ec1639
Author: Sebastien Tardif <[email protected]>
AuthorDate: Thu Aug 27 08:58:59 2026 -0700

    docs: Routing Appender security considerations for high-cardinality keys 
(#4217)
    
    * docs: add Routing Appender security considerations for high-cardinality 
keys
    
    Document that default Route appender definitions create one appender per
    routing key value, which can exhaust file descriptors when the key is
    untrusted or high-cardinality. Recommend purge policies and low-cardinality
    keys.
    
    * docs: note SSRF exposure and link the Routing security section
    
    ---------
    
    Signed-off-by: Sebastien Tardif <[email protected]>
    Co-authored-by: Ramanathan <[email protected]>
---
 .../.2.x.x/4181_routing_appender_security_docs.xml |  8 ++++
 .../ROOT/pages/manual/appenders/delegating.adoc    | 53 +++++++++++++++++++++-
 2 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/src/changelog/.2.x.x/4181_routing_appender_security_docs.xml 
b/src/changelog/.2.x.x/4181_routing_appender_security_docs.xml
new file mode 100644
index 0000000000..acd8bb3e3b
--- /dev/null
+++ b/src/changelog/.2.x.x/4181_routing_appender_security_docs.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xmlns="https://logging.apache.org/xml/ns";
+       xsi:schemaLocation="https://logging.apache.org/xml/ns 
https://logging.apache.org/xml/ns/log4j-changelog-0.xsd";
+       type="fixed">
+  <issue id="4181" 
link="https://github.com/apache/logging-log4j2/issues/4181"/>
+  <description format="asciidoc">Document security considerations for 
high-cardinality keys with the `Routing` Appender</description>
+</entry>
diff --git 
a/src/site/antora/modules/ROOT/pages/manual/appenders/delegating.adoc 
b/src/site/antora/modules/ROOT/pages/manual/appenders/delegating.adoc
index 6076fafa71..287ba4dcfa 100644
--- a/src/site/antora/modules/ROOT/pages/manual/appenders/delegating.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/appenders/delegating.adoc
@@ -872,7 +872,7 @@ The appender can be:
 --
 * A previously declared appender, from the 
xref:manual/configuration.adoc#main-configuration-elements[`Appenders` section] 
of the configuration file.
 * A new appender that is instantiated based on a nested appender definition, 
when the route becomes active.
-See also <<PurgePolicy>> to learn more about the lifecycle of such an appender.
+See also <<PurgePolicy>> to learn more about the lifecycle of such an 
appender, and <<RoutingAppender-security,Security considerations>> before 
deriving the key from request data.
 --
 +
 [#Route-attributes]
@@ -945,6 +945,57 @@ If the `Route` element contains an appender definition, 
the appender will be ins
 * once for each value of the key, if the `Route` has the default key.
 ====
 
+[#RoutingAppender-security]
+=== Security considerations
+
+When a default <<Route,`Route`>> embeds an appender definition, the `Routing` 
Appender creates **one subordinate appender per distinct routing key value**.
+Unlike most appenders, which are fully built when the configuration is loaded, 
those subordinate appenders are created **at runtime** when a new key appears.
+Lookups used in the route (for example `${ctx:userId}`) can therefore still 
carry attacker-controlled data when appender attributes are resolved.
+
+Review two aspects of any dynamic routing configuration:
+
+[#RoutingAppender-security-resources]
+==== Resource allocation
+
+The `Routing` Appender is intentionally powerful: a separate log file per 
tenant or per long-running job, or round-robin routing between a fixed set of 
appenders, are all supported designs.
+The responsibility that comes with that power is provisioning: the system must 
be able to allocate the resources required by every appender that can be 
created.
+
+If the key is derived from untrusted or high-cardinality data (for example 
`${ctx:userId}`, a client IP, or a free-form request header), an attacker or a 
busy system can force creation of an unbounded number of appenders.
+
+That growth commonly leads to:
+
+* exhaustion of file descriptors (when each route opens a `File` or rolling 
file appender)
+* elevated memory use for appender state, buffers, and managers
+* difficulty shutting down or reconfiguring the application cleanly
+
+[#RoutingAppender-security-threat-model]
+==== Threat model
+
+An untrusted key is not only a resource problem: it is also substituted into 
the subordinate appender's configuration.
+Attributes such as `fileName` therefore inherit whatever the lookup returns.
+
+For example, with `fileName="logs/${ctx:userId}.log"`, a Thread Context value 
of `../../../../tmp/x` (as a whole path segment) can open `/tmp/x.log` without 
an error.
+Embedding the lookup inside a longer fixed segment, such as 
`logs/user-${ctx:userId}.log`, usually fails to open the file instead of 
escaping the directory, so the exact `fileName` pattern matters.
+That failure is a side effect of how paths are resolved, not a mitigation: it 
is loud rather than safe, and it does not hold for every value a lookup can 
return.
+The appender is also re-attempted, and the event lost, on every subsequent 
event with that key.
+
+This matches the project's 
{logging-services-url}/security.html#threat-common-sources-configuration[threat 
model for configuration sources]: operators are responsible for ensuring that 
appender configuration attributes come from trusted data.
+Only the application developer knows which Thread Context keys carry validated 
values and which are entirely attacker-controlled.
+See also {logging-services-url}/security/faq.html#path-traversal[path 
traversal in the security FAQ].
+
+The same substitution reaches non-file sinks: a `Route` that builds an 
xref:manual/appenders/network.adoc#HttpAppender[HTTP Appender] interpolates the 
key into its `url`, turning an untrusted routing key into a server-side request 
forgery (SSRF) vector.
+
+[#RoutingAppender-security-mitigations]
+==== Mitigations
+
+* Prefer the <<Route-attr-ref,`ref` attribute>> of a `Route`, pointing at a 
fixed, predeclared set of appenders, when the set of destinations is known.
+* When dynamic routes are required, always configure a 
<<PurgePolicy,`PurgePolicy`>> (typically <<IdlePurgePolicy,`IdlePurgePolicy`>>) 
so idle route appenders are stopped and released.
++
+Note that a purge policy bounds how long an unused appender survives, not the 
rate at which new ones are created.
+* Constrain routing keys to a low-cardinality, validated domain (allow-lists, 
enums, hashed buckets) instead of raw user input.
+* Avoid routing on pure user-controlled identifiers when each value would 
create a new file-backed appender, or when the key is interpolated into paths, 
URLs, or other sink configuration.
+* Do not create an appender per web request. 
xref:manual/api.adoc#fish-tagging[Fish tagging] the events and filtering on the 
tag is a far better use of resources.
+
 [#PurgePolicy]
 === Purge Policy
 

Reply via email to