diff --git a/src/open_inwoner/apimock/tests/test_views.py b/src/open_inwoner/apimock/tests/test_views.py index a203228392..ccb69d8d1c 100644 --- a/src/open_inwoner/apimock/tests/test_views.py +++ b/src/open_inwoner/apimock/tests/test_views.py @@ -5,9 +5,8 @@ class APIMockTest(TestCase): - @classmethod - def setUpTestData(cls): - cls.url = reverse( + def test_basic_response(self): + url = reverse( "apimock:mock", kwargs={ "set_name": "openklant-read", @@ -16,8 +15,7 @@ def setUpTestData(cls): }, ) - def test_basic_response(self): - response = self.client.get(self.url) + response = self.client.get(url) self.assertEqual(response.status_code, 200) data = response.json() @@ -27,3 +25,17 @@ def test_basic_response(self): url = data["results"][0]["url"] self.assertNotIn("https://klanten.nl/", url) self.assertIn("http://testserver/", url) + + def test_doctored_response_endpoint(self): + url = reverse( + "apimock:mock", + kwargs={ + "set_name": "openklant-read", + "api_name": "klanten", + # let's try to read package.json + "endpoint": "../../../../../../package", + }, + ) + response = self.client.get(url) + # status 403 if we get blocked on directory traversal + self.assertEqual(response.status_code, 403) diff --git a/src/open_inwoner/apimock/views.py b/src/open_inwoner/apimock/views.py index f7a005406d..88b8c5a0d6 100644 --- a/src/open_inwoner/apimock/views.py +++ b/src/open_inwoner/apimock/views.py @@ -1,6 +1,7 @@ import json from pathlib import Path +from django.core.exceptions import PermissionDenied from django.http import Http404, JsonResponse from django.views import View @@ -27,6 +28,7 @@ def get(self, request, *args, **kwargs): endpoint = endpoint.rstrip("/") + # grab source dir base_dir = Path(__file__).parent.resolve() base_dir /= "apis" @@ -34,7 +36,11 @@ def get(self, request, *args, **kwargs): if not api_dir.exists(): raise Http404("bad api_dir") - file_path = api_dir / (endpoint + ".json") + file_path = (api_dir / (endpoint + ".json")).resolve() + + if base_dir not in file_path.parents: + raise PermissionDenied("bad traversal") + if not file_path.exists(): raise Http404("bad endpoint")