diff --git a/docs/Secure-Coding-Guide-for-Python/CWE-707/CWE-117/README.md b/docs/Secure-Coding-Guide-for-Python/CWE-707/CWE-117/README.md
new file mode 100644
index 000000000..c63992758
--- /dev/null
+++ b/docs/Secure-Coding-Guide-for-Python/CWE-707/CWE-117/README.md
@@ -0,0 +1,199 @@
+# CWE-117: Improper Output Neutralization for Logs
+
+Ensure all untrusted data is properly neutralized or sanitized before writing to application logs. Log injection occurs when untrusted data is written to application logs without proper neutralization, allowing attackers to forge log entries or inject malicious content. Attackers can inject fake log records or hide real ones by inserting newline sequences (`\r` or `\n`), misleading auditors and incident-response teams. This vulnerability can also enable injection of XSS attacks when logs are viewed in vulnerable web applications.
+
+Attackers can exploit this weakness (see [*Attacks on Logs*](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html#attacks-on-logs) [[OWASP 2025]](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html#attacks-on-logs)) by submitting strings containing CRLF sequences that create fake log entries.
+
+Attackers can exploit this weakness by submitting strings containing Carriage Return Line Feed (CRLF) sequences that create fake log entries. For instance, an attacker authenticating with a crafted username can make failed login attempts appear successful in audit logs, potentially framing innocent users or hiding malicious activity.
+
+This vulnerability is classified as **CWE-117: Improper Output Neutralization for Logs** [[CWE-117](https://cwe.mitre.org/data/definitions/117.html)]. It occurs when CRLF sequences are not properly neutralized in log output, which is a specific instance of the broader **CWE-93: Improper Neutralization of CRLF Sequences** [[CWE-93](https://cwe.mitre.org/data/definitions/93.html)] weakness. Attackers exploit this using the **CAPEC-93: Log Injection-Tampering-Forging** [[CAPEC-93](https://capec.mitre.org/data/definitions/93.html)] attack pattern.
+
+The OWASP Top 10 [[OWASP A09:2021](https://owasp.org/Top10/A09_2021-Security_Logging_and_Monitoring_Failures/)] lists “Security Logging and Monitoring Failures” as a critical security risk.
+
+## Noncompliant Code Example
+
+This example demonstrates how raw user input written to logs enables injection attacks:
+
+*[noncompliant01.py](noncompliant01.py):*
+
+```python
+""" Non-compliant Code Example """
+import logging
+
+def log_authentication_failed(user):
+ """Simplified audit logging missing RFC 5424 details"""
+ logging.warning("User login failed for: '%s'", user)
+
+#####################
+# attempting to exploit above code example
+#####################
+log_authentication_failed("guest'\nWARNING:root:User login failed for: 'administrator")
+```
+
+**Output of `noncompliant01.py`:**
+
+```bash
+WARNING:root:User login failed for: 'guest'
+WARNING:root:User login failed for: 'administrator'
+```
+
+The attacker's input creates what appears to be a legitimate log entry showing a login failure for user `administrator`.
+
+## Compliant Solution
+
+As per the OWASP Logging Cheat Sheet [[OWASP 2025]](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html) section on ["Event collection"](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html#event-collection), applications should sanitize event data to prevent log injection and encode data correctly for the logged format.
+
+The `compliant01.py` solution uses a strict allow-list for usernames and returns early on any mismatch, so `CR/LF` or other disallowed characters never reach the logger; for rejected attempts it logs a safe one-line summary with `%r` (escaped newlines), preventing forged secondary log lines. In short: validate upfront and neutralize what you do record.
+
+*[compliant01.py](compliant01.py):*
+
+```python
+""" Compliant Code Example """
+
+import logging
+import re
+
+# Allow only ASCII letters, digits, underscore, dot, and hyphen; max 64 chars
+_ALLOWED_USER = re.compile(r"^[A-Za-z0-9._-]{1,64}$")
+
+
+def is_allowed_username(user: str) -> bool:
+ """Return True if username matches the strict allow-list."""
+ return bool(_ALLOWED_USER.fullmatch(user))
+
+
+def log_authentication_failed(user):
+ """Simplified audit logging (example)"""
+ if not is_allowed_username(user):
+ # Safe summary: %r escapes CR/LF so the log remains one line
+ logging.warning("Rejected login attempt: invalid username=%r", user)
+ return
+ logging.warning("User login failed for: '%s'", user)
+
+
+#####################
+# attempting to exploit above code example
+#####################
+log_authentication_failed("guest'\nWARNING:root:User login failed for: 'administrator")
+
+
+
+# TODO: Production — keep sink-side neutralization (escape CR/LF) even with validation,
+# prefer structured JSON logs.
+```
+
+The following output shows that a warning is logged, and the input is sanitized before logging.
+
+**Example compliant01.py output:**
+
+```bash
+WARNING:root:Rejected login attempt: invalid username="guest'\nWARNING:root:User login failed for: 'administrator"
+```
+
+## Automated Detection
+
+
+
+
+ Tool |
+ Version |
+ Check |
+ Description |
+
+
+
+
+ Bandit |
+ 1.7.5 |
+ Not Available |
+ |
+
+
+ CodeQL |
+ Latest |
+ py-log-injection |
+ |
+
+
+ Veracode |
+ Latest |
+ CWE 117 |
+ How to Fix CWE-117 |
+
+
+
+
+## Related Guidelines
+
+
+
+## Bibliography
+
+
diff --git a/docs/Secure-Coding-Guide-for-Python/CWE-707/CWE-117/compliant01.py b/docs/Secure-Coding-Guide-for-Python/CWE-707/CWE-117/compliant01.py
index 5e69b77c3..13e12581f 100644
--- a/docs/Secure-Coding-Guide-for-Python/CWE-707/CWE-117/compliant01.py
+++ b/docs/Secure-Coding-Guide-for-Python/CWE-707/CWE-117/compliant01.py
@@ -1,26 +1,33 @@
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
-""" Compliant Code Example """
+"""Compliant Code Example"""
+
import logging
import re
+# Allow only ASCII letters, digits, underscore, dot, and hyphen; max 64 chars
+_ALLOWED_USER = re.compile(r"^[A-Za-z0-9._-]{1,64}$")
+
-def allowed_chars(user):
- """Verify only allowed characters are used"""
- if bool(re.compile(r"\w+").fullmatch(user)):
- return True
- return False
+def is_allowed_username(user: str) -> bool:
+ """Return True if username matches the strict allow-list."""
+ return bool(_ALLOWED_USER.fullmatch(user))
def log_authentication_failed(user):
- """Simplified audit logging missing RFC 5424 details"""
- if not allowed_chars(user):
- logging.critical("Login attempt with non-allowed characters in user name: '%s'", user)
+ """Simplified audit logging (example)"""
+ if not is_allowed_username(user):
+ # Safe summary: %r escapes CR/LF so the log remains one line
+ logging.warning("Rejected login attempt: invalid username=%r", user)
+ return
logging.warning("User login failed for: '%s'", user)
#####################
# attempting to exploit above code example
#####################
-log_authentication_failed("""foo
-WARNING:root:User login failed for: administrator""")
+log_authentication_failed("guest'\nWARNING:root:User login failed for: 'administrator")
+
+
+# TODO: Production — keep sink-side neutralization (escape CR/LF) even with validation,
+# prefer structured JSON logs.
diff --git a/docs/Secure-Coding-Guide-for-Python/CWE-707/CWE-117/noncompliant01.py b/docs/Secure-Coding-Guide-for-Python/CWE-707/CWE-117/noncompliant01.py
index 2105df82c..228380faa 100644
--- a/docs/Secure-Coding-Guide-for-Python/CWE-707/CWE-117/noncompliant01.py
+++ b/docs/Secure-Coding-Guide-for-Python/CWE-707/CWE-117/noncompliant01.py
@@ -1,6 +1,7 @@
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
-""" Non-compliant Code Example """
+"""Non-compliant Code Example"""
+
import logging
@@ -12,5 +13,4 @@ def log_authentication_failed(user):
#####################
# attempting to exploit above code example
#####################
-log_authentication_failed("""foo
-WARNING:root:User login failed for: administrator""")
+log_authentication_failed("guest'\nWARNING:root:User login failed for: 'administrator")
diff --git a/docs/Secure-Coding-Guide-for-Python/readme.md b/docs/Secure-Coding-Guide-for-Python/readme.md
index c46ad3d74..3f302957a 100644
--- a/docs/Secure-Coding-Guide-for-Python/readme.md
+++ b/docs/Secure-Coding-Guide-for-Python/readme.md
@@ -110,7 +110,7 @@ It is __not production code__ and requires code-style or python best practices t
|:----------------------------------------------------------------|:----|
|[CWE-78: Improper Neutralization of Special Elements Used in an OS Command ("OS Command Injection")](CWE-707/CWE-78/README.md)|[CVE-2024-43804](https://www.cvedetails.com/cve/CVE-2024-43804/),
CVSSv3.1: __8.8__,
EPSS: __00.06__ (08.11.2024)|
|[CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')](CWE-707/CWE-89/README.md)|[CVE-2019-8600](https://www.cvedetails.com/cve/CVE-2019-8600/),
CVSSv3.1: __9.8__,
EPSS: __01.43__ (18.02.2024)|
-|[CWE-117: Improper Output Neutralization for Logs](CWE-707/CWE-117/.)||
+|[CWE-117: Improper Output Neutralization for Logs](CWE-707/CWE-117/README.md)||
|[CWE-175: Improper Handling of Mixed Encoding](CWE-707/CWE-175/README.md)||
|[CWE-180: Incorrect behavior order: Validate before Canonicalize](CWE-707/CWE-180/README.md)|[CVE-2022-26136](https://www.cvedetails.com/cve/CVE-2022-26136/),
CVSSv3.1: __9.8__,
EPSS: __00.18__ (24.04.2025)|
|[CWE-838: Inappropriate Encoding for Output Context](CWE-707/CWE-838/README.md)||