Regex Dos in Adonisjs with Firestore
Regex Dos in Adonisjs with Firestore — how this specific combination creates or exposes the vulnerability
AdonisJS, a Node.js web framework, often uses route parameters and query strings to drive database operations. When these inputs are passed into Firestore queries without normalization or strict validation, complex regular expressions and unbounded pattern matching can cause catastrophic backtracking. This occurs because JavaScript regex engines attempt all possible permutations of a pattern when processing nested quantifiers on untrusted input, leading to exponential CPU consumption.
In the context of Firestore, developers sometimes construct dynamic query filters using string interpolation with user-controlled values. For example, concatenating a route parameter directly into a Firestore where clause field name or value can introduce regular expressions inadvertently if the code uses methods like String.prototype.match or RegExp to sanitize or parse input before issuing the query. Even when Firestore itself does not evaluate regex, the surrounding AdonisJS application layer can become the bottleneck as it processes and transforms incoming payloads.
Consider an endpoint that accepts a filterTag parameter intended to match predefined tag patterns. A naive implementation might use a permissive regex to validate allowed characters, such as /^[a-zA-Z0-9_-]+$/, but if the regex is applied repeatedly or combined with recursive logic on large inputs, the engine can enter a state of excessive backtracking. This becomes more pronounced when the input includes overlapping character classes or ambiguous quantifiers like * and + without atomic grouping. Although Firestore queries execute efficiently, the CPU time spent in the AdonisJS middleware before the request reaches Firestore can degrade service responsiveness significantly.
An attacker can exploit this by sending specially crafted strings designed to maximize the number of regex evaluation paths. For instance, a payload containing repeated characters such as a*a* or patterns with nested quantifiers can force the runtime to explore exponentially many matching attempts. Because the scan is unauthenticated, an attacker does not need valid credentials to trigger this behavior, making it a viable vector for denial-of-service within the security risk score reported by middleBrick under the Input Validation and Rate Limiting checks.
Real-world impact includes increased latency and resource exhaustion on the application server, which may cascade into higher latencies for legitimate Firestore operations. Since Firestore usage patterns often involve high-frequency reads and writes, any bottleneck introduced upstream can affect overall throughput. middleBrick identifies such risks by correlating untrusted input handling with Firestore query construction, highlighting insecure regex usage in findings mapped to the OWASP API Top 10 and categorized under Input Validation.
Firestore-Specific Remediation in Adonisjs — concrete code fixes
Remediation focuses on removing regex-based validation for Firestore-bound inputs and enforcing strict allowlists at the framework level. Instead of relying on complex patterns, use deterministic checks that validate length, character set, and structure without backtracking risks. Always treat route parameters and query strings as untrusted and sanitize them before using them in Firestore queries.
Below is a secure pattern for handling a document identifier in an AdonisJS route that targets a Firestore collection. The example avoids regular expressions entirely and uses a combination of length checks, character whitelisting, and explicit error handling.
import { schema, rules } from '@ioc:Adonis/Core/Validator'
import { Firestore, doc, getDoc } from 'firebase/firestore'
// Define a strict schema for the incoming parameter
const documentIdSchema = schema.create({
docId: schema.string({}, [
rules.minLength(12),
rules.maxLength(12),
rules.regex(new RegExp('^[a-zA-Z0-9\-_]+$')), // Only if regex is unavoidable; prefer custom check below
])
})
// Alternatively, use a custom validator without regex:
async function validateDocId(value: string): boolean {
if (value.length !== 12) return false
for (let i = 0; i < value.length; i++) {
const c = value.charCodeAt(i)
const isAlphanumeric = (c >= 48 && c <= 57) || // 0-9
(c >= 65 && c <= 90) || // A-Z
(c >= 97 && c <= 122) // a-z
if (!isAlphanumeric) return false
}
return true
}
// In your route handler:
router.get('/documents/:docId', async ({ params }) => {
const isValid = await validateDocId(params.docId)
if (!isValid) {
return Response.badRequest({ error: 'Invalid document identifier' })
}
const db = new Firestore()
const docRef = doc(db, 'userData', params.docId)
const snapshot = await getDoc(docRef)
if (!snapshot.exists()) {
return Response.notFound({ error: 'Document not found' })
}
return Response.ok(snapshot.data())
})
For query parameters that influence Firestore field filters, avoid string interpolation for field names. Instead, use a hardcoded map of allowed fields to prevent injection through property names. This approach neutralizes both regex-based DoS and Firestore field manipulation risks.
const allowedFields = {
status: 'status',
createdAt: 'createdAt',
priority: 'priority'
}
router.get('/tasks', async ({ request }) => {
const field = request.qs().field
const direction = request.qs().direction as 'asc' | 'desc' || 'asc'
if (!allowedFields[field]) {
return Response.badRequest({ error: 'Invalid filter field' })
}
const db = new Firestore()
const snapshot = await getDocs(
query(collection(db, 'tasks'), orderBy(allowedFields[field], direction))
)
const results = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }))
return Response.ok(results)
})
Additionally, apply rate limiting at the AdonisJS middleware layer to mitigate repeated high-volume requests that could trigger regex evaluation storms. Combine this with input normalization to lowercase or trimmed values before validation to reduce edge cases. middleBrick’s findings under BFLA/Privilege Escalation and Input Validation highlight the importance of these controls in preventing abuse paths that do not directly modify data but degrade service integrity.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |