Django formset security and injecting PKs in formset hidden id fields

88 views
Skip to first unread message

Rob Ladd

unread,
May 3, 2016, 2:23:12 PM5/3/16
to Django users

I've noticed something troubling in Django formsets:

Each formset.form has a hidden field with the id of the model being edited. 

All one would need to do is change this id and submit, and the default formset clean() or save() methods don't bat an eye.


I would think that it wouldn't be too complicated to keep track of which objects were in the original formset queryset, and compare them on save. 

Given all the other convenient security methods we have, I wonder why Django doesn't do this already?

Tim Graham

unread,
May 4, 2016, 10:33:37 AM5/4/16
to Django users
How would you keep track of which objects were in the original formset? If you generate the same queryset in the formset for both formset creation and formset submission you shouldn't run into any security issues.

Carl Meyer

unread,
May 6, 2016, 7:15:43 PM5/6/16
to django...@googlegroups.com
Hi Rob,

On 05/03/2016 12:23 PM, Rob Ladd wrote:
> I've noticed something troubling in Django formsets:
>
> Each formset.form has a hidden field with the id of the model being edited.
>
> All one would need to do is change this id and submit, and the default
> formset |clean()| or |save()| methods don't bat an eye.

First of all, if you believe that you've found a security issue in
Django, please err on the side of caution and email
secu...@djangoproject.com, rather than reporting it in public. Thanks!

Second: can you provide a sample project demonstrating the behavior you
describe? I'm unable to reproduce that behavior, and by code inspection
I don't see how that behavior could occur, either. If you pass in the
`queryset` keyword argument when instantiating the formset, only objects
matching that queryset will be editable via the formset. Meddling with
IDs will at best allow you to create a new object, never to edit one
that's outside of `queryset`. But formsets always allow creation of new
objects.

It is true that the given queryset could match some new object on submit
that wasn't part of the queryset when the formset was initially
displayed, if that object was created or edited such that it now matches
the queryset filters in the meantime. There isn't any reasonable way for
Django to address this problem: there isn't necessarily any location
available to store state in between display and submit other than the
page, and that's under the control of the user. You should just be sure
that the filters applied to the `queryset` accurately describe the
limitations you want applied to the editing abilities of the user being
shown the formset. In a typical use case, the `queryset` would apply a
filter like `(owner=request.user)`, allowing a user to edit only the
objects they own.

If you still believe you're seeing a security issue here, please email
secu...@djangoproject.com with step by step reproduction instructions.

Thanks,

Carl

signature.asc
Reply all
Reply to author
Forward
0 new messages