Safeguard
Application Security•

CWE-167 Additional Special Element: Extra Characters That Beat Filters

One extra angle bracket has defeated script filters. How CWE-167 works, what the observed cases show, and how to fix it with output encoding.

Safeguard Security Team
3 min read

CWE-167 describes input that includes an additional, unexpected special element, which the product does not handle correctly. The extra character is meant to confuse a filter while a browser or parser still reads the content the way the attacker wants.

It matters most for anyone writing filters that look for known bad patterns in web input.

How it happens

A filter looks for a literal pattern, such as the start of a script tag. Adding one more special character in front or inside changes what the filter sees, but a forgiving downstream parser skips the extra character and still finds the tag.

import re

# Vulnerable: removes a literal pattern and trusts the result
def sanitize(html: str) -> str:
    return re.sub(r"(?i)script", "", html)

Variants of this filter fall to inputs where a leftover or extra character makes the pattern disappear and reappear.

The observed examples are all of this kind. CVE-2000-0116 is an extra less than sign in front of a script tag that bypasses cross-site scripting prevention. CVE-2001-1157 is another extra less than sign in front of a script tag. CVE-2002-2086 involves the string script with an opening bracket and is probably a cleansing error, according to MITRE.

What an attacker gains

The record lists integrity impact as unexpected state. In these cases it means running script in a victim's browser through a filter that was supposed to stop it.

How to find it

No detection methods are listed. Use these checks.

  • Send inputs with an extra opening bracket, doubled brackets and stray characters around tags to every field that is later displayed.
  • Review sanitizers that remove or replace patterns by text matching.
  • Pass filter output through the filter again. If it changes, the filter is not stable.

How to fix it

  1. Do not try to clean markup by removing strings. Encode on output for the context where the value lands, so special characters render as text.
from html import escape

safe = escape(user_value)   # extra brackets become harmless text
  1. Anticipate that extra special elements will be injected, and use an allowlist for what is acceptable.
  2. If you must accept some markup, use a maintained sanitizer built on a real parser and keep it current.
  3. Reject input that does not conform instead of repairing it.

Quick check

Why does an extra bracket bypass a filter?

The filter looks for an exact pattern. The extra character breaks that match, but a lenient parser downstream ignores it and still sees the tag.

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.