mass-assignment-anti-pattern

📁 igbuend/grimbard 📅 Jan 20, 2026
3
总安装量
3
周安装量
#54889
全站排名
安装命令
npx skills add https://github.com/igbuend/grimbard --skill mass-assignment-anti-pattern

Agent 安装分布

claude-code 3
codex 3
cursor 3
opencode 3
trae-cn 2
antigravity 2

Skill 文档

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

# VULNERABLE: Incoming request data used directly to update user model
from flask import request
from db import User, session

@app.route("/api/users/me", methods=["POST"])
def update_profile():
    # User already authenticated
    user = get_current_user()

    # Attacker crafts JSON body:
    # {
    #   "email": "new.email@example.com",
    #   "is_admin": true
    # }
    request_data = request.get_json()

    # ORMs allow updating objects from dictionaries
    # If User model has `is_admin` property, it updates here
    for key, value in request_data.items():
        setattr(user, key, value) # Direct, unsafe assignment

    session.commit()
    return {"message": "Profile updated."}

# Attacker just became administrator

GOOD Code Example

# SECURE: Use DTO or explicit allowlist to control updatable fields
from flask import request
from db import User, session

# Option 1: 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():
        # Update only if in explicit allowlist
        if key in ALLOWED_UPDATE_FIELDS:
            setattr(user, key, value)

    session.commit()
    return {"message": "Profile updated."}


# Option 2 (Better): Use DTO or schema for validation
from pydantic import BaseModel, EmailStr

class UserUpdateDTO(BaseModel):
    # Defines *only* submittable fields
    # `is_admin` not included, can't be set by 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 raises validation error if extra fields 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

  • 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

  • Use allowlists: Never use blocklists. Always use allowlists of user-settable properties
  • Use DTOs or schemas: Strictly define expected request body. Most robust solution
  • Set sensitive properties explicitly: Outside mass assignment (e.g., new_user.is_admin = False)
  • Know framework features: Some frameworks include mass assignment protections. Use them correctly

Related Security Patterns & Anti-Patterns

References