Safeguard
Application Security•

CWE-117 Log Injection: Neutralizing Output Written to Logs

Logging external input verbatim lets attackers forge entries and mislead investigators. CWE-117 explained, with a Python fix.

Safeguard Security Team
3 min read

CWE-117, Improper Output Neutralization for Logs, applies when a product builds a log message from external input and does not neutralize special elements as the message is written to the log file.

Logs are what you read after something goes wrong. If an attacker can write into them, they can shape the story you find.

How it happens

The easy mistake is logging a user supplied value as is.

import logging
log = logging.getLogger("auth")

def login_failed(username):
    log.warning("Failed login for user " + username)

# username = "bob\n2026-10-19 09:00:00 INFO Login OK for user admin"

The output now holds two lines. The second looks like a genuine entry from your application. MITRE's observed example, CVE-2006-4624, is exactly this: a chain that injects fake log entries with fake timestamps using CRLF injection.

What an attacker gains

MITRE lists integrity, confidentiality, availability and non-repudiation impact. Interpretation of the log files may be hindered or misdirected when attacker data is logged verbatim. The most benign result is confusion. It also lets an attacker hide activities, and MITRE includes execution of unauthorized code or commands as a possibility, for example if a log viewer or a downstream tool interprets what it reads.

How to find it

MITRE says static analysis can find some instances. Search your log calls for string concatenation or formatting with request data, headers, usernames and file names. Then test: send a value containing a line break and see whether a forged line appears in the real output.

How to fix it

MITRE's mitigations are the familiar pair. Validate input with an accept known good strategy, and use an output encoding that the downstream reader can handle. It also says to decode and canonicalize input to the internal representation before validating, so nothing is decoded twice and slips past the check.

In practice, make line breaks impossible inside a single record.

def clean(value):
    return value.replace("\r", "\\r").replace("\n", "\\n")

def login_failed(username):
    log.warning("Failed login for user %s", clean(username))

Structured logging, where each event is one encoded record such as a JSON object, gives the same protection with less effort. Whatever you pick, keep readers in mind: dashboards, parsers and log viewers each interpret text in their own way.

Quick check

Why does a forged log entry matter?

Investigators rely on logs. A fake entry with a plausible timestamp can mislead them or cover real activity.

Sources

Never miss an update

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

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.