Mass Assignment
Mass assignment vulnerabilities occur when an API binds all user-supplied fields to a data model without filtering, allowing attackers to set fields they should never control — such as role, isAdmin, or plan — and escalate their own privileges.
What Is Mass Assignment?
Mass assignment happens when a backend framework automatically binds all JSON fields from a request body to a database model — including fields that should be internal-only. An attacker adds unexpected fields to a legitimate request and the server persists them.
This is one of the most common vulnerabilities in AI-generated backends because frameworks like FastAPI, Express, and Rails make it easy to auto-bind request bodies to models.
How It Works
A user updates their profile:
PATCH /api/profile
Content-Type: application/json
{"name": "Alice", "email": "alice@example.com"}An attacker adds extra fields:
PATCH /api/profile
Content-Type: application/json
{
"name": "Alice",
"email": "alice@example.com",
"role": "admin",
"is_admin": true,
"plan": "enterprise",
"verified": true,
"credits": 999999
}If the backend does this:
# Vulnerable — SQLAlchemy / ORM auto-binding
user = db.query(User).get(user_id)
for key, value in request.json().items():
setattr(user, key, value) # sets ANYTHING from the request
db.commit()The attacker is now an admin with an enterprise plan and unlimited credits.
Common in AI-Generated Code
AI tools frequently generate patterns like:
# FastAPI — dangerous if User model has sensitive fields
@router.patch("/profile")
def update_profile(user_id: int, data: User, db: Session = Depends(get_db)):
db_user = db.query(User).get(user_id)
db_user.__dict__.update(data.dict()) # mass assignment// Express + Mongoose — dangerous
User.findByIdAndUpdate(userId, req.body) // req.body has everythingReal-World Impact
- Privilege escalation — any user can become admin
- Subscription bypass — free tier users unlock paid features
- Credit fraud — unlimited balance injection
- Account verification bypass — set
email_verified: truewithout clicking the link - Data integrity — overwrite internal fields like
created_at,user_id
How to Fix
Use explicit allow-lists (schemas/DTOs):
# FastAPI — define exactly what users can update
class ProfileUpdate(BaseModel):
name: str | None = None
email: EmailStr | None = None
avatar_url: str | None = None
# role, is_admin, plan — NOT included
@router.patch("/profile")
def update_profile(data: ProfileUpdate, ...):
# Only allowed fields can be set
user.update(**data.model_dump(exclude_unset=True))// TypeScript / Zod — strict schema
const ProfileUpdateSchema = z.object({
name: z.string().optional(),
email: z.string().email().optional(),
// role is NOT in schema — cannot be set
})
const data = ProfileUpdateSchema.parse(req.body)Explicitly exclude sensitive fields in ORMs:
# SQLAlchemy — only update allowed columns
allowed_fields = {"name", "email", "avatar_url"}
update_data = {k: v for k, v in data.items() if k in allowed_fields}
db.query(User).filter(User.id == user_id).update(update_data)// Mongoose — use select() to exclude fields
const ALLOWED = ['name', 'email', 'avatarUrl']
const update = Object.fromEntries(
Object.entries(req.body).filter(([k]) => ALLOWED.includes(k))
)What VibeWShield Detects
VibeWShield's Mass Assignment scanner (aggressive mode) injects privilege-escalation fields into discovered POST/PUT endpoints:
role, is_admin, isAdmin, admin, verified, active, status, permissions, scope, plan
After injecting, it makes a GET request to the same resource and checks whether the injected field was persisted or reflected. Confirmed findings are flagged as High with the exact field and endpoint.
Free security scan
Test your app for Mass Assignment
VibeWShield automatically checks for Mass Assignment and 40+ other vulnerabilities using 63 scanners — in under 3 minutes, no signup required.
Scan your app free