Safeguard
Application Security•

CWE-168 Inconsistent Special Elements: Misordered and Unnested Input

Pairs in the wrong order or special characters that are not nested properly can crash parsers and hide activity. How to find and fix CWE-168.

Safeguard Security Team
3 min read

CWE-168 covers input where two or more special characters or reserved words are in an inconsistent relationship. MITRE's examples: paired characters that appear in the wrong order, or special characters that are not properly nested.

Parsers for query languages, markup, expressions and protocols deal with this constantly. Any code that counts or matches openers and closers can be fooled.

How it happens

A parser or validator handles pairs with a simple rule, such as count the opening and closing characters and check that the numbers match. Equal counts do not mean valid structure. A closer before its opener has the same count as the correct order.

# Vulnerable: equal counts do not prove correct nesting
def balanced(s: str) -> bool:
    return s.count("(") == s.count(")")

balanced(")(")   # True, but the structure is wrong

The record lists no observed example CVEs for this entry. The consequences MITRE lists are wide, which is a signal about how different downstream parsers can react: availability loss through a crash, exit or restart, access control bypass, bypass of protection mechanisms, hiding activities, and impact on non-repudiation.

What an attacker gains

Each recorded impact follows from a misparse.

  • Crash, exit or restart, when the parser hits a state it did not plan for.
  • Bypass of protection mechanisms and access control, when a check and a consumer read the structure differently.
  • Hiding activities and weakening non-repudiation, when logs or records are built from input whose structure was misread.

How to find it

MITRE lists no detection methods. Test directly.

  • Send reversed pairs, interleaved pairs and mismatched types, such as an opening parenthesis closed by a bracket.
  • Include deeply nested input to look for stack or resource problems.
  • Compare the validator's reading with the consumer's.

How to fix it

  1. Anticipate that inconsistent special elements will be injected or manipulated.
  2. Check structure with a stack, not a counter. Push openers, pop on closers, and fail on a mismatch or leftover.
PAIRS = {")": "(", "]": "[", "}": "{"}

def balanced(s: str) -> bool:
    stack = []
    for ch in s:
        if ch in "([{":
            stack.append(ch)
        elif ch in PAIRS:
            if not stack or stack.pop() != PAIRS[ch]:
                return False
    return not stack
  1. Limit nesting depth and input length.
  2. Use a real parser for structured formats and reject input that does not conform.
  3. Consider consistency across related fields as well as within one field.

Quick check

Why is counting not enough?

Counts ignore order. A closing character before an opening one still balances the totals but breaks the structure.

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.