File CVE-2021-33203.patch of Package python-Django1
From e8533625cff17b41daf2352abadb74fa4209d911 Mon Sep 17 00:00:00 2001
From: Florian Apolloner <florian@apolloner.eu>
Date: Tue, 25 May 2021 11:55:06 +0200
Subject: [PATCH] [2.2.x] Fixed CVE-2021-33203 -- Fixed potential
path-traversal via admindocs' TemplateDetailView.
---
django/contrib/admindocs/views.py | 3 ++-
tests/admin_docs/test_views.py | 16 ++++++++++++++++
3 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/django/contrib/admindocs/views.py b/django/contrib/admindocs/views.py
index 12f5863228e8..2ddd710edb80 100644
--- a/django/contrib/admindocs/views.py
+++ b/django/contrib/admindocs/views.py
@@ -15,6 +15,7 @@ from django.db import models
from django.http import Http404
from django.template.engine import Engine
from django.urls import get_mod_func, get_resolver, get_urlconf, reverse
+from django.utils._os import safe_join
from django.utils.decorators import method_decorator
from django.utils.inspect import (
func_accepts_kwargs, func_accepts_var_args, func_has_no_args,
@@ -347,7 +348,7 @@ class TemplateDetailView(BaseAdminDocsView):
else:
# This doesn't account for template loaders (#24128).
for index, directory in enumerate(default_engine.dirs):
- template_file = os.path.join(directory, template)
+ template_file = safe_join(directory, template)
if os.path.exists(template_file):
with open(template_file) as f:
template_contents = f.read()
diff --git a/tests/admin_docs/test_views.py b/tests/admin_docs/test_views.py
index cf4f9359c7df..a528c07347ec 100644
--- a/tests/admin_docs/test_views.py
+++ b/tests/admin_docs/test_views.py
@@ -138,6 +138,22 @@ class AdminDocViewTests(TestDataMixin, AdminDocsTestCase):
self.assertContains(response, 'View documentation')
+@unittest.skipUnless(utils.docutils_is_available, 'no docutils installed.')
+class AdminDocViewDefaultEngineOnly(TestDataMixin, AdminDocsTestCase):
+
+ def setUp(self):
+ self.client.force_login(self.superuser)
+
+ def test_template_detail_path_traversal(self):
+ cases = ['/etc/passwd', '../passwd']
+ for fpath in cases:
+ with self.subTest(path=fpath):
+ response = self.client.get(
+ reverse('django-admindocs-templates', args=[fpath]),
+ )
+ self.assertEqual(response.status_code, 400)
+
+
@override_settings(TEMPLATES=[{
'NAME': 'ONE',
'BACKEND': 'django.template.backends.django.DjangoTemplates',