CWE-222, Truncation of Security-relevant Information, is the weakness where a product truncates the display, recording or processing of security-relevant information in a way that can obscure the source or nature of an attack.
It affects browsers and other user interfaces, logging pipelines, web filters and servers. Anywhere a length limit meets data that an attacker controls, the question is which end gets cut.
How it happens
Fixed-size fields and display widths are convenient. An attacker pads the input so the revealing part falls outside the limit. MITRE's observed examples:
- CVE-2005-0585: a web browser truncates long subdomains or paths, which helps phishing.
- CVE-2004-2032: a URL filter is bypassed with a long URL carrying many trailing hex-encoded space characters.
- CVE-2003-0412: an application server does not log the complete URI of a long request.
# Vulnerable: the log keeps only the first 100 characters of the path
log.info("request %s", request.path[:100])
An attacker sends a path with 100 harmless characters first. The payload follows, and never reaches the log.
What an attacker gains
MITRE lists non-repudiation: the attacker hides activities. The source of an attack is difficult or impossible to determine, and attacks can continue without notice.
How to find it
MITRE lists no detection methods. Search the code for slicing, fixed-size buffers and column limits applied to URLs, user names, file names, headers and log messages. Then test with inputs just over each limit and read what is recorded or shown.
How to fix it
MITRE gives no mitigations. These steps follow from the weakness:
- Log the whole value, or mark the cut. If you must limit size, say so in the record and keep a hash or the tail.
- Show the part users need. For files, keep the extension visible. For hostnames, keep the registrable domain visible.
- Process before truncating. Normalize and decide on the full value, then shorten only for display.
def clip(value: str, limit: int = 200) -> str:
if len(value) <= limit:
return value
return value[:limit] + f"...[truncated {len(value) - limit} chars]"
Quick check
Why check the filter on the full value?
If the filter only sees a clipped version, an attacker can push the dangerous part past the limit, as in the long URL example.