Regex Empty Character Class
ID |
javascript.regex_empty_char_class |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
JavaScript |
Tags |
reliability |
Description
Reports a character class with no members inside a regex literal or a new RegExp("…") pattern.
There are two such classes and JavaScript accepts both:
-
[]matches no character at all, so the alternative it belongs to can never match; -
[^]is its complement and matches every character, line terminators included.
Neither is a syntax error, so neither is caught when the pattern is parsed — the pattern simply stops doing what it says.
Rationale
const slug = new RegExp("^[a-z]+[]$"); // never matches anything
if (slug.test("hello")) { // dead branch
save();
}
const between = new RegExp("start[^]end"); // any bytes at all, across lines
An empty class is nearly always the residue of an edit: the members were deleted, or the brackets were meant to be escaped and match literally. Because the class is still syntactically fine, the failure shows up as a validation that never triggers or a search that quietly returns nothing.
The negated form is the mirror image. [^] is occasionally written on purpose as "any character
including newline", but it reads as a class that forgot its members, and the modern spelling of
that intent is explicit.
Remediation
Put the members back, escape the brackets if they were meant literally, or say "anything" the way that reads as deliberate:
const slug = new RegExp("^[a-z]+$");
const literalBrackets = new RegExp("\\[\\]"); // matches the two characters [ and ]
const between = new RegExp("start[\\s\\S]*end");
const alsoBetween = new RegExp("start.*end", "s"); // the dotAll flag