Fixed #23601 -- Ensured view exists in URLconf before importing it in admindocs.

This commit is contained in:
Markus Holtermann 2014-10-04 19:04:21 +02:00 committed by Tim Graham
parent a24cf21722
commit 2f16ff5a6c
4 changed files with 29 additions and 4 deletions

View File

@ -143,10 +143,11 @@ class ViewDetailView(BaseAdminDocsView):
def get_context_data(self, **kwargs):
view = self.kwargs['view']
mod, func = urlresolvers.get_mod_func(view)
try:
urlconf = urlresolvers.get_urlconf()
if urlresolvers.get_resolver(urlconf)._is_callback(view):
mod, func = urlresolvers.get_mod_func(view)
view_func = getattr(import_module(mod), func)
except (ImportError, AttributeError):
else:
raise Http404
title, body, metadata = utils.parse_docstring(view_func.__doc__)
if title:

View File

@ -353,6 +353,11 @@ class RegexURLResolver(LocaleRegexProvider):
self._populate()
return self._app_dict[language_code]
def _is_callback(self, name):
if not self._populated:
self._populate()
return name in self._callback_strs
def resolve(self, path):
path = force_text(path) # path may be a reverse_lazy object
tried = []
@ -430,7 +435,7 @@ class RegexURLResolver(LocaleRegexProvider):
original_lookup = lookup_view
try:
if lookup_view in self._callback_strs:
if self._is_callback(lookup_view):
lookup_view = get_callable(lookup_view, True)
except (ImportError, AttributeError) as e:
raise NoReverseMatch("Error importing '%s': %s." % (lookup_view, e))

View File

@ -76,6 +76,14 @@ Minor features
<django.contrib.admin.ModelAdmin.show_full_result_count>` to control whether
or not the full count of objects should be displayed on a filtered admin page.
:mod:`django.contrib.admindocs`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* The view to browse view details now checks if the view specified in the URL
exists in the URLconf. Previously it was possible to import arbitrary
packages from the Python path. This was not considered a security issue
because ``admindocs`` is only accessible to staff users.
:mod:`django.contrib.auth`
^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -1,3 +1,4 @@
import sys
import unittest
from django.conf import settings
@ -84,6 +85,16 @@ class AdminDocViewTests(AdminDocsTestCase):
# View docstring
self.assertContains(response, 'Base view for admindocs views.')
def test_view_detail_illegal_import(self):
"""
#23601 - Ensure the view exists in the URLconf.
"""
response = self.client.get(
reverse('django-admindocs-views-detail',
args=['urlpatterns_reverse.nonimported_module.view']))
self.assertEqual(response.status_code, 404)
self.assertNotIn("urlpatterns_reverse.nonimported_module", sys.modules)
def test_model_index(self):
response = self.client.get(reverse('django-admindocs-models-index'))
self.assertContains(