Unicode Normalization in Adonisjs with Firestore
Unicode Normalization in Adonisjs with Firestore — how this specific combination creates or exposes the vulnerability
Unicode normalization inconsistencies arise when an application normalizes user input in one form (e.g., NFC) but a backend service such as Firestore stores or indexes strings in another canonical form. AdonisJS, a Node.js web framework, does not enforce a default normalization form for strings, so developers must explicitly normalize inputs. Firestore, depending on its backend collation and indexing implementation, may store and compare strings in a specific normalization state. If an attacker supplies a visually identical string that normalizes differently, they can bypass access controls or matching logic that relies on string equality.
For example, consider the character é, which can be represented as a single code point U+00E9 or as a combination of U+0065 U+0301 (e + combining acute). If AdonisJS compares a user-supplied identifier directly to a Firestore document ID or field without normalizing both sides to the same form, the comparison may fail or match unexpectedly. This can enable IDOR-like conditions where an attacker iterates over visually equivalent strings to access records they should not see. In security testing, such inconsistencies are surfaced by checks that validate canonicalization of identifiers and inputs across the stack.
In the context of the 12 security checks run by middleBrick, Unicode normalization is relevant to Input Validation and Property Authorization. A normalized mismatch can be leveraged for BOLA/IDOR when document IDs or resource handles are derived from user-controlled strings. It can also affect Data Exposure when logs or error messages reflect unnormalized inputs, potentially leaking variant forms that aid reconnaissance. Because Firestore may normalize data differently depending on indexing and collation settings, the framework-to-database boundary becomes a critical point to test.
middleBrick can detect these classes of issues by cross-referencing OpenAPI specifications with runtime behavior. If your API accepts identifiers or search parameters that involve international text, ensure normalization is applied consistently before any Firestore lookup. For LLM-related endpoints, note that middleBrick uniquely includes checks for system prompt leakage and prompt injection, which are orthogonal but complementary to input integrity concerns like normalization.
Firestore-Specific Remediation in Adonisjs — concrete code fixes
To mitigate Unicode normalization issues when using AdonisJS with Firestore, enforce a single normalization form at the boundary where data enters your application and before any Firestore operation. Use a well-maintained Unicode library to normalize strings consistently, and apply the same normalization to any string used in document IDs, field values, or query constraints.
Below is a realistic example using AdonisJS with the Firestore Node.js client. It shows normalization before creating or retrieving a document, ensuring that comparisons and lookups are performed on a canonical form.
import { normalize, unescape } from 'unescape';
// A robust normalization helper using the Unicode Normalization Form KC (NFKC)
// which is appropriate for most security-sensitive use cases.
const normalizeInput = (value: string): string => {
return value.normalize('NFKC');
};
// Firestore initialization (assumes application default credentials)
import { initializeApp } from 'firebase-admin/app';
import { getFirestore, doc, getDoc, setDoc } from 'firebase-admin/firestore';
initializeApp();
const db = getFirestore();
export async function upsertUserProfile(userId: string, inputName: string) {
// Normalize both the identifier and any user-supplied display fields
const safeUserId = normalizeInput(userId);
const normalizedName = normalizeInput(inputName);
const userRef = doc(db, 'profiles', safeUserId);
await setDoc(userRef, {
name: normalizedName,
normalizedId: safeUserId,
updatedAt: new Date().toISOString(),
});
const snap = await getDoc(userRef);
if (snap.exists()) {
return snap.data();
}
return null;
}
export async function getUserProfile(userId: string) {
const safeUserId = normalizeInput(userId);
const userRef = doc(db, 'profiles', safeUserId);
const snap = await getDoc(userRef);
if (snap.exists()) {
return snap.data();
}
return null;
}
In this example, both the document ID and the name field are normalized with NFKC before being used in Firestore operations. This ensures that a client supplying é as either U+00E9 or U+0065 U+0301 will always map to the same document and stored representation. For queries that involve user-controlled strings, normalize the search term in the same way before passing it to Firestore.
When integrating with middleBrick’s CLI or Web Dashboard, you can include these normalization steps and re-scan to verify that findings related to Input Validation and Property Authorization are resolved. The Pro plan’s continuous monitoring can help ensure that future changes do not reintroduce inconsistent normalization across endpoints that interact with Firestore. Similarly, the GitHub Action can be configured to fail builds if risk scores degrade, providing a safety net for string handling in CI/CD.
For teams using the MCP Server, you can scan APIs directly from your AI coding assistant to surface normalization concerns during development, complementing Firestore-specific fixes with contextual guidance.