detect-non-literal-regexp
ESLint security rule documentation for detect-non-literal-regexp
📡 Live from GitHub — This documentation is fetched directly from detect-non-literal-regexp.md and cached for 6 hours.
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
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
| Aspect | Details |
|---|---|
| CWE Reference | CWE-400 (ReDoS - Regular Expression Denial of Service) |
| Severity | High (performance/security issue) |
| Auto-Fix | ⚠️ Suggests fixes (manual application) |
| Category | Security |
| ESLint MCP | ✅ Optimized for ESLint MCP integration |
| Best For | Applications 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
| Component | Purpose | Example |
|---|---|---|
| Risk Standards | Security benchmarks | CWE-400 OWASP:A06 CVSS:7.5 |
| Issue Description | Specific vulnerability | Uncontrolled Resource Consumption (ReDoS) detected |
| Severity & Compliance | Impact assessment | HIGH |
| Fix Instruction | Actionable remediation | Follow the remediation steps below |
| Technical Truth | Official reference | OWASP Top 10 |
Configuration
| Option | Type | Default | Description |
|---|---|---|---|
allowLiterals | boolean | false | Allow literal string regex patterns |
additionalPatterns | string[] | [] | Additional RegExp creation patterns |
maxPatternLength | number | 100 | Maximum 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 timeSafe Alternatives
-
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, }; -
Input Escaping
function escapeRegex(string: string): string { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } -
Safe Libraries
import safeRegex from 'safe-regex'; if (safeRegex(userPattern)) { new RegExp(userPattern); }
Common ReDoS Patterns
| Pattern | Risk | Example | Safe Alternative |
|---|---|---|---|
(a+)+ | Critical | /(a+)+b/ | /a+b/ |
(a*)* | Critical | /(a*)*b/ | /a*b/ |
(a|b)* | High | Complex alternations | Simplify |
.* | Medium | Greedy matching | Be 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
| Feature | detect-non-literal-regexp | eslint-plugin-security | eslint-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 |
Related Rules
detect-eval-with-expression- Prevents code injection via eval()detect-child-process- Prevents command injectiondetect-non-literal-fs-filename- Prevents path traversaldetect-object-injection- Prevents prototype pollution
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 internallyMitigation: 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
- OWASP ReDoS Attacks - ReDoS attack guide
- Safe Regex Library - Safe regex patterns
- CWE-400: Uncontrolled Resource Consumption - Official CWE entry
- ESLint MCP Setup - Enable AI assistant integration
Edit this page on GitHub →