CWE-1286 covers input that is expected to be well-formed, meaning it follows a particular syntax, where the product does not validate or incorrectly validates that it does. It reaches anything that reads JSON, XML, HTTP, IP addresses, dates, URLs or any other structured text.
How it happens
Complex inputs often follow a syntax that is either assumed by the input itself or declared in metadata such as headers. The syntax can belong to a data exchange format, a markup language or even a programming language.
When untrusted input is not checked for the expected syntax, MITRE says attackers can cause parsing failures, trigger unexpected errors, or expose latent vulnerabilities that would not be directly exploitable if the input had conformed.
That last point is the interesting one. The input is not the bug. It reaches a bug that was waiting behind the assumption of well formed data.
Two recorded cases:
- CVE-2016-4029: a chain where incorrect validation of an intended decimal IP address format (CWE-1286) allows octal or hexadecimal formats to be parsed (CWE-1389), bypassing an SSRF protection (CWE-918).
- CVE-2007-5893: an HTTP request with a missing protocol version number leads to a crash.
Vulnerable and fixed
An SSRF filter that checks a hostname string without understanding address syntax:
# Vulnerable: string checks miss alternate notations
def is_blocked(host):
return host.startswith("127.") or host == "localhost"
Many parsers accept forms such as a decimal or hexadecimal integer for an IP address. A string prefix test sees those as harmless names. A safer approach resolves the value with a strict parser and checks the parsed result:
import ipaddress
import socket
def is_blocked(host):
# Resolve to actual addresses, then check the parsed objects
infos = socket.getaddrinfo(host, None)
for info in infos:
ip = ipaddress.ip_address(info[4][0])
if ip.is_loopback or ip.is_private or ip.is_link_local:
return True
return False
Resolving first means the check runs on what the connection will actually use. For SSRF you should still connect to the address you checked, to avoid a gap between check and use, which this short sample does not show.
For structured data, parse with a strict parser and reject on failure:
import json
def load_config(raw):
try:
data = json.loads(raw)
except json.JSONDecodeError:
raise ValueError("invalid JSON")
if not isinstance(data, dict):
raise ValueError("expected an object")
return data
What an attacker gains
MITRE tags the consequences as varying by context. The recorded cases show two: a denial of service through a crash, and a bypass of a security control, here an SSRF protection. The second can open internal services to the attacker.
How to find it
The record lists no detection methods. Practical checks:
- Find every parser entry point where your code reads a format and note whether it uses a strict library or hand rolled string handling.
- Feed malformed input on purpose: truncated, missing required fields, extra fields, wrong encodings, alternate number notations.
- Fuzz network protocol handlers and file readers.
- For each security filter that works on text, such as URL, host or path allow lists, test alternate spellings of the same value.
How to fix it
The record gives no mitigation text. These steps follow from the definition.
- Parse with a well maintained, strict library instead of regular expressions or string splitting.
- Validate against the syntax first, then validate meaning. A string can be syntactically valid and still not allowed.
- Make security decisions on the parsed, canonical form of a value, not the raw string.
- Reject on any parse error. Do not guess or repair.
- Keep parser libraries updated, since many weaknesses of this type are fixed upstream.
Try it yourself
Syntax edge cases are a core part of API testing. The demo walks through scanning an API for inputs that should be rejected.
Click through it at your own pace, or open it full screen.
Quick check
Why did the IP address filter fail in the recorded chain?
It validated only the intended decimal format, so octal and hexadecimal forms were still parsed as addresses and slipped past the SSRF protection.
Should you repair malformed input?
Generally no. Rejecting it avoids creating a second, different interpretation that an attacker can exploit.