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)) { ... }