Safeguard
Application Security•

CWE-791 Incomplete Filtering of Special Elements

A filter that catches most special elements but not all still lets attacks through. See what CWE-791 covers and how to design safer handling.

Safeguard Security Team
2 min read

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

  1. Stop trying to enumerate bad characters. Use the downstream component's safe API, such as parameterized queries or argument lists.
  2. If you must transform input, use an allowlist and reject whatever does not match.
  3. Canonicalize first, then validate the canonical form.
  4. For path handling, resolve the final path and confirm it sits inside the intended directory, rather than stripping dot sequences.
  5. 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.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.