
mass-assignment-anti-pattern
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.
"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 (also known as "autobinding") is a vulnerability that occurs when a web framework automatically binds incoming HTTP request parameters to variables or objects in the application's code. This is a convenient feature, but it becomes a vulnerability when an attacker can inject and set properties they are not supposed to control. The most common example is an attacker submitting a request with a field like "isAdmin": true and having the application blindly save it, escalating their privileges.
The Anti-Pattern
The anti-pattern is directly using a dictionary of user-provided data to create or update a database model without first filtering for allowed properties.
BAD Code Example
# VULNERABLE: The incoming request data is used directly to update the user model.
from flask import request
from db import User, session
@app.route("/api/users/me", methods=["POST"])
def update_profile():
# Assume user is already authenticated.
user = get_current_user()
# Attacker crafts a JSON body:
# {
# "email": "new.email@example.com",
# "is_admin": true
# }
request_data = request.get_json()
# Many ORMs allow updating an object from a dictionary.
# If the User model has an `is_admin` property, it will be updated here.
for key, value in request_data.items():
setattr(user, key, value) # Direct, unsafe assignment.
session.commit()
return {"message": "Profile updated."}
# The attacker has just made themselves an administrator.
GOOD Code Example
# SECURE: Use a Data Transfer Object (DTO) or an explicit allowlist to control which fields can be updated.
from flask import request
from db import User, session
# Option 1: Use an allowlist of fields.
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():
# Only update the attribute if it's in our explicit allowlist.
if key in ALLOWED_UPDATE_FIELDS:
setattr(user, key, value)
session.commit()
return {"message": "Profile updated."}
# Option 2 (Better): Use a DTO or schema to define and validate the input.
from pydantic import BaseModel, EmailStr
class UserUpdateDTO(BaseModel):
# This class defines the *only* fields that can be submitted.
# The `is_admin` field is not here, so it can't be set by the user.
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:
# Pydantic will raise a validation error if extra fields like `is_admin` are present.
update_data = UserUpdateDTO(**request.get_json())
except ValidationError as e:
return {"error": str(e)}, 400
user.email = update_data.email
user.first_name = update_data.first_name
user.last_name = update_data.last_name
session.commit()
return {"message": "Profile updated."}
Detection
- Review update/create logic: Look for any code that takes a user-provided dictionary or object (
request.body,params, etc.) and uses it to directly populate a model (e.g.,user.update(params),new User(params)). - Check for "allowlists" vs. "blocklists": Code that tries to remove bad keys (a blocklist, e.g.,
del params['is_admin']) is insecure. A new sensitive property could be added to the model later and forgotten in the blocklist. Secure code uses an allowlist to only accept known-good keys. - Test API endpoints: Send requests to
POSTorPUTendpoints with extra, unauthorized fields in the JSON body (e.g.,is_admin,role,account_balance) and see if the values are reflected in the API's response or the database.
Prevention
- [ ] Use an allowlist approach: Never use a blocklist to filter incoming data. Always use an allowlist of properties that are permitted to be set by the user.
- [ ] Use Data Transfer Objects (DTOs) or dedicated input schemas to strictly define the expected request body. This is the most robust solution.
- [ ] Set sensitive properties explicitly in your code, outside of any mass assignment operation (e.g.,
new_user.is_admin = False). - [ ] Be aware of framework features: Some frameworks have built-in protections against mass assignment. Understand how to use them correctly.
Related Security Patterns & Anti-Patterns
- Excessive Data Exposure Anti-Pattern: The inverse of mass assignment. Instead of accepting too much data, the application returns too much data.
- Missing Authentication Anti-Pattern: If an endpoint is also missing proper authentication, mass assignment becomes even more dangerous, as an unauthenticated user could modify any object.
References
You Might Also Like
Related Skills

coding-agent
Run Codex CLI, Claude Code, OpenCode, or Pi Coding Agent via background process for programmatic control.
openclaw
add-uint-support
Add unsigned integer (uint) type support to PyTorch operators by updating AT_DISPATCH macros. Use when adding support for uint16, uint32, uint64 types to operators, kernels, or when user mentions enabling unsigned types, barebones unsigned types, or uint support.
pytorch
at-dispatch-v2
Convert PyTorch AT_DISPATCH macros to AT_DISPATCH_V2 format in ATen C++ code. Use when porting AT_DISPATCH_ALL_TYPES_AND*, AT_DISPATCH_FLOATING_TYPES*, or other dispatch macros to the new v2 API. For ATen kernel files, CUDA kernels, and native operator implementations.
pytorch
skill-writer
Guide users through creating Agent Skills for Claude Code. Use when the user wants to create, write, author, or design a new Skill, or needs help with SKILL.md files, frontmatter, or skill structure.
pytorch
implementing-jsc-classes-cpp
Implements JavaScript classes in C++ using JavaScriptCore. Use when creating new JS classes with C++ bindings, prototypes, or constructors.
oven-sh
implementing-jsc-classes-zig
Creates JavaScript classes using Bun's Zig bindings generator (.classes.ts). Use when implementing new JS APIs in Zig with JSC integration.
oven-sh