Mass Assignment in Actix with Bearer Tokens
Mass Assignment in Actix with Bearer Tokens — how this specific combination creates or exposes the vulnerability
Mass Assignment occurs when an API binds incoming JSON directly to a server-side structure or model without filtering fields, allowing an attacker to set properties that should be immutable or managed server-side. In Actix, this commonly happens when a developer uses a handler that deserializes request bodies into a struct with serde and then uses that struct to create or update a database record. If the handler also relies on Bearer Tokens for authorization, the risk pattern becomes:
- The token identifies a user and is validated (e.g., via middleware or guards).
- The validated identity is used to decide what data the user is allowed to modify.
- The deserialization step maps all request fields into a model that may include sensitive fields like
is_admin,role, orpermissions.
If field-level allowlisting is not enforced, an authenticated request with a valid Bearer Token can overwrite privileged attributes simply by including them in the JSON payload. For example, a PATCH endpoint that intends to update a user’s email might bind the entire request to a struct containing an is_admin field. If the handler calls a method like update_user(id, payload) without explicitly excluding is_admin, the token-authenticated update can escalate privileges.
This is distinct from general IDOR/BOLA because the issue is not about accessing another user’s resource, but about modifying one’s own resource with maliciously extended fields. The presence of Bearer Tokens is necessary for authentication but insufficient for authorization at the field level, which is why the combination exposes a Mass Assignment vector.
Real-world analogs include findings reported in frameworks where binding logic is too permissive. In Actix-web, this often maps to the OWASP API Top 10 2023 category 1: Broken Object Level Authorization when the lack of field filtering enables privilege escalation.
Bearer Tokens-Specific Remediation in Actix — concrete code fixes
Remediation focuses on strict field filtering and avoiding automatic mapping of all request fields into domain models. Prefer explicit extraction or DTOs that only include updatable fields. Below are two concrete patterns for Actix handlers using Bearer Tokens.
1) Whitelist-based handler with a dedicated update DTO
Define a struct that includes only the fields you intend to allow updates for, and deserialize into that struct instead of your domain model.
use actix_web::{web, HttpResponse, Result};
use serde::Deserialize;
#[derive(Deserialize)]
struct UpdateUserEmail {
email: String,
}
async fn change_email(
token_user_id: u64, // extracted from Bearer Token by middleware
payload: web::Json,
) -> Result {
// Only the email field is accepted from the request
let new_email = &payload.email;
// Proceed to update only the email for token_user_id
// db.update_email(token_user_id, new_email).await?;
Ok(HttpResponse::Ok().finish())
}
This ensures fields like is_admin or role cannot be set via the request, regardless of whether a Bearer Token is present.
2) PATCH with selective merging and Bearer Token identity
If you must accept a flexible payload, parse into a serde_json::Value or a map and merge only allowed keys.
use actix_web::{web, HttpResponse, Result};
use serde_json::Value;
async fn patch_user(
token_user_id: u64,
body: web::Json,
) -> Result {
let obj = body.as_object().ok_or_else(|| {
actix_web::error::ErrorBadRequest("Expected JSON object")
})?;
// Allowlist of mutable fields
const ALLOWED: &[&str] = &["email", "display_name"];
let mut updates = serde_json::Map::new();
for key in ALLOWED {
if let Some(value) = obj.get(*key) {
updates.insert(key.to_string(), value.clone());
}
}
// db.patch_user(token_user_id, &updates).await?;
Ok(HttpResponse::Ok().finish())
}
In both examples, Bearer Tokens are still used for authentication (user identity), but the handler enforces authorization at the field level, eliminating Mass Assignment.
Additional guidance:
- For Rust structs used with database models, consider separate request types for creation, update, and admin actions.
- Combine this with middleware that validates Bearer Tokens and injects the user identity into request extensions for consistent identity handling.
Related CWEs: propertyAuthorization
| CWE ID | Name | Severity |
|---|---|---|
| CWE-915 | Mass Assignment | HIGH |