RSTR-ORM-002 — Django ORM create/filter/update with **request.POST

Summary

A Django view passes a request body directly into a model create / update / filter, e.g. Model.objects.create(**request.POST). Every key in the request body becomes a field write, regardless of whether the form was meant to expose it. An attacker can promote themselves to admin by submitting is_staff=true (or whatever the model's flag field is called).

This is mass assignment, CWE-915.

Severity

High.

Languages

Python (Django).

What rastray flags

def signup(request):
    User.objects.create(**request.POST)              # ← flagged
def update(request, pk):
    Article.objects.filter(pk=pk).update(**request.POST)  # ← flagged

What rastray deliberately does not flag

  • Form-bound paths: form = SignupForm(request.POST); form.save().
  • ModelForm or DRF Serializer-driven updates.
  • Explicit field lists: User.objects.create(email=request.POST['email']).

How to fix it

Always go through a ModelForm, a Django REST Framework Serializer, or an explicit allow-list:

from django.forms import ModelForm

class SignupForm(ModelForm):
    class Meta:
        model = User
        fields = ['email', 'password']     # allow-list

def signup(request):
    form = SignupForm(request.POST)
    if not form.is_valid():
        return HttpResponseBadRequest(form.errors)
    form.save()
# REST framework
class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['email', 'password']
        read_only_fields = ['is_staff', 'is_superuser']

References