Out Of Bounds Write in Adonisjs with Firestore
Out Of Bounds Write in Adonisjs with Firestore — how this specific combination creates or exposes the vulnerability
An Out Of Bounds Write occurs when application logic allows data to be written outside the intended storage range or structure. When using AdonisJS with Google Cloud Firestore, this typically manifests through unchecked user input used as document IDs, array indices, or map keys, combined with Firestore’s permission and data modeling behaviors.
AdonisJS does not inherently validate identifiers before they are used in Firestore operations. If a controller accepts an ID or index from request parameters and directly passes it to Firestore without validation, an attacker can supply values that write to unexpected document paths or overwrite system-critical fields. For example, an ID like ../../../admin/settings or a numeric index beyond expected array bounds can shift writes into parent collections or unintended documents, especially when rules permit write access at broader scopes.
Firestore’s data model amplifies the impact. Because documents can nest maps and arrays, an out-of-bounds index written into an array field can corrupt adjacent entries or create new elements in ways that bypass application-level assumptions. In AdonisJS, if array manipulation logic assumes a fixed size or validated indices, an injected index can extend arrays beyond intended limits or overwrite existing entries. This may lead to privilege escalation if roles or permissions are stored in arrays and an attacker forces writes into administrative slots.
Additionally, Firestore security rules that rely on resource-based checks (e.g., allowing writes if the document exists) can be abused when an attacker determines valid document paths through enumeration or error leakage. AdonisJS error handling might inadvertently expose path details in stack traces or validation messages, helping an attacker refine out-of-bounds targets. The framework’s request lifecycle, if not explicitly sanitizing parameters before Firestore calls, provides no boundary checks on numeric ranges or path validity, leaving the API surface open to manipulation.
Real-world attack patterns include overwriting configuration documents, injecting malicious arrays into shared resources, or manipulating counters and state arrays. These map to OWASP API Top 10 categories such as Broken Object Level Authorization (BOLA) and Excessive Data Exposure. Because Firestore operations are asynchronous and batched, an out-of-bounds write might not immediately fail, allowing an attacker to persist invalid state that later causes logic failures or data integrity issues.
Firestore-Specific Remediation in Adonisjs — concrete code fixes
Remediation focuses on strict input validation, path normalization, and defensive Firestore usage within AdonisJS controllers and services. Always treat user-supplied identifiers as untrusted and sanitize them before using them in document references or array operations.
Use a validation schema to enforce expected formats for IDs and indices. For document IDs, restrict to alphanumeric characters and reject path-like sequences. For array indices, ensure they are integers within a valid range before performing writes.
import { schema } from '@ioc:Adonis/Core/Validator'
export const documentValidator = schema.create({
id: schema.string({}, [rules.alpha()]),
index: schema.number([rules.range(0, 100)]),
data: schema.object({})
})
export async function updateDocument({ request, firestore }) {
const payload = await request.validate({ schema: documentValidator })
const docRef = firestore.collection('records').doc(payload.id)
await docRef.update({ data: payload.data })
}
For array operations, avoid direct index writes based on user input. Instead, use Firestore’s array union or transformation functions with controlled values. If an index is required, validate it against the current array length retrieved from the document.
import { DocumentReference } from '@google-cloud/firestore'
async function safeArrayWrite(docRef: DocumentReference, index: number, value: any) {
const snapshot = await docRef.get()
const currentArray = snapshot.get('items') || []
if (index < 0 || index > currentArray.length) {
throw new Error('Index out of bounds')
}
// Replace element at validated index
const updates: any = {}
updates[`items.${index}`] = value
await docRef.update(updates)
}
Normalize paths to prevent directory traversal in document references. Reject IDs containing .. or leading slashes, and use Firestore’s built-in reference methods rather than string concatenation.
function normalizeDocId(input: string): string {
if (input.includes('..') || input.startsWith('/')) {
throw new Error('Invalid document ID')
}
return input.trim()
}
const safeId = normalizeDocId(userSuppliedId)
const docRef = firestore.collection('data').doc(safeId)
Apply principle of least privilege in Firestore security rules and avoid broad write permissions at collection group levels. Combine rule checks with AdonisJS validation so that both layers reject suspicious paths and indices.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /records/{docId} {
allow write: if docId.matches(/^[a-zA-Z0-9_-]{1,100}$/)
&& request.resource.data.keys().hasAll(['data'])
&& request.resource.data.data is string;
}
}
}
Log and monitor write attempts that include unusual path patterns or out-of-range indices. Use these logs to refine validation rules and detect reconnaissance attempts targeting boundary conditions.