CWE-179, Incorrect Behavior Order: Early Validation, is a sequencing mistake. The product validates input before applying protection steps that change that input. An attacker can then supply a value that looks fine at the check and becomes dangerous after the change.
Any application with a pipeline of "check, then clean up, then use" is a candidate. Web servers, filename handlers, and database layers are the usual victims.
How it happens
MITRE puts it directly: data has to be validated at the proper time, after it has been canonicalized and cleansed. Early validation is open to manipulations that produce dangerous input out of the cleansing step itself.
Here is a simple case. The code rejects the string "../" and then strips the letter X from the input. An attacker sends "..X/", which passes the check and turns into "../" afterward.
# Vulnerable: validate, then modify
def clean(name):
if "../" in name:
raise ValueError("bad")
return name.replace("X", "") # "..X/" becomes "../" after the check
# Fixed: modify first, then validate the final value
def clean(name):
name = name.replace("X", "")
if "../" in name:
raise ValueError("bad")
return name
MITRE's observed examples include CVE-2003-0332, where a product modified the first two letters of a filename extension after a security check, allowing authentication bypass with a different extension. In CVE-2002-0802, a database consumed an extra character when it hit one it could not convert, which could remove an escape character from a query and open the door to SQL injection. See CVE-2002-0433 as well, which involved listing files with a wildcard pattern.
What an attacker gains
MITRE lists access control and integrity impact, bypass of protection mechanisms, and execution of unauthorized code or commands. It also says the dangerous input can be used to launch injection attacks or cause other unintended behavior.
How to find it
Trace each input from entry to use and list every transformation along the way: decode, trim, strip, replace, normalise, convert charset. Any check that sits before one of those steps is suspect. In testing, feed values built to become forbidden after each transformation.
How to fix it
The record gives no mitigations, so these steps are general practice.
- Finish all transformations first.
- Validate the final form, immediately before use.
- Prefer an allowlist of what is valid over a list of what is bad.
- Avoid cleansing steps that remove characters from the middle of a value. Reject instead.
Quick check
What is the one rule that prevents this weakness?
Validate the exact value that will be used, after every change to it has been made.