Hallucination Attacks in Actix with Mongodb
Hallucination Attacks in Actix with Mongodb — how this specific combination creates or exposes the vulnerability
A hallucination attack in the context of an Actix web service backed by MongoDB occurs when an attacker manipulates inputs or API behavior to produce fabricated or misleading database responses. This can expose sensitive data, bypass authorization logic, or cause the application to act on incorrect assumptions about the state of data.
Actix is a high-performance Rust framework where handlers often deserialize incoming requests into strongly typed structures and build MongoDB queries dynamically. If user-controlled fields are used to construct query filters, projection shapes, or aggregation pipelines without strict validation, an attacker can supply values that cause the driver to interpret the request in unintended ways. For example, injection into a doc! { "status": user_input } document can change matching semantics or unintentionally expose fields if projection keys are derived from user input.
With MongoDB, certain operators can trigger server-side behaviors that amplify hallucination risks. If an attacker influences $where, $function, or aggregation expressions, they may coerce the server to evaluate JavaScript or reference fields that should remain private. In Actix, this often happens when deserialization rules are too permissive or when dynamic BSON documents are constructed by concatenating user-provided strings. The combination of Actix’s asynchronous request handling and MongoDB’s flexible document model means that unchecked inputs can lead to queries that return incorrect documents, fabricated field values, or metadata that should not be disclosed.
Another vector is schema inference on the client side. If an Actix handler uses generic types or loosely typed BSON deserialization (e.g., bson::Document without strict validation), an attacker can send carefully crafted payloads that cause the application to hallucinate fields during deserialization. These hallucinated fields may then be used in business logic such as authorization checks or response assembly, leading to information leakage or privilege escalation. Because MongoDB returns partial matches and can include extra metadata in responses (e.g., via explain or cursor information), an attacker can probe the handler to infer internal query patterns and observe how hallucinated data affects server behavior.
Middleware and logging in Actix can unintentionally amplify these risks. If request payloads or derived MongoDB queries are logged without sanitization, hallucinated inputs and their effects may be persisted, aiding further reconnaissance. Additionally, error messages from the MongoDB driver embedded in Actix responses can reveal internal field names or operator usage, giving attackers hints on how to refine injection techniques to deepen the hallucination impact.
Mongodb-Specific Remediation in Actix — concrete code fixes
Remediation centers on strict input validation, schema enforcement, and avoiding dynamic construction of MongoDB documents from untrusted data. Prefer strongly typed structures and explicit query definitions over runtime-built BSON.
1. Use strongly typed structs and validate inputs
Define request DTOs with serde and validate required fields before building queries. This prevents unexpected keys from altering query semantics.
use actix_web::{post, web, HttpResponse};
use serde::Deserialize;
use mongodb::{bson::doc, Collection};
#[derive(Deserialize)]
struct StatusQuery {
status: String,
#[serde(default)]
include_metadata: bool,
}
#[post("/items")]
async fn list_items(
body: web::Json,
items_coll: web::Data>,
) -> HttpResponse {
let filter = doc! { "status": &body.status };
let find_options = if body.include_metadata {
mongodb::options::FindOptions::builder()
.projection(doc! { "name": 1, "status": 1, "_id": 0 })
.build()
} else {
mongodb::options::FindOptions::builder()
.projection(doc! { "status": 1, "_id": 0 })
.build()
};
match items_coll.find(filter, find_options).await {
Ok(cursor) => {
let results: Vec = cursor.collect().await;
HttpResponse::Ok().json(results)
}
Err(_) => HttpResponse::InternalServerError().finish(),
}
}
2. Avoid dynamic field names and operator injection
Never allow user input to become a field key or an operator name. If you need conditional projections, map known keys explicitly.
use mongodb::bson::doc;
fn build_projection(allowed_field: &str) -> mongodb::bson::Document {
match allowed_field {
"name" => doc! { "name": 1, "_id": 0 },
"status" => doc! { "status": 1, "_id": 0 },
_ => doc! { "status": 1, "_id": 0 },
}
}
// Usage inside handler:
let projection = build_projection(&user_input_field);
let opts = mongodb::options::FindOptions::builder().projection(projection).build();
3. Sanitize and reject unexpected keys in aggregation pipelines
If you build pipelines dynamically, validate each stage and parameter. Do not concatenate user input into stage definitions.
use mongodb::bson::doc;
fn pipeline_for_role(role: &str) -> Vec {
match role {
"admin" => vec![doc! { "$match": { "role": "admin" } }],
"user" => vec![doc! { "$match": { "role": { "$in": ["user", "admin"] } } }],
_ => vec![doc! { "$match": { "role": "user" } }],
}
}
// Do NOT do this:
// let user_stage = format!("$match: {{ status: {} }}", user_status);
// pipeline.push(bson::from_str(&user_stage).unwrap());
4. Disable server-side JavaScript where possible
Ensure MongoDB deployment does not allow $where or $function unless strictly required and properly isolated. In application code, avoid constructing query strings that the server will evaluate.
// Safe query using only standard operators:
let filter = doc! {
"tenant_id": tenant_uuid,
"deleted_at": None::,
"$and": vec![
doc! { "value": doc! { "$gte": 0 } },
doc! { "value": doc! { "$lte": 1000 } }
]
};
5. Use strict error handling and avoid leaking internal details
Map MongoDB driver errors to generic responses in Actix to prevent information disclosure that could assist hallucination probing.
async fn safe_find(coll: &Collection, filter: doc! {}) -> Result, actix_web::Error> {
match coll.find(filter, None).await {
Ok(cursor) => Ok(cursor.collect().await),
Err(e) => {
// Log detailed error internally, return generic response
error!("Database access failed");
Err(actix_web::error::ErrorInternalServerError("Service error"))
}
}
} Related CWEs: llmSecurity
| CWE ID | Name | Severity |
|---|---|---|
| CWE-754 | Improper Check for Unusual or Exceptional Conditions | MEDIUM |