Excessive Data Exposure in Actix with Cockroachdb
Excessive Data Exposure in Actix with Cockroachdb — how this specific combination creates or exposes the vulnerability
Excessive Data Exposure occurs when an API returns more information than necessary for a given operation. In an Actix web service that uses Cockroachdb as the backend datastore, this commonly manifests through endpoints that query broad fields or fail to enforce field-level authorization before serialization. Because Cockroachdb is compatible with PostgreSQL wire protocol and drivers, Actix applications often use SQLx or diesel with queries like SELECT * FROM accounts or SELECT id, email, role, salary, ssn, internal_notes, reset_token FROM users. If the handler then serializes the full row into JSON, sensitive columns such as internal_notes or reset_token can be unintentionally exposed to the client.
Another contributing pattern is the use of generic DTOs or structs that mirror the database schema directly. In Actix, it is straightforward to define a struct with #[derive(Serialize)] that maps 1:1 to a Cockroachdb table. Without explicit field selection, this approach copies every column into the HTTP response. Even when endpoints accept query parameters for filtering (for example, ?fields=id,name), missing validation may cause the server to ignore the parameter or, worse, to still return full rows in error paths or default projections.
Versioned schema evolution in Cockroachdb can also amplify the risk. If new sensitive columns are added to a table and existing Actix handlers use broad queries or ORM entities that automatically include all columns, the newly added fields will automatically appear in API responses. This is particularly dangerous for regulated data such as personally identifiable information or financial details, which may be returned to clients that have no legitimate need to see them. The exposure is unauthenticated if the endpoint does not require a token or if the token is only checked after the data has already been selected and serialized.
Operational practices can further increase exposure. For instance, logging full query results during development might inadvertently capture sensitive Cockroachdb rows in application logs. If these logs are aggregated or accessible to a broader team, the sensitive data is effectively duplicated beyond the intended boundary. Additionally, HTTP caching layers or browser history may retain JSON responses that contain more data than necessary, extending the window of exposure beyond the immediate request.
middleBrick detects Excessive Data Exposure by correlating OpenAPI/Swagger specifications with runtime behavior. For an Actix service backed by Cockroachdb, it checks whether responses include fields that are not explicitly declared in the spec or which should be restricted based on the operation’s security requirements. This approach highlights mismatches between declared minimal schemas and actual data leakage, helping teams identify unintended exposure of sensitive columns such as internal_notes or reset_token before they are exploited.
Cockroachdb-Specific Remediation in Actix — concrete code fixes
Remediation for Excessive Data Exposure in Actix with Cockroachdb focuses on strict field selection, explicit DTOs, and disciplined mapping. Instead of selecting all columns, write targeted queries that return only the fields required by the response schema. Below are concrete, realistic examples using SQLx with Postgres types in an Actix service.
1) Use explicit column selection in SQLx queries. Define a minimal struct for serialization and map only the necessary columns:
use serde::Serialize; use sqlx::FromRow; #[derive(Serialize, FromRow)] struct UserSummary { id: i64, email: String, name: String, } async fn get_user_summary( pool: &sqlx::PgPool, user_id: i64, ) -> Result<UserSummary, sqlx::Error> { let row = sqlx::query_as!(UserSummary) .select(&["id", "email", "name"]) .from("users") .filter("id = $1") .fetch_one(pool) .await?; Ok(row) }
2) Avoid mapping directly to full table entities. If you have a table accounts with sensitive columns, create a separate read model or view in Cockroachdb and map to it:
create view public.v_user_public as
select id, email, display_name, created_at
from accounts
where deleted_at is null;
Then in Actix, map to a DTO that matches the view:
#[derive(Serialize, sqlx::FromRow)]
struct PublicUser {
id: i64,
email: String,
display_name: String,
created_at: chrono::DateTime<chrono::Utc>,
}
async fn get_public_users(pool: &sqlx::PgPool) -> Result<Vec<PublicUser>, sqlx::Error> {
sqlx::query_as("SELECT id, email, display_name, created_at FROM public.v_user_public")
.fetch_all(pool)
.await
}
3) Enforce field filtering at the handler level when clients request specific columns. Validate the requested fields against an allowlist and construct dynamic queries safely using SQLx’s query with explicit column lists, avoiding string interpolation that could lead to injection:
async fn get_user_fields(
pool: &sqlx::PgPool,
user_id: i64,
requested_fields: &[&str],
) -> Result<serde_json::Value, ApiError> {
const ALLOWED: &[&str] = &["id", "email", "name", "role"];
let cols: Vec<&str> = requested_fields
.iter()
.filter(|f| ALLOWED.contains(f.to_string().as_str()))
.copied()
.collect();
if cols.is_empty() {
return Err(ApiError::BadRequest("No valid fields requested"));
}
let col_list = cols.join(", ");
let sql = format!("SELECT {} FROM users WHERE id = $1", col_list);
let row = sqlx::query(&sql)
.bind(user_id)
.fetch_one(pool)
.await?;
Ok(row.try_into_json()?)
}
4) Apply row-level security in Cockroachdb for tenant or ownership checks, and ensure Actix validates ownership before constructing queries. Even when using column selection, rows should be scoped so that one user cannot request another user’s data:
async fn get_user_accounts(
pool: &sqlx::PgPool,
user_id: i64,
subject_id: i64,
) -> Result<Vec<AccountInfo>, sqlx::Error> {
sqlx::query_as(
"SELECT id, name, currency FROM accounts WHERE owner_id = $1 AND id = $2",
)
.bind(subject_id)
.bind(user_id)
.fetch_all(pool)
.await
}
These patterns limit the data surface exposed by Actix endpoints backed by Cockroachdb, ensuring that only necessary columns are selected and that sensitive fields are never part of the default response.
Related CWEs: propertyAuthorization
| CWE ID | Name | Severity |
|---|---|---|
| CWE-915 | Mass Assignment | HIGH |