HIGH regex dosadonisjsfirestore

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 IDNameSeverity
CWE-20Improper Input Validation HIGH
CWE-22Path Traversal HIGH
CWE-74Injection CRITICAL
CWE-77Command Injection CRITICAL
CWE-78OS Command Injection CRITICAL
CWE-79Cross-site Scripting (XSS) HIGH
CWE-89SQL Injection CRITICAL
CWE-90LDAP Injection HIGH
CWE-91XML Injection HIGH
CWE-94Code Injection CRITICAL

Frequently Asked Questions

Why does using regex for Firestore field names in AdonisJS increase risk?
Using regex on user input to construct Firestore field names can cause exponential backtracking if patterns contain nested quantifiers. Since Firestore queries depend on exact field names, invalid names are rejected only after the regex processing stage, wasting CPU cycles in AdonisJS before the request reaches Firestore.
Can middleBrick detect regex DoS vulnerabilities in API endpoints that interact with Firestore?
Yes. middleBrick runs parallel security checks including Input Validation and Rate Limiting, which identify unsafe pattern matching and unbounded processing of untrusted input. Findings include severity, categorization under relevant frameworks, and remediation guidance without implying automatic fixes.