| name | mass-assignment-anti-pattern |
| description | Security anti-pattern for mass assignment vulnerabilities (CWE-915). Use when generating or reviewing code that creates or updates objects from user input, form handling, or API request processing. Detects uncontrolled property binding enabling privilege escalation. |
Mass Assignment Anti-Pattern
Severity: High
Summary
Mass assignment (autobinding) occurs when frameworks automatically bind HTTP parameters to object properties without filtering. Attackers inject unauthorized properties (isAdmin: true) to escalate privileges or modify protected fields. This vulnerability enables complete access control bypass through parameter injection.
The Anti-Pattern
Never use user-provided data dictionaries to update models without filtering for allowed properties. Use explicit allowlists.
BAD Code Example
from flask import request
from db import User, session
@app.route("/api/users/me", methods=["POST"])
def update_profile():
user = get_current_user()
request_data = request.get_json()
for key, value in request_data.items():
setattr(user, key, value)
session.commit()
return {"message": "Profile updated."}
GOOD Code Example
from flask import request
from db import User, session
ALLOWED_UPDATE_FIELDS = {"email", "first_name", "last_name"}
@app.route("/api/users/me", methods=["POST"])
def update_profile_allowlist():
user = get_current_user()
request_data = request.get_json()
for key, value in request_data.items():
if key in ALLOWED_UPDATE_FIELDS:
setattr(user, key, value)
session.commit()
return {"message": "Profile updated."}
from pydantic import BaseModel, EmailStr
class UserUpdateDTO(BaseModel):
email: EmailStr
first_name: str
last_name: str
@app.route("/api/users/me/dto", methods=["POST"])
def update_profile_dto():
user = get_current_user()
try:
update_data = UserUpdateDTO(**request.get_json())
ValidationError e:
{: (e)},
user.email = update_data.email
user.first_name = update_data.first_name
user.last_name = update_data.last_name
session.commit()
{: }
Detection
- Find direct model updates from request data: Grep for unsafe binding:
rg 'setattr.*request\.|\.update\(request\.' --type py
rg 'Object\.assign.*req\.body|\.save\(req\.body' --type js
rg 'BeanUtils\.copyProperties|ModelMapper' --type java
- Identify blocklist approaches (insecure): Find key deletion patterns:
rg 'del.*\[.*(admin|role|permission)|\.pop\(.*(admin|role)' --type py
rg 'delete.*\.(isAdmin|role)|omit\(' --type js
- Blocklists are insecure - search for allowlist patterns instead
- Test for mass assignment: Send malicious parameters:
curl -X POST /api/users -d '{"email":"test@example.com","isAdmin":true}'
- Try:
isAdmin, role, permissions, accountBalance, verified
- Check for DTO usage: Verify proper input validation:
rg 'class.*DTO|@Valid|validator\.validate' --type py --type java
Prevention
Related Security Patterns & Anti-Patterns
References