Safeguard
Application Security•

CWE-185 Incorrect Regular Expression: Anchors, Nulls and Bypasses

A regex that is not anchored, or that fails on odd input, can let spoofed values through. How CWE-185 happens and how to write validation patterns that hold.

Safeguard Security Team
3 min read

CWE-185, Incorrect Regular Expression, is about a regular expression that is written so that data is matched or compared wrongly. When the pattern guards filtering or validation, a mistake lets an attacker bypass the restriction.

This is a class level weakness, so it covers many specific mistakes. Anyone validating input with patterns is in scope.

How it happens

The common mistakes in MITRE's examples are small. A pattern that is not anchored to the start or end matches a trusted value hidden inside a longer, malicious one. CVE-2002-2109 describes this: the regexp was not anchored at the beginning or end, so spoofed values containing trusted values as substrings passed. CVE-2005-1949 is an IP address regexp not anchored at the end, which allowed shell metacharacters to be appended.

Other cases: CVE-2001-1072 bypassed access restrictions with multiple leading slashes that made a regular expression fail, and CVE-2000-0115 let a local user cause a denial of service with invalid regular expressions.

MITRE also notes a language specific trap: in PHP, regular expression checks can sometimes be bypassed with a null byte.

import re

# Vulnerable: search matches anywhere, so "10.0.0.1; rm -rf /" passes
def is_ip(s):
    return re.search(r"\d+\.\d+\.\d+\.\d+", s) is not None

# Fixed: whole string must match
def is_ip(s):
    return re.fullmatch(r"(\d{1,3}\.){3}\d{1,3}", s) is not None

Even the fixed version only checks the shape. If you need real validity, use the language's IP address parser after the shape check.

What an attacker gains

MITRE lists two kinds of impact. One is an unexpected state, because data may have a different format or type than the rest of the program assumes. The other is access control bypass of a protection mechanism.

How to find it

MITRE says static analysis (SAST) can find some instances by following data flow. Add these checks in review and test:

  • Does every validation pattern anchor both ends, or use a full match function?
  • What happens with a newline, a null byte, or a very long input?
  • Are the patterns tested with values that should fail, not only with values that should pass?

How to fix it

The record lists no mitigations, so these are general steps.

  1. Anchor patterns and use whole string matching.
  2. Prefer built in parsers for structured data like IP addresses, URLs and dates.
  3. Reject null bytes and unexpected control characters before the pattern runs.
  4. Write negative tests for every pattern guarding a security decision.

Try it yourself

Click through it at your own pace, or open it full screen.

Quick check

What does "not anchored" mean? The pattern can match a piece in the middle of the input, so extra characters before or after are allowed unless you forbid them.

Is a regex ever enough for validating an IP address? It can check the shape, but a parser from the standard library is better for deciding whether the value is actually valid.

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.