GuardAPI Logo
GuardAPI

Fix Mass Assignment in Axum

Mass Assignment, or Overposting, in Axum occurs when you deserialize untrusted user input directly into internal domain models or database entities. In a typical Rust/Axum stack using Serde, if your request extractor uses the same struct as your database model, an attacker can inject fields like 'is_admin' or 'balance' into the JSON payload. If your update logic blindly applies these fields, you've just handed over the keys to the kingdom. Real hackers look for these 'hidden' fields in documentation or by guessing common administrative property names.

The Vulnerable Pattern

use axum::{Json, routing::post, Router};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)] struct User { id: u64, username: String, is_admin: bool, // Sensitive field }

// VULNERABLE: The handler accepts the full User struct. // An attacker can send: {“username”: “pwned”, “is_admin”: true} async fn update_profile(Json(user_data): Json) { println!(“Updating user {:?}”, user_data); // Database logic here would mistakenly update is_admin }

pub fn app() -> Router { Router::new().route(“/profile”, post(update_profile)) }

The Secure Implementation

The fix is strict decoupling via the DTO (Data Transfer Object) pattern. Never expose your internal state or DB schema directly to the Axum extractors. By creating a specific struct (e.g., UpdateUserRequest) that only contains public-facing fields, you create an implicit whitelist. Even if an attacker sends extra fields in the JSON body, Serde's default behavior will ignore them because they aren't defined in the target struct. For maximum security, you can also use #[serde(deny_unknown_fields)] on your DTOs to return a 400 Bad Request if an attacker tries to pass unexpected parameters, making reconnaissance much harder for them.

use axum::{Json, routing::post, Router};
use serde::Deserialize;

// SECURE: Define a Data Transfer Object (DTO) for the request. // Only include fields that are safe for the user to modify. #[derive(Deserialize)] struct UpdateUserRequest { username: String, // is_admin is omitted here; Serde will ignore it if sent in JSON }

async fn update_profile(Json(payload): Json) { // Manually map the DTO to your internal logic/DB model println!(“Updating username to: {}”, payload.username); // Internal logic handles sensitive fields separately, usually via auth checks }

pub fn app() -> Router { Router::new().route(“/profile”, post(update_profile)) }

System Alert • ID: 1196
Target: Axum API
Potential Vulnerability

Your Axum API might be exposed to Mass Assignment

74% of Axum apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.

RUN FREE SECURITY DIAGNOSTIC
GuardLabs Engine: ONLINE

Free Tier • No Credit Card • Instant Report

Verified by Ghost Labs Security Team

This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.