Detective desk with regex patterns on a corkboard and a cat lounging nearby

Regex Cop on Duty: eslint-plugin-regexp

The Orange Cat
The Orange Cat

Regular expressions are the Swiss Army knife of text processing, but they are also one of the easiest ways to introduce subtle bugs into a codebase. A misplaced quantifier, a forgotten flag, or an overly greedy pattern can cause anything from silent data corruption to full-blown denial-of-service vulnerabilities. eslint-plugin-regexp is an ESLint plugin that brings 80 specialized rules to your linting pipeline, catching regex mistakes that would otherwise slip through code review unnoticed.

Whether you are validating user input, parsing log files, or building a search feature, this plugin watches your back. It covers correctness, performance, and style, making sure your patterns do exactly what you intend.

Eighty Rules and Counting

The plugin organizes its rules into three categories. The first group, with 22 rules, focuses on possible errors -- patterns that are outright wrong or dangerously ambiguous. The second group of 36 rules promotes best practices, including performance optimizations and safer alternatives. The third group of 20 rules handles stylistic consistency, ensuring your team writes regex the same way.

The recommended configuration alone enables roughly 45 of these rules, striking a balance between thoroughness and noise. If you want the full experience, the all configuration turns on every single rule.

Getting Started

Installation

Install the plugin alongside ESLint:

npm install --save-dev eslint eslint-plugin-regexp
yarn add --dev eslint eslint-plugin-regexp

Wiring It Up

Version 3.0 is ESM-only and requires ESLint v9.38.0 or later with flat config. The setup is minimal:

// eslint.config.js
import regexpPlugin from "eslint-plugin-regexp";

export default [
  regexpPlugin.configs.recommended,
];

That single line gives you the recommended set of rules. If you want to cherry-pick specific rules instead, register the plugin manually:

// eslint.config.js
import regexpPlugin from "eslint-plugin-regexp";

export default [
  {
    plugins: { regexp: regexpPlugin },
    rules: {
      "regexp/no-super-linear-backtracking": "error",
      "regexp/no-useless-flag": "warn",
      "regexp/prefer-character-class": "warn",
    },
  },
];

Your Regex Safety Net

Catching Catastrophic Backtracking

The no-super-linear-backtracking rule is arguably the most valuable rule in the entire plugin. It detects patterns that can cause exponential or polynomial backtracking, a class of vulnerability known as ReDoS (Regular Expression Denial of Service). A single malicious input string against a vulnerable pattern can freeze your application for minutes or longer.

// This pattern has catastrophic backtracking potential
// eslint-plugin-regexp will flag it
const badPattern = /^(a+)+$/;

// The plugin suggests a safe alternative
const safePattern = /^a+$/;

The rule does not just warn you -- it often provides an auto-fix that rewrites the pattern to eliminate the backtracking risk entirely.

Spotting Dead Code in Patterns

Several rules detect parts of a regex that do nothing useful. The no-useless-assertions rule catches assertions that always accept or always reject. The no-useless-backreference rule finds backreferences that can never match anything meaningful. The no-useless-quantifier rule removes quantifiers that have no effect.

// The \b assertion here is useless because it's already at a word boundary
const pattern = /\bhello\b/;

// Unnecessary non-greedy quantifier (only one possible match length)
const another = /a{3}?/;
// Flagged: the lazy modifier does nothing when the quantifier is fixed-length

Enforcing the Unicode Flag

The require-unicode-regexp rule pushes your team toward using the u flag on all regular expressions. Without it, patterns may silently mishandle multi-byte characters, emoji, and other Unicode text. The related require-unicode-sets-regexp rule encourages the newer v flag for even more powerful Unicode support.

// Without the u flag, this pattern may misbehave on emoji
const noUnicode = /^.$/;

// With the u flag, the dot correctly matches a single Unicode code point
const withUnicode = /^.$/u;

Power Moves

Auto-Fix Your Patterns

Many rules in the plugin support ESLint's --fix flag. Running eslint --fix can automatically simplify character classes, remove unnecessary escapes, sort flags alphabetically, and even rewrite patterns to eliminate backtracking. This is not just cosmetic cleanup -- it can prevent real bugs.

// Before auto-fix: unnecessary escape and unsorted flags
const before = /\a/gi;

// After auto-fix: escape removed, flags sorted
const after = /a/gi;
// Before: verbose alternation
const verbose = /a|b|c|d/;

// After auto-fix: character class
const concise = /[a-d]/;

Analyzing Constructor Calls

The plugin does not just analyze regex literals. It also inspects new RegExp() constructor calls, catching issues in dynamically built patterns that are notoriously hard to review by eye.

// The plugin catches issues here too
const dynamic = new RegExp("(a+)+$");
// Flagged: super-linear backtracking in RegExp constructor

This is particularly useful in codebases where patterns are assembled from variables or configuration, since those patterns are invisible to most static analysis tools.

Cleaning Up Character Classes

A suite of rules targets character class hygiene. The no-useless-character-class rule removes single-character classes that serve no purpose. The prefer-range rule enforces ranges like [a-d] instead of [abcd]. The simplify-set-operations rule streamlines intersection and subtraction expressions.

// Unnecessary character class wrapping a single character
const wrapped = /[a]/;
// Auto-fixed to: /a/

// Verbose enumeration instead of a range
const enumerated = /[0123456789]/;
// Auto-fixed to: /[0-9]/ or simplified to /\d/

A Clean Regex Style Guide

The stylistic rules bring consistency to how your team writes patterns. The prefer-d and prefer-w rules enforce shorthand character classes. The sort-flags rule keeps flags in alphabetical order. The match-any rule enforces a consistent way to write "match any character" patterns.

These may seem minor individually, but across a large codebase they reduce cognitive load during code review. When every regex follows the same conventions, spotting actual bugs becomes much easier.

// Inconsistent flag ordering
const messy = /hello/gi;

// After sort-flags: alphabetical
const tidy = /hello/gi;
// (flags already sorted in this case, but imagine /misgu -> /gimsu)

Wrapping Up

eslint-plugin-regexp fills a gap that ESLint's built-in rules barely touch. Where ESLint ships roughly five regex-related rules, this plugin delivers 80. It catches security vulnerabilities, eliminates dead code in patterns, enforces consistency, and auto-fixes many issues on the spot. With over a million weekly downloads on npm, it has earned its place as the standard tool for regex quality in JavaScript and TypeScript projects. If you write regular expressions -- and you almost certainly do -- this plugin deserves a spot in your ESLint config.