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