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']