Description
Overview
This document details the analysis and fixes for Regular Expression Denial of Service (ReDoS) vulnerabilities found in the Meteor project's meteor-babel package.
Vulnerabilities Identified
Vulnerability 1: Whitespace Pattern
Location: npm-packages/meteor-babel/test/mocha.js:5949
Original Pattern: /\s+\}$/
Context: .replace(/\s+\}$/, '');
Attack Vectors:
""+" ".repeat(100000)+"◎"""+" ".repeat(100000)+"!"
Problem: The pattern /\s+\}$/ causes catastrophic backtracking when input contains many whitespace characters followed by a non-} character at the end.
Vulnerability 2: Number Pattern
Location: npm-packages/meteor-babel/test/mocha.js:6005
Original Pattern: /(\d+\.\d+)/gm
Context: .replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>')
Attack Vectors:
""+"0".repeat(100000)+"."""+"1".repeat(100000)+"◎"
Problem: The pattern /(\d+\.\d+)/gm causes excessive backtracking when input contains many digits followed by a dot but no digits after.
Fixes Using Negative Lookahead
Fix 1: Whitespace Pattern
// Original (vulnerable)
.replace(/\s+\}$/, '');
// Fixed using positive lookahead
.replace(/\s+(?=\}$)/, '');
Explanation: The positive lookahead (?=\}$) ensures we only match whitespace that is immediately followed by } at the end, preventing backtracking on non-matching endings.
Fix 2: Number Pattern
// Original (vulnerable)
.replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>')
// Fixed using negative lookahead
.replace(/(\d+\.\d+)(?!\d)/gm, '<span class="number">$1</span>')
Explanation: The negative lookahead (?!\d) ensures we don't match if there's another digit after the decimal number, making the pattern more precise and preventing backtracking.
Security Impact
- Severity: Medium
- Attack Vector: Malicious input strings
- Impact: CPU exhaustion, application freeze, denial of service
- Affected Component: Test files (potential risk if patterns used in production)
Testing the Fixes
Before Fix (Vulnerable)
// This will cause high CPU usage
const maliciousInput = " ".repeat(100000) + "◎";
const result = maliciousInput.replace(/\s+\}$/, '');
After Fix (Safe)
// This executes quickly
const maliciousInput = " ".repeat(100000) + "◎";
const result = maliciousInput.replace(/\s+(?=\}$)/, '');
Recommendations
- Immediate: Apply the proposed fixes to prevent ReDoS attacks
- Long-term: Implement regex security scanning in CI/CD pipeline
- Best Practice: Use tools like
safe-regexto detect vulnerable patterns - Code Review: Include regex security checks in code review process