Pii Leakage in Actix with Firestore
Pii Leakage in Actix with Firestore — how this specific combination creates or exposes the vulnerability
Actix is a popular Rust framework for building high-performance web services. When Actix services integrate with Google Cloud Firestore as a backend datastore, PII leakage can occur if application code or Firestore security rules inadvertently expose sensitive user data. This risk arises from the combination of Actix request handling patterns and Firestore document reads/writes, especially when developers map Firestore documents directly to structured responses without filtering or redaction.
In a typical Actix handler, a developer might deserialize a Firestore document into a Rust struct and return it as JSON. If the struct contains PII fields such as email, phone, or internal identifiers and the handler does not strip or mask those fields before serialization, the API response will include that data to the client. Because Firestore documents often store user profile information, preferences, or audit metadata, naive mapping creates an easy path for PII leakage.
Another vector specific to the Actix + Firestore combo is the use of Firestore’s real-time listeners or snapshots in server-side code. If an Actix service attaches listeners to sensitive collections and broadcasts snapshot data over WebSockets or Server-Sent Events without access checks, PII can be streamed to unauthorized clients. Additionally, Firestore’s flexible schema can lead to inconsistent document structures; if an Actix handler assumes a fixed shape and iterates over dynamic key-value pairs, it might inadvertently serialize and return fields that contain PII.
Misconfigured Firestore security rules can exacerbate the issue. Rules that allow read access based solely on authentication status, without scoping to the user’s own documents or enforcing field-level restrictions, can permit an Actix service (acting on behalf of a client) to retrieve more data than necessary. When Actix code trusts the retrieved data and passes it through to the API response, the service effectively becomes a conduit for PII leakage.
Real-world attack patterns include an unauthenticated or weakly authenticated Actix endpoint returning user profile documents that contain email and display name, or an over-permissive Firestore rule enabling an Actix service to read entire collections. These patterns align with common OWASP API Top 10 risks such as excessive data exposure and broken object level authorization, and they can be surfaced by middleBrick’s checks for Data Exposure and BOLA/IDOR when scanning the unauthenticated attack surface.
Firestore-Specific Remediation in Actix — concrete code fixes
Remediation focuses on strict data handling in Actix handlers and disciplined Firestore rule design. In code, you should define separate response models that exclude PII and map only the necessary fields when serializing Firestore documents. Avoid directly exposing Firestore document structs; instead, construct lean data transfer objects (DTOs).
use actix_web::{web, HttpResponse};
use google_cloud_rust::firestore::client::FirestoreClient;
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize)]
struct UserRecord {
email: String,
phone: String,
display_name: String,
internal_id: String,
}
#[derive(Debug, Serialize)]
struct UserProfileResponse {
display_name: String,
// intentionally excluding email, phone, internal_id
}
async fn get_profile(
firestore_client: web::Data,
path: web::Path,
) -> HttpResponse {
let user_id = path.into_inner();
let doc_path = format!("users/{}", user_id);
let snapshot = firestore_client.get_document(&doc_path, None).await;
match snapshot {
Ok(doc) => {
// Map Firestore document to domain model, then to DTO
let user: UserRecord = doc.deserialize().unwrap_or_default();
let response = UserProfileResponse {
display_name: user.display_name,
};
HttpResponse::Ok().json(response)
}
Err(_) => HttpResponse::NotFound().finish(),
}
}
In this example, the Actix handler deserializes the Firestore document into a full domain struct but constructs a separate response type that contains only non-PII fields before serializing to JSON. This ensures that even if Firestore returns PII, the API response does not.
On the Firestore rules side, adopt principle of least privilege and field-level restrictions. Use Firebase Security Rules to limit read access to the owner’s documents and to specific fields. While rules are not enforced by Actix code, they reduce the data surface that Actix services can retrieve:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read: if request.auth != null && request.auth.uid == userId;
allow write: if request.auth != null && request.auth.uid == userId;
// Explicitly deny reading sensitive fields by default; allow only for owner
allow get_email: if request.auth != null && request.auth.uid == userId && request.resource.data.keys().hasAny(['email']);
}
}
}
Additionally, sanitize and validate Firestore document keys in Actix to avoid dynamic exposure. When iterating over map-like structures, filter out known PII keys before including data in responses:
fn sanitize_user_data(doc_data: std::collections::HashMap) -> std::collections::HashMap {
let pii_keys = ["email", "phone", "ssn"];
doc_data.into_iter()
.filter(|(k, _)| !pii_keys.contains(&k.as_str()))
.collect()
}
These practices reduce the likelihood of PII leakage by ensuring Actix handlers handle only necessary data and that Firestore rules minimize what can be read. Findings from middleBrick’s scans, such as Data Exposure and BOLA/IDOR checks, can highlight where such gaps remain.
Related CWEs: dataExposure
| CWE ID | Name | Severity |
|---|---|---|
| CWE-200 | Exposure of Sensitive Information | HIGH |
| CWE-209 | Error Information Disclosure | MEDIUM |
| CWE-213 | Exposure of Sensitive Information Due to Incompatible Policies | HIGH |
| CWE-215 | Insertion of Sensitive Information Into Debugging Code | MEDIUM |
| CWE-312 | Cleartext Storage of Sensitive Information | HIGH |
| CWE-359 | Exposure of Private Personal Information (PII) | HIGH |
| CWE-522 | Insufficiently Protected Credentials | CRITICAL |
| CWE-532 | Insertion of Sensitive Information into Log File | MEDIUM |
| CWE-538 | Insertion of Sensitive Information into Externally-Accessible File | HIGH |
| CWE-540 | Inclusion of Sensitive Information in Source Code | HIGH |