Hallucination Attacks in Adonisjs with Mongodb
Hallucination Attacks in Adonisjs with Mongodb — how this specific combination creates or exposes the vulnerability
Hallucination attacks in an AdonisJS application using MongoDB occur when an attacker manipulates inputs or query construction to produce misleading, fabricated, or overly broad responses from the database. Because AdonisJS often builds queries programmatically and MongoDB supports rich query expressions and aggregation pipelines, inconsistencies in validation and sanitization can allow an attacker to influence which documents are returned or how they are projected, effectively causing the application to hallucinate data that does not exist or to reveal unintended data patterns.
In AdonisJS, developers commonly use the Lucid ORM with MongoDB through a community driver or custom query builder integrations. If user-controlled parameters are directly embedded into query filters, sort orders, or aggregation stages without strict schema and type validation, an attacker can inject values that change the semantics of queries. For example, supplying a malformed $where or an unexpected $expr clause can cause the server to evaluate expressions that return true for attacker-influenced inputs, resulting in documents being returned that should be hidden. Similarly, projection manipulation via $project or $addFields in an aggregation can expose fields that are normally restricted, leading to data exposure hallucinations where the application appears to return correct data but actually leaks sensitive fields.
The risk is compounded when the application dynamically constructs pipelines based on client request parameters, such as filtering by tenant ID or user roles. Without rigorously enforcing tenant isolation and role checks at the database query level, an attacker can supply parameters that bypass intended filters. For instance, an attacker may inject a $or condition that always evaluates to true, causing the query to return documents across tenants or roles. Because the application may cache or log these responses, the hallucinated data can persist in downstream systems, increasing the blast radius. These patterns map closely to OWASP API Top 10 #1 Broken Object Level Authorization (BOLA) and #7 Data Exposure, and can violate compliance mappings such as PCI-DSS and SOC2 if sensitive data is inappropriately returned.
AdonisJS-specific concerns include improper use of dynamic query building and reliance on loosely typed request payloads. If route handlers directly pass request queries into MongoDB aggregation stages without schema validation, an attacker can exploit type coercion to alter logical conditions. Real-world examples include using strings where ObjectIds are expected, causing implicit casts that bypass intended document matching. The LLM/AI Security checks in middleBrick are designed to detect such unsafe consumption patterns and insecure API surface areas, highlighting where hallucination attacks may arise from unchecked input influence on database behavior.
To understand the practical impact, consider a search endpoint that builds a MongoDB aggregation based on user-supplied text and filters. Without strict validation, an attacker can inject pipeline stages or modify match conditions to return arbitrary documents. middleBrick’s 12 security checks, including Input Validation, Property Authorization, and Unsafe Consumption, are aligned with these risks and provide prioritized findings with severity and remediation guidance to help developers identify and correct such hallucination attack vectors before deployment.
Mongodb-Specific Remediation in Adonisjs — concrete code fixes
Remediation focuses on strict input validation, schema enforcement, and defensive query construction when using MongoDB with AdonisJS. Always validate and sanitize incoming parameters against a known schema, use parameterized queries, and avoid dynamically injecting user input into aggregation pipelines or $where clauses. The following examples illustrate secure patterns.
1. Validate and sanitize filter inputs
Use a validation schema to ensure fields match expected types and values. Reject unexpected keys to prevent injection of malicious operators.
import { schema } from '@ioc:AdonisJS/Core/Validator'
const filterSchema = schema.create({
tenantId: schema.string({ trim: true, validate: { uuid: true } }),
status: schema.enum(['active', 'inactive', 'pending']),
search: schema.string.optional({ trim: true }),
})
export async function validateFilter(ctx) {
const payload = await ctx.validate({
schema: filterSchema,
})
return payload
}
2. Use parameterized queries with ObjectId
Ensure IDs are explicitly converted and validated before inclusion in queries. Do not rely on implicit casting from strings.
import { ObjectId } from 'mongodb'
import User from 'App/Models/User'
export async function showUser(ctx) {
const { id } = ctx.params
if (!ObjectId.isValid(id)) {
return ctx.response.badRequest({ error: 'Invalid user ID' })
}
const user = await User.query()
.where('_id', new ObjectId(id))
.preload('posts')
.first()
return ctx.response.ok(user)
}
3. Build aggregation pipelines safely
Construct pipelines programmatically without directly concatenating user input. Use constants for allowed stages and whitelist filter fields.
import { HttpContextContract } from '@ioc:AdonisJS/Core/HttpContext'
import { ObjectId } from 'mongodb'
export async function searchItems(ctx: HttpContextContract) {
const validated = await ctx.validate({
schema: schema.create({
tenantId: schema.string.optional({ validate: { uuid: true } }),
category: schema.string.optional(),
stages: schema.array.optional().describing({ type: 'allowed stages' }),
}),
})
const pipeline = []
if (validated.tenantId) {
pipeline.push({ $match: { tenantId: new ObjectId(validated.tenantId) } })
}
if (validated.category) {
pipeline.push({ $match: { category: validated.category } })
}
// Only allow safe, predefined additional stages
const allowedStages = { $project: 1, $sort: 1, $limit: 1 }
if (validated.stages) {
for (const stage of validated.stages) {
if (allowedStages[stage.type]) {
pipeline.push({ [stage.type]: stage.payload })
}
}
}
const results = await Item.aggregate(pipeline)
return ctx.response.ok(results)
}
4. Enforce field-level authorization in projections
Explicitly define which fields are allowed for the requesting context to prevent over-fetching and hallucination of restricted data.
export function allowedFieldsForRole(ctx, role) {
const base = ['_id', 'name', 'description', 'createdAt']
if (role === 'admin') {
return base.concat(['internalNotes', 'auditLog'])
}
return base
}
export async function listItems(ctx) {
const { role } = ctx.auth
const fields = allowedFieldsForRole(ctx, role)
const projection = fields.reduce((acc, f) => ({ ...acc, [f]: 1 }), {})
const items = await Item.query()
.where('tenantId', ctx.auth.tenantId)
.project(projection)
.exec()
return ctx.response.ok(items)
}
5. Avoid $where and dynamic JavaScript evaluation
Never use $where or similar server-side evaluation with user-controlled values. If complex filtering is required, map inputs to known safe operators.
// Unsafe — avoid
// db.items.find({ $where: `this.status === "${userStatus}"` })
// Safe alternative
const statusMap = { active: 'active', inactive: 'inactive' }
const safeStatus = statusMap[userStatus]
if (!safeStatus) {
return ctx.response.badRequest({ error: 'Invalid status' })
}
const items = await Item.find({ status: safeStatus })
These patterns reduce the attack surface for hallucination attacks by ensuring that database interactions are predictable, constrained, and auditable. middleBrick’s checks for Input Validation, Property Authorization, and Unsafe Consumption help identify remaining gaps, and its integration options — including the CLI (middlebrick scan <url>), GitHub Action for CI/CD gates, and MCP Server for IDE integration — support continuous monitoring to keep these protections effective over time.
Related CWEs: llmSecurity
| CWE ID | Name | Severity |
|---|---|---|
| CWE-754 | Improper Check for Unusual or Exceptional Conditions | MEDIUM |