MongoDBRules
no-unsafe-regex-query
Detects user input in MongoDB `$regex` operators that could cause ReDoS (Regular Expression Denial of Service) or information disclosure.
Keywords: ReDoS, CWE-400, MongoDB, $regex, regular expression, denial of service
Detects user input in MongoDB $regex operators that could cause ReDoS (Regular Expression Denial of Service) or information disclosure.
⚠️ This rule errors by default in the recommended config.
Quick Summary
| Aspect | Details |
|---|---|
| CWE Reference | CWE-400 (Resource Exhaustion) |
| OWASP | A03:2021 - Injection |
| Severity | High (CVSS: 7.5) |
| Category | Security |
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 |
Rule Details
User input in $regex operators is dangerous because:
- ReDoS attacks: Crafted regex patterns can cause exponential backtracking
- Information disclosure: Regex can be used to probe for data patterns
- Injection: Special regex characters can alter query behavior
Attack Example
// Attacker sends: "(a+)+$"
// This causes exponential backtracking on strings like "aaaaaaaaaa!"
db.users.find({ email: { $regex: userInput } });❌ Incorrect
// User input directly in $regex
User.find({ name: { $regex: req.query.search } });
// User input as regex pattern
User.find({ email: { $regex: new RegExp(userInput) } });
// User input with $options
User.find({ name: { $regex: req.body.pattern, $options: 'i' } });✅ Correct
// Escape special regex characters
import escapeRegex from 'escape-string-regexp';
User.find({ name: { $regex: escapeRegex(req.query.search), $options: 'i' } });
// Use $text search instead (indexed, safer)
User.find({ $text: { $search: req.query.search } });
// Anchor and limit pattern
const safePattern = `^${escapeRegex(req.query.search).slice(0, 50)}`;
User.find({ name: { $regex: safePattern } });
// Use MongoDB text index
db.users.createIndex({ name: 'text' });
User.find({ $text: { $search: userInput } });Known False Negatives
Sanitized Input
// ❌ NOT DETECTED - but may still be vulnerable
const sanitized = userInput.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
User.find({ name: { $regex: sanitized } });When Not To Use It
- When using escape-string-regexp or similar libraries consistently
- When regex patterns are from trusted source (internal config)