Interlace ESLint
ESLint Interlace
Secure CodingRules

detect-non-literal-regexp

Detects `RegExp(variable)`, which might allow an attacker to DOS your server with a long-running regular expression. This rule is part of [`eslint-plugin-secure

Keywords: ReDoS, CWE-400, security, ESLint rule, regular expression denial of service, RegExp, regex injection, performance, auto-fix, LLM-optimized, code security

Detects RegExp(variable), which might allow an attacker to DOS your server with a long-running regular expression. This rule is part of eslint-plugin-secure-coding and provides LLM-optimized error messages with fix suggestions.

🚨 Security rule | 💡 Provides LLM-optimized guidance | ⚠️ Set to error in recommended

Quick Summary

AspectDetails
CWE ReferenceCWE-400 (ReDoS - Regular Expression Denial of Service)
SeverityHigh (performance/security issue)
Auto-Fix⚠️ Suggests fixes (manual application)
CategorySecurity
ESLint MCP✅ Optimized for ESLint MCP integration
Best ForApplications processing user input with regex, validation libraries

Vulnerability and Risk

Vulnerability: Creating regular expressions from dynamic, untrusted input (e.g., using new RegExp()) can lead to the creation of complex or malicious patterns.

Risk: Attackers can craft regular expressions that cause catastrophic backtracking (ReDoS - Regular Expression Denial of Service), leading to high CPU usage and making the application unresponsive. In some cases, it might also allow for bypassing validation logic.

Rule Details

This rule detects dangerous use of RegExp constructor with dynamic patterns that can lead to Regular Expression Denial of Service (ReDoS) attacks.

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

Configuration

OptionTypeDefaultDescription
allowLiteralsbooleanfalseAllow literal string regex patterns
additionalPatternsstring[][]Additional RegExp creation patterns
maxPatternLengthnumber100Maximum allowed pattern length

Examples

❌ Incorrect

// ReDoS - CRITICAL risk
new RegExp(userInput); // Attacker can cause exponential backtracking

// Complex dynamic patterns - HIGH risk
RegExp(`^${userPattern}$`); // Unvalidated pattern construction

// ReDoS in literal regex - MEDIUM risk
/(a+)+b/.test(input); // Nested quantifiers cause backtracking

✅ Correct

// Pre-defined patterns
const PATTERNS = {
  email: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
  phone: /^\+?[\d\s\-\(\)]+$/,
  url: /^https?:\/\/[^\s/$.?#].[^\s]*$/i,
};

// Safe usage
if (PATTERNS[userChoice]) {
  const result = PATTERNS[userChoice].test(input);
}

// Dynamic with escaping
function escapeRegex(string: string): string {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

const safePattern = new RegExp(`^${escapeRegex(userInput)}$`);

// Length validation
if (userPattern.length > 100) {
  throw new Error('Pattern too long');
}

ReDoS Prevention

Understanding ReDoS

// ❌ Vulnerable: Nested quantifiers
/(a+)+b/.test('aaaaaaaaaaaaaab'); // Exponential backtracking

// ✅ Safe: Restructure
/a+b/.test('aaaaaaaaaaaaaab'); // Linear time

Safe Alternatives

  1. Pre-defined Patterns

    const SAFE_PATTERNS = {
      email: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
      uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
    };
  2. Input Escaping

    function escapeRegex(string: string): string {
      return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    }
  3. Safe Libraries

    import safeRegex from 'safe-regex';
    if (safeRegex(userPattern)) {
      new RegExp(userPattern);
    }

Common ReDoS Patterns

PatternRiskExampleSafe Alternative
(a+)+Critical/(a+)+b//a+b/
(a*)*Critical/(a*)*b//a*b/
(a|b)*HighComplex alternationsSimplify
.*MediumGreedy matchingBe specific

Migration Guide

Phase 1: Discovery

{
  rules: {
    'secure-coding/detect-non-literal-regexp': 'warn'
  }
}

Phase 2: Replace Dynamic Construction

// Replace dynamic RegExp
new RegExp(userInput) → PATTERNS[userChoice]

// Add escaping for necessary dynamic patterns
new RegExp(escapeRegex(userInput))

Phase 3: Test Performance

// Test with potentially malicious inputs
const maliciousInputs = [
  'a'.repeat(10000) + 'b', // Triggers backtracking
  '(a+)+b'.repeat(1000), // Complex patterns
  '[a-z]*'.repeat(100), // Nested quantifiers
];

Comparison with Alternatives

Featuredetect-non-literal-regexpeslint-plugin-securityeslint-plugin-sonarjs
ReDoS Detection✅ Yes⚠️ Limited⚠️ Limited
CWE Reference✅ CWE-400 included⚠️ Limited⚠️ Limited
LLM-Optimized✅ Yes❌ No❌ No
ESLint MCP✅ Optimized❌ No❌ No
Fix Suggestions✅ Detailed⚠️ Basic⚠️ Basic

Known False Negatives

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

Values from Variables

Why: Values stored in variables are not traced.

// ❌ NOT DETECTED - Value from variable
const value = userInput;
dangerousOperation(value);

Mitigation: Validate all user inputs.

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

On this page