Skip to main content
interlace
Plugin: secure-codingRules

no-unsafe-regex-construction

ESLint Rule: no-unsafe-regex-construction with LLM-optimized suggestions and auto-fix capabilities

CWE: CWE-693
OWASP Mobile: OWASP Mobile Top 10

ESLint Rule: no-unsafe-regex-construction with LLM-optimized suggestions and auto-fix capabilities. This rule is part of eslint-plugin-secure-coding.

Quick Summary

AspectDetails
CWE ReferenceCWE-185 (Incorrect Regular Expression)
SeverityError (Security)
Auto-Fix❌ No
CategorySecurity
ESLint MCP✅ Optimized for ESLint MCP integration
Best ForProduction applications handling user input
Suggestions✅ Advice on escaping input

Vulnerability and Risk

Vulnerability: Constructing regular expressions from untrusted or unvalidated user input.

Risk: Attackers can inject malicious regex patterns (Regex Injection) or complex patterns that cause excessive backtracking (ReDoS), leading to Denial of Service. They might also alter the logic of the regex to bypass validations (e.g., changing a match standard to match anything).

Error Message Format

The rule provides LLM-optimized error messages (Compact 2-line format) with actionable security guidance:

🔒 CWE-400 OWASP:A06 CVSS:7.5 | Uncontrolled Resource Consumption (ReDoS) detected | HIGH
   Fix: Review and apply the recommended fix | https://owasp.org/Top10/A06_2021/

Message Components

ComponentPurposeExample
Risk StandardsSecurity benchmarksCWE-400 OWASP:A06 CVSS:7.5
Issue DescriptionSpecific vulnerabilityUncontrolled Resource Consumption (ReDoS) detected
Severity & ComplianceImpact assessmentHIGH
Fix InstructionActionable remediationFollow the remediation steps below
Technical TruthOfficial referenceOWASP Top 10

Rule Details

This rule detects the creation of RegExp objects using user-controlled input. Constructing a regular expression from untrusted input is dangerous because it leads to:

  1. ReDoS (Regular Expression Denial of Service): An attacker can provide a pattern that causes catastrophic backtracking (e.g., (a+)+).
  2. Logic Errors: An attacker can inject special characters (like *, +, |) to alter the matching behavior in unintended ways.

Why This Matters

IssueImpactSolution
🔒 SecurityDenial of Service (DoS)Escape user input before creating RegExp
🐛 LogicRegex Injection (bypassing filters)Use escape-string-regexp

Configuration

This rule accepts an options object:

{
  "rules": {
    "secure-coding/no-unsafe-regex-construction": ["error", {
      "allowLiterals": false,           // Default: false. Allow new RegExp("fixed-string").
      "trustedEscapingFunctions": ["escapeRegex", "escape", "sanitize"], // Default list of safe functions.
      "maxPatternLength": 100           // Default: 100. Limit the length of dynamic patterns.
    }]
  }
}

Examples

❌ Incorrect

// Direct user input usage
const pattern = new RegExp(req.query.search);

// Template literal with user input
const pattern2 = new RegExp(`^${req.query.prefix}`);

// Passing request input through a variable without sanitization
function search(req) {
  const term = req.query.term;
  return new RegExp(term, 'i');
}

This rule reports only a pattern whose source it can name: a request member (directly, through a local, or spliced into a template), process.argv, or bytes read from a file or response body. A pattern built from a bare function parameter or another value of unknown provenance — function search(term) { return new RegExp(term, 'i'); } — is not attributed here; it is reported by detect-non-literal-regexp, so the two rules never report the same line twice at two severities.

✅ Correct

const regex = /^[a-z]+$/;

LLM-Based Suggestions

The rule provides guidance on how to fix detected patterns:

  • "Escape User Input": Suggests using a library like escape-string-regexp to neutralize special characters.
  • "Use Literal": Suggests converting new RegExp("constant") to /constant/ if possible.

Known False Negatives

The following patterns are not detected due to static analysis limitations:

Wrapper Functions

Why: Custom wrappers not recognized.

// ❌ NOT DETECTED - Wrapper
myWrapper(userInput); // Uses dangerous API internally

Mitigation: Apply rule to wrapper implementations.

Dynamic Invocation

Why: Dynamic calls not analyzed.

// ❌ NOT DETECTED - Dynamic
obj[method](userInput);

Mitigation: Avoid dynamic method invocation.

Further Reading

⚙️ Options

OptionTypeDefaultDescription
requestRootNamesstring[]["req","request","ctx","event","message"]Identifier names that select a candidate inbound request. Replaces the default.
allowLiteralsbooleantrueAllow literal string patterns
trustedEscapingFunctionsstring[]["escapeRegex","escapeRegExp","escapeStringRegexp","regexpEscape"]Trusted functions that escape input
maxPatternLengthnumber100Maximum pattern length for dynamic regex

Use this rule

npm install -D oxlint-plugin-secure-coding
.oxlintrc.json
{  "jsPlugins": ["oxlint-plugin-secure-coding"],  "rules": {    "secure-coding/no-unsafe-regex-construction": "error"  }}
vite.config.ts
import { defineConfig } from 'vite-plus';export default defineConfig({  lint: {    jsPlugins: ['oxlint-plugin-secure-coding'],    rules: {      'secure-coding/no-unsafe-regex-construction': 'error',    },  },});

oxlint-plugin-secure-coding re-exports eslint-plugin-secure-coding/oxlint: the same rules under the same IDs, and no ESLint install. Why oxlint.

Did this rule catch something? Star the repo to get new CWE coverage as we ship it — or follow the AI-code-security benchmarks behind these rules.