CWE-791 is a base level weakness: the product receives data from an upstream component but does not completely filter special elements before sending it to a downstream component.
The word to notice is completely. The code does filter. It just does not finish the job.
How it happens
A filter starts life covering the cases the developer had in mind. Later someone finds another special character, another encoding, or another place the element can appear, and the filter is not updated. Or the author never knew the full list for the downstream system in the first place.
def sanitize_path(p):
p = p.replace("../", "") # removes one form only
return p
Input such as ....// becomes ../ after the replace. The filter ran and the result is still dangerous. That is incomplete filtering in one line. Narrower forms of this weakness, such as filtering only one instance, or only a certain position, are covered by their own entries (CWE-792 and CWE-795).
What an attacker gains
The MITRE record lists integrity and an unexpected state, with no observed CVEs. The practical gain is whatever the downstream component allows once a special element gets through: altered queries, commands, markup or file paths.
How to find it
- List what the destination treats as special, from its documentation, not from memory.
- Compare that list with what your filter removes or escapes.
- Test with repeated, nested and re-encoded special elements.
- Look for single-pass replace calls, which are a sign that output may still contain the thing you removed.
How to fix it
- Stop trying to enumerate bad characters. Use the downstream component's safe API, such as parameterized queries or argument lists.
- If you must transform input, use an allowlist and reject whatever does not match.
- Canonicalize first, then validate the canonical form.
- For path handling, resolve the final path and confirm it sits inside the intended directory, rather than stripping dot sequences.
- Run the filter's output through the same check again if you can, to prove nothing is left.
Quick check
Why does removing the string dot-dot-slash once fail?
Removal can create a new match from the leftover pieces. Resolving the real path and checking its location is safer.