Prevent Log Injection in Log4j2: Clean Input, PatternLayout, and Custom Throwable Converter
This article explains how malicious newline characters in logged usernames can cause log injection, demonstrates a simple input‑sanitizing method, shows how to use Log4j2's %enc{%m}{CRLF} pattern and a custom ThrowablePatternConverter to ensure all log messages and exception stacks remain on a single safe line.
A new system's login module logs every attempt; an attacker supplies a username containing a newline, bypassing whitelist validation and causing log injection that leads to false account bans.
Simple remediation: replace newline characters in log parameters before logging.
public static String getCleanedMsg(String message) {
if (message == null) {
return "";
}
message = message.replace('
', '_').replace('\r', '_');
return message;
}
LOGGER.warn("username is wrong,userName={}", getCleanedMsg(userName));When many legacy log statements exist, leverage Log4j2's built‑in encoding to automatically filter CR/LF characters.
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}][%-5p] [%t] [%c{10}#%M:%L] %enc{%m}{CRLF} %n " />
</Console>For exception stack traces, create a custom ThrowablePatternConverter that encodes newline characters in the exception message.
@Plugin(name = "UndefineThrowablePatternConverter", category = PatternConverter.CATEGORY)
@ConverterKeys({"uEx"})
public class UndefineThrowablePatternConverter extends ThrowablePatternConverter {
static class EncodeThrowableProxy extends ThrowableProxy {
public EncodeThrowableProxy(Throwable throwable) { super(throwable); }
@Override
public String getMessage() {
return super.getMessage().replaceAll("\r", "\\r").replaceAll("
", "\
");
}
}
protected UndefineThrowablePatternConverter(Configuration config, String[] options) {
super("UndefineThrowable", "throwable", options, config);
}
public static UndefineThrowablePatternConverter newInstance(final Configuration config, final String[] options) {
return new UndefineThrowablePatternConverter(config, options);
}
@Override
public void format(final LogEvent event, final StringBuilder toAppendTo) {
Throwable throwable = event.getThrown();
if (throwable == null) return;
EncodeThrowableProxy proxy = new EncodeThrowableProxy(throwable);
proxy.formatExtendedStackTraceTo(toAppendTo, options.getIgnorePackages(),
options.getTextRenderer(), getSuffix(event), options.getSeparator());
}
}Adding %uEx to the layout activates this converter, ensuring exception messages are also protected from injection.
Key takeaways: Whitelist validation cannot prevent log injection when error inputs are logged; use Log4j2's encoding features ( %enc{%m}{CRLF}) to handle all parameters centrally; also sanitize exception messages with a custom converter to eliminate injection risks.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Huawei Cloud Developer Alliance
The Huawei Cloud Developer Alliance creates a tech sharing platform for developers and partners, gathering Huawei Cloud product knowledge, event updates, expert talks, and more. Together we continuously innovate to build the cloud foundation of an intelligent world.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
