Description
Currently RoutingAppender based on its configuration can materialize an unbounded number of routes. This coupled with a user controlled or high cardinality key can result in File descriptor exhaustion.
Example configuration which can be problematic:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Routing name="Routing">
<Routes pattern="${ctx:userId}">
<Route>
<File name="File-${ctx:userId}" fileName="logs/user-${ctx:userId}.log">
<PatternLayout pattern="%d %p %c{1.} [%t] %m%n"/>
</File>
</Route>
</Routes>
<IdlePurgePolicy timeToLive="10" cleanupIntervalMillis="1000"/>
</Routing>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Routing"/>
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
Configuration
Version: 2.26.3
Operating system: Mac OS 15
JDK: openjdk64-25.0.3
Logs
N/A
Reproduction
log4j config:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Routing name="Routing">
<Routes pattern="${ctx:userId}">
<Route>
<File name="File-${ctx:userId}" fileName="logs/user-${ctx:userId}.log">
<PatternLayout pattern="%d %p %c{1.} [%t] %m%n"/>
</File>
</Route>
</Routes>
<IdlePurgePolicy timeToLive="10" cleanupIntervalMillis="1000"/>
</Routing>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Routing"/>
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
Java Code to Trigger the bug:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
import java.util.UUID;
public class Harness {
private static final Logger logger = LogManager.getLogger(Harness.class);
public static void main(String[] args) {
System.out.println("Starting DoS harness...");
for (int i = 0; i < 1000000; i++) {
String userId = UUID.randomUUID().toString();
ThreadContext.put("userId", userId);
[logger.info](http://logger.info/)("Log message for user: " + userId);
if (i % 10000 == 0) {
System.out.println("Logged " + i + " unique users...");
}
}
System.out.println("Finished logging.");
}
}
Detected using Decypher
Description
Currently
RoutingAppenderbased on its configuration can materialize an unbounded number of routes. This coupled with a user controlled or high cardinality key can result in File descriptor exhaustion.Example configuration which can be problematic:
Configuration
Version: 2.26.3
Operating system: Mac OS 15
JDK: openjdk64-25.0.3
Logs
N/A
Reproduction
log4j config:
Java Code to Trigger the bug:
Detected using Decypher