diff options
| author | Carlton Gibson <carlton.gibson@noumenal.es> | 2019-11-25 15:23:52 +0100 |
|---|---|---|
| committer | Carlton Gibson <carlton.gibson@noumenal.es> | 2019-12-02 08:57:44 +0100 |
| commit | 092cd66cf3c3e175acce698d6ca2012068d878fa (patch) | |
| tree | 7632a9bd92e8bdc07a6e2e082a895d6c7101e965 /django | |
| parent | db0cc4ae96c4752d10d98a3c7f2c48f813bf8a7f (diff) | |
Fixed CVE-2019-19118 -- Required edit permissions on parent model for editable inlines in admin.
Thank you to Shen Ying for reporting this issue.
Diffstat (limited to 'django')
| -rw-r--r-- | django/contrib/admin/options.py | 21 | ||||
| -rw-r--r-- | django/contrib/admin/templates/admin/edit_inline/stacked.html | 2 | ||||
| -rw-r--r-- | django/contrib/admin/templates/admin/edit_inline/tabular.html | 4 |
3 files changed, 19 insertions, 8 deletions
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index 85896bed7e..795d20f96a 100644 --- a/django/contrib/admin/options.py +++ b/django/contrib/admin/options.py @@ -1464,13 +1464,20 @@ class ModelAdmin(BaseModelAdmin): ) def get_inline_formsets(self, request, formsets, inline_instances, obj=None): + # Edit permissions on parent model are required for editable inlines. + can_edit_parent = self.has_change_permission(request, obj) if obj else self.has_add_permission(request) inline_admin_formsets = [] for inline, formset in zip(inline_instances, formsets): fieldsets = list(inline.get_fieldsets(request, obj)) readonly = list(inline.get_readonly_fields(request, obj)) - has_add_permission = inline.has_add_permission(request, obj) - has_change_permission = inline.has_change_permission(request, obj) - has_delete_permission = inline.has_delete_permission(request, obj) + if can_edit_parent: + has_add_permission = inline.has_add_permission(request, obj) + has_change_permission = inline.has_change_permission(request, obj) + has_delete_permission = inline.has_delete_permission(request, obj) + else: + # Disable all edit-permissions, and overide formset settings. + has_add_permission = has_change_permission = has_delete_permission = False + formset.extra = formset.max_num = 0 has_view_permission = inline.has_view_permission(request, obj) prepopulated = dict(inline.get_prepopulated_fields(request, obj)) inline_admin_formset = helpers.InlineAdminFormSet( @@ -1535,8 +1542,12 @@ class ModelAdmin(BaseModelAdmin): else: obj = self.get_object(request, unquote(object_id), to_field) - if not self.has_view_or_change_permission(request, obj): - raise PermissionDenied + if request.method == 'POST': + if not self.has_change_permission(request, obj): + raise PermissionDenied + else: + if not self.has_view_or_change_permission(request, obj): + raise PermissionDenied if obj is None: return self._get_obj_does_not_exist_redirect(request, opts, object_id) diff --git a/django/contrib/admin/templates/admin/edit_inline/stacked.html b/django/contrib/admin/templates/admin/edit_inline/stacked.html index 8af4d54791..d9c27b1578 100644 --- a/django/contrib/admin/templates/admin/edit_inline/stacked.html +++ b/django/contrib/admin/templates/admin/edit_inline/stacked.html @@ -12,7 +12,7 @@ <h3><b>{{ inline_admin_formset.opts.verbose_name|capfirst }}:</b> <span class="inline_label">{% if inline_admin_form.original %}{{ inline_admin_form.original }}{% if inline_admin_form.model_admin.show_change_link and inline_admin_form.model_admin.has_registered_model %} <a href="{% url inline_admin_form.model_admin.opts|admin_urlname:'change' inline_admin_form.original.pk|admin_urlquote %}" class="{% if inline_admin_formset.has_change_permission %}inlinechangelink{% else %}inlineviewlink{% endif %}">{% if inline_admin_formset.has_change_permission %}{% trans "Change" %}{% else %}{% trans "View" %}{% endif %}</a>{% endif %} {% else %}#{{ forloop.counter }}{% endif %}</span> {% if inline_admin_form.show_url %}<a href="{{ inline_admin_form.absolute_url }}">{% trans "View on site" %}</a>{% endif %} - {% if inline_admin_formset.formset.can_delete and inline_admin_form.original %}<span class="delete">{{ inline_admin_form.deletion_field.field }} {{ inline_admin_form.deletion_field.label_tag }}</span>{% endif %} + {% if inline_admin_formset.formset.can_delete and inline_admin_formset.has_delete_permission and inline_admin_form.original %}<span class="delete">{{ inline_admin_form.deletion_field.field }} {{ inline_admin_form.deletion_field.label_tag }}</span>{% endif %} </h3> {% if inline_admin_form.form.non_field_errors %}{{ inline_admin_form.form.non_field_errors }}{% endif %} {% for fieldset in inline_admin_form %} diff --git a/django/contrib/admin/templates/admin/edit_inline/tabular.html b/django/contrib/admin/templates/admin/edit_inline/tabular.html index 531d7b6a21..d643955dcf 100644 --- a/django/contrib/admin/templates/admin/edit_inline/tabular.html +++ b/django/contrib/admin/templates/admin/edit_inline/tabular.html @@ -17,7 +17,7 @@ </th> {% endif %} {% endfor %} - {% if inline_admin_formset.formset.can_delete %}<th>{% trans "Delete?" %}</th>{% endif %} + {% if inline_admin_formset.formset.can_delete and inline_admin_formset.has_delete_permission %}<th>{% trans "Delete?" %}</th>{% endif %} </tr></thead> <tbody> @@ -63,7 +63,7 @@ {% endfor %} {% endfor %} {% endfor %} - {% if inline_admin_formset.formset.can_delete %} + {% if inline_admin_formset.formset.can_delete and inline_admin_formset.has_delete_permission %} <td class="delete">{% if inline_admin_form.original %}{{ inline_admin_form.deletion_field.field }}{% endif %}</td> {% endif %} </tr> |
