CWE-148 applies when the product does not properly handle a missing or malformed leading character or sequence, called a leader, or when multiple leaders are used where only one is allowed. It is a variant of CWE-140 and is language-neutral. MITRE's record lists no observed CVEs for it.
How it happens
Some formats expect a prefix. A comment marker, a quote, a protocol verb, a path separator or a scheme can all act as a leader. The parser relies on it to decide how to read what follows.
Trouble starts in three ways, all drawn from the definition.
- The leader is missing, and the parser falls back to a different interpretation.
- The leader is malformed, and the parser accepts it in a form the author did not expect.
- More than one leader is present, and a check that looks for one is satisfied while the consumer sees another.
MITRE notes that an injected, absent or malformed delimiter may cause the process to take unexpected actions. A short sketch of the third case follows.
# Vulnerable: strips one leading slash, but the consumer sees the second
def clean(p):
return p[1:] if p.startswith("/") else p
# clean("//admin") returns "/admin", which is still an absolute path
The check removed one leader and assumed that was enough. Repeated leaders are why strict parsing beats strip-and-hope.
What an attacker gains
The listed consequence is an integrity impact with an unexpected state. The attacker can make the program interpret input differently from what the validator intended, which may defeat checks that relied on the prefix.
How to find it
The record has no detection section. Useful checks are to feed each parser inputs with no leader, a damaged leader and several leaders in a row, then compare how the validator and the consumer treat them. Any difference is a finding.
How to fix it
- Validate that the input has exactly one well-formed leader, and reject anything else.
- Normalize once, in one place, and let validator and consumer use the same normalized value.
- Prefer a real parser for the format over string slicing.
- Test the edges: empty input, a leader alone, and repeated leaders.
Quick check
Why is stripping a single leading character risky?
If the input has two, one remains after the strip, and the consumer may still treat it as meaningful. Loop until none remain, or better, reject input with unexpected leaders.