Injection Flaws in Loopback with Firestore
Injection Flaws in Loopback with Firestore — how this specific combination creates or exposes the vulnerability
Loopback is a widely used Node.js framework for building APIs, and it often integrates with Google Cloud Firestore as a backend datastore. Injection flaws in this combination arise when developer code interpolates untrusted input into Firestore queries, command construction, or document paths without proper validation or sanitization. Because Firestore queries are expressed as JavaScript objects and method chains, dynamically building query constraints from user-controlled data can lead to unintended query behavior or exposure of unintended document fields.
For example, using user-supplied field names or values directly in where() clauses or document lookups can allow an attacker to probe data outside intended access boundaries. In a black-box scan, middleBrick tests inputs that reference document IDs, collection names, and field values to detect whether crafted payloads can bypass intended filters or enumeration rules.
Specific risk patterns include:
- Dynamic construction of document references using concatenated strings, which may allow directory traversal across collections if an attacker supplies path segments such as
../../other-collection/docId. - Unsanitized input to query filters where keys or operators are derived from request parameters, potentially enabling enumeration of indexed fields or bypassing intended scoping logic.
- Use of Firestore JavaScript SDK methods with raw user input in callbacks or
orderByclauses, which can change sort behavior or expose sensitive ordering of results.
During an unauthenticated scan, middleBrick submits probe values designed to test whether injected constraints alter the set or sensitivity of returned documents. For instance, a probe may include special characters, boolean expressions, or reserved field names to evaluate whether the implementation safely handles or rejects malformed input. The scanner also checks whether error messages inadvertently disclose collection structures or index configurations that could aid an attacker.
Because Firestore rules are not evaluated by middleBrick, findings related to injection focus on the API layer — specifically how the Loopback application builds and executes queries. Even when Firestore rules are strict, a vulnerable query method in the Loopback controller can expose data through overly permissive reads or unsafe document lookups. The scanner correlates these runtime behaviors with the OpenAPI specification to determine whether declared parameters and expected request shapes align with actual query construction.
Firestore-Specific Remediation in Loopback — concrete code fixes
Remediation centers on strict input validation, avoiding dynamic query assembly, and using parameterized patterns. Do not concatenate user input into document paths or query constraints. Instead, validate allowed values against a whitelist and use Firestore SDK methods with fixed field names and safe operators.
Example: Unsafe dynamic query
// UNSAFE: directly using request query parameters in where clause
const field = req.query.field; // attacker-controlled
const value = req.query.value; // attacker-controlled
const snapshot = await db.collection('records').where(field, '==', value).get();
Example: Safe parameterized query
// SAFE: map known fields to canonical Firestore field names
const allowedFields = new Set(['email', 'status', 'createdAt']);
const field = req.query.field;
const value = req.query.value;
if (!allowedFields.has(field)) {
throw new Error('Invalid query field');
}
const snapshot = await db.collection('records').where(field, '==', value).get();
Example: Safe document lookup with ID validation
// SAFE: validate document ID format before lookup
const docId = req.params.id;
const idPattern = /^[a-zA-Z0-9_-]{1,100}$/;
if (!idPattern.test(docId)) {
throw new Error('Invalid document identifier');
}
const docRef = db.collection('profiles').doc(docId);
const doc = await docRef.get();
if (!doc.exists) {
// handle not found without revealing internals
}
Example: Avoiding injection in collection or field names
// SAFE: never use raw input to determine collection names
const collectionName = 'profiles'; // hardcoded or selected from a strict enum
const sortBy = 'email'; // validated field name
let query = db.collection(collectionName);
query = query.orderBy(sortBy, 'asc');
const results = await query.limit(10).get();
Additional practices include using Firestore’s built-in data validation rules on the server side, enabling robust error handling that does not expose stack traces or internal identifiers, and structuring data models to minimize the need for deeply dynamic queries. middleBrick’s scans can be used in CI/CD via the GitHub Action to ensure that new commits do not reintroduce insecure query patterns by failing the build if risk thresholds are exceeded.
When remediation is applied, developers should re-scan the endpoint through the middleBrick Web Dashboard or CLI to confirm that the injection surface has been reduced and that findings are resolved or properly mitigated.