Skip to main content
ESLint Interlace
Plugin: secure-codingRules

detect-non-literal-regexp

Detects RegExp(variable), which might allow an attacker to DOS your server with a long-running regular expression

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

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

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

Value & investment case

Why this rule pays for itself. Framework: cicd-impact/philosophy.md.

DimensionValue
CWECWE-400 — Uncontrolled Resource Consumption (ReDoS)
Feedback-loop tierEditor / pre-commit (sub-second) — cheapest layer per the feedback-loop hierarchy
Defensive-layer leverage~10× cheaper than unit-test · ~1,000× cheaper than production rollback · 10,000+× cheaper than customer disclosure (cost-ratio anchors)
Niche relevanceCritical: fintech, infra/devtools (downstream consumers of vulnerable libraries) · High: B2B SaaS, cybersecurity · Medium: B2C, marketplaces · Low: gaming
Investor-frame impactA single ReDoS in a fintech / B2B SaaS production system = an outage event with regulatory and ARR-at-risk exposure ($50K–$500K typical incident cost). One catch at lint-time costs ~$0 of CI minutes. See Acme Pay walk-through.

Read also: philosophy.md §investor-frame · niche-presets.json · analyzer-evaluation-framework.md

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

const result = myFunction(pattern);

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