Sql Injection in Actix with Firestore
Sql Injection in Actix with Firestore — how this specific combination creates or exposes the vulnerability
SQL Injection (SQLi) is a web security vulnerability that occurs when untrusted input is concatenated into a database query without proper validation or parameterization. In an Actix web service that uses Google Cloud Firestore, risk arises not from Firestore itself (which is a NoSQL database and does not use SQL), but from how developers construct queries or downstream SQL-based systems using data from Firestore. For example, if an Actix handler reads a document field from Firestore and then uses that value to build a SQL string sent to a relational database, the concatenation can lead to SQLi if the input is not properly parameterized.
Consider an Actix handler that retrieves a user identifier from Firestore and uses it in a raw SQL query:
// Dangerous: using Firestore data directly in downstream SQL string building
async fn get_user_orders(req: HttpRequest) -> impl Responder {
let user_id = get_user_id_from_firestore(&req).unwrap_or_default();
let sql = format!("SELECT * FROM orders WHERE user_id = '{}'", user_id);
// execute sql with a database client...
HttpResponse::Ok().body(sql)
}
If user_id contains values like 123' OR '1'='1, the resulting SQL string becomes:
SELECT * FROM orders WHERE user_id = '123' OR '1'='1'
This allows an attacker to bypass intended filters and potentially read or modify other users’ data. Even when Firestore is used only as a configuration or identity store, using its data to construct SQL without strict validation or parameterization exposes the application to SQLi. Additionally, Firestore document IDs or field values that include special characters can inadvertently contribute to injection if treated as identifiers or interpolated into queries.
Another scenario involves reflection or logging features in Actix that include Firestore data in system-generated queries or error messages. For instance, including Firestore document contents in verbose logs or dynamic query builders without escaping can aid reconnaissance for injection attacks. Therefore, the combination of Actix routing and Firestore data becomes a concern when Firestore values are passed to SQL-based components without secure handling.
Firestore-Specific Remediation in Actix — concrete code fixes
Defend against SQLi by ensuring any data from Firestore that is used in downstream SQL is handled safely. The primary technique is to use parameterized queries or prepared statements rather than string interpolation. Below are concrete, safe patterns for Actix handlers that incorporate Firestore data into SQL operations.
1. Use parameterized queries with a SQL client (e.g., sqlx)
Instead of building SQL strings, bind parameters so the database driver handles escaping:
// Safe: using parameterized queries with sqlx
async fn get_user_orders_safe(user_id: String) -> Result {
let pool = establish_pool().await?;
let rows = sqlx::query!("SELECT * FROM orders WHERE user_id = ?", user_id)
.fetch_all(&pool)
.await?;
Ok(format!("{:#?}", rows))
}
2. Validate and sanitize Firestore-derived input
Enforce strict allowlists for expected formats (e.g., numeric IDs) before using the value in SQL:
// Validate Firestore-derived user_id is numeric before using in SQL
fn is_valid_user_id(id: &str) -> bool {
id.chars().all(char::is_numeric)
}
async fn handler(req: HttpRequest) -> impl Responder {
let user_id = match get_user_id_from_firestore(&req) {
Some(id) if is_valid_user_id(&id) => id,
_ => return HttpResponse::BadRequest().body("Invalid user ID"),
};
let pool = establish_pool().await.unwrap();
let result = sqlx::query_as!(
Order,
"SELECT * FROM orders WHERE user_id = ?",
user_id
)
.fetch_all(&pool)
.await;
match result {
Ok(orders) => HttpResponse::Ok().json(orders),
Err(_) => HttpResponse::InternalServerError().finish(),
}
}
3. Use Firestore as the source of truth and avoid constructing SQL from its documents
Where possible, perform filtering and authorization in Firestore and avoid generating SQL from Firestore document contents. If SQL is unavoidable, treat Firestore data as an input vector and apply strict encoding depending on the target SQL context (e.g., identifiers vs. literals).
4. Encode identifiers if they must be interpolated
If dynamic SQL generation is necessary (not recommended), use proper identifier quoting functions provided by your database driver:
// Example using a quoting helper for identifiers (pseudo-code)
let safe_column = db_quote_identifier("user_id");
let sql = format!("SELECT {} FROM users WHERE status = ?", safe_column);
// Still prefer parameters for values
let rows = client.query(&sql, &[&status]).await;
These practices ensure that data sourced from Firestore does not become a vector for SQL Injection when used within Actix services.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |