VNX-777 – Regular Expression without Anchors

Overview

This rule flags regular expression patterns used for input validation that lack start (^) and end ($) anchors. Without anchors, a regex matches anywhere in the string — re.match("[0-9]+", input) matches "123abc" because it finds digits at the start, ignoring the trailing non-digits. This maps to CWE-777: Regular Expression without Anchors.

Severity: Medium | CWE: CWE-777

Why This Matters

Unanchored validation regexes are a classic validation bypass. An email validator that uses re.match("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+") accepts "admin@example.com<script>" because the match succeeds without consuming the XSS payload at the end.

What Gets Flagged

# FLAGGED: re.match without end anchor
if re.match("[0-9]+", user_id):
    # user_id = "123abc" passes! (123 matched, abc ignored)
    pass

# FLAGGED: only checks beginning, not end
if re.match("[a-zA-Z]+", username):
    pass  # "admin<script>" passes
// FLAGGED: Pattern without anchors used for validation
Pattern p = Pattern.compile("[a-z]+");
Matcher m = p.matcher(input);
if (m.find()) {  // find() matches anywhere in string!
    processInput(input);
}
// FLAGGED: regex test without anchors
if (/[0-9]+/.test(userId)) {
    // "123evil" passes
}

Remediation

# SAFE: use re.fullmatch() (Python 3.4+)
if re.fullmatch(r"[0-9]+", user_id):
    pass

# SAFE: explicit anchors
if re.match(r"^[0-9]+$", user_id):
    pass
// SAFE: String.matches() implicitly anchors
if (input.matches("[a-z]+")) { ... }

// SAFE: explicit anchors with Pattern
Pattern p = Pattern.compile("^[a-z]+$");
if (p.matcher(input).matches()) { ... }
// SAFE: explicit anchors
if (/^[0-9]+$/.test(userId)) { ... }

References