diff options
Diffstat (limited to 'pkgs/development/python-modules/sanic/22.3.2-CVE-2022-35920.patch')
-rw-r--r-- | pkgs/development/python-modules/sanic/22.3.2-CVE-2022-35920.patch | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/pkgs/development/python-modules/sanic/22.3.2-CVE-2022-35920.patch b/pkgs/development/python-modules/sanic/22.3.2-CVE-2022-35920.patch new file mode 100644 index 00000000000..694c69602c1 --- /dev/null +++ b/pkgs/development/python-modules/sanic/22.3.2-CVE-2022-35920.patch @@ -0,0 +1,141 @@ +Based on upstream 9d415e4ec63d31b3749fd540e2c2ac7c98dedcdd and +2fa28f1711a8e59c6f4d3468e9c2f8b6991188a2, adjusted to apply to +v22.3.2, raise the same exception as before and not remove any +imports. + +diff --git a/sanic/mixins/routes.py b/sanic/mixins/routes.py +index 9e2cf96..e0cf86b 100644 +--- a/sanic/mixins/routes.py ++++ b/sanic/mixins/routes.py +@@ -3,7 +3,7 @@ from contextlib import suppress + from functools import partial, wraps + from inspect import getsource, signature + from mimetypes import guess_type +-from os import path ++from os import path, sep + from pathlib import PurePath + from re import sub + from textwrap import dedent +@@ -775,23 +775,23 @@ class RouteMixin(metaclass=SanicMeta): + content_type=None, + __file_uri__=None, + ): +- # Using this to determine if the URL is trying to break out of the path +- # served. os.path.realpath seems to be very slow +- if __file_uri__ and "../" in __file_uri__: +- raise InvalidUsage("Invalid URL") + # Merge served directory and requested file if provided +- # Strip all / that in the beginning of the URL to help prevent python +- # from herping a derp and treating the uri as an absolute path +- root_path = file_path = file_or_directory ++ root_path = file_path = path.abspath(unquote(file_or_directory)) ++ + if __file_uri__: +- file_path = path.join( +- file_or_directory, sub("^[/]*", "", __file_uri__) +- ) ++ # Strip all / that in the beginning of the URL to help prevent ++ # python from herping a derp and treating the uri as an ++ # absolute path ++ unquoted_file_uri = unquote(__file_uri__).lstrip("/") ++ ++ segments = unquoted_file_uri.split("/") ++ if ".." in segments or any(sep in segment for segment in segments): ++ raise InvalidUsage("Invalid URL") ++ ++ file_path = path.join(file_or_directory, unquoted_file_uri) ++ file_path = path.abspath(file_path) + +- # URL decode the path sent by the browser otherwise we won't be able to +- # match filenames which got encoded (filenames with spaces etc) +- file_path = path.abspath(unquote(file_path)) +- if not file_path.startswith(path.abspath(unquote(root_path))): ++ if not file_path.startswith(root_path): + error_logger.exception( + f"File not found: path={file_or_directory}, " + f"relative_url={__file_uri__}" +diff --git a/tests/test_static.py b/tests/test_static.py +index 36a98e1..aeb625b 100644 +--- a/tests/test_static.py ++++ b/tests/test_static.py +@@ -1,6 +1,7 @@ + import inspect + import logging + import os ++import sys + + from collections import Counter + from pathlib import Path +@@ -8,7 +9,7 @@ from time import gmtime, strftime + + import pytest + +-from sanic import text ++from sanic import Sanic, text + from sanic.exceptions import FileNotFound + + +@@ -21,6 +22,22 @@ def static_file_directory(): + return static_directory + + ++@pytest.fixture(scope="module") ++def double_dotted_directory_file(static_file_directory: str): ++ """Generate double dotted directory and its files""" ++ if sys.platform == "win32": ++ raise Exception("Windows doesn't support double dotted directories") ++ ++ file_path = Path(static_file_directory) / "dotted.." / "dot.txt" ++ double_dotted_dir = file_path.parent ++ Path.mkdir(double_dotted_dir, exist_ok=True) ++ with open(file_path, "w") as f: ++ f.write("DOT\n") ++ yield file_path ++ Path.unlink(file_path) ++ Path.rmdir(double_dotted_dir) ++ ++ + def get_file_path(static_file_directory, file_name): + return os.path.join(static_file_directory, file_name) + +@@ -578,3 +595,40 @@ def test_resource_type_dir(app, static_file_directory): + def test_resource_type_unknown(app, static_file_directory, caplog): + with pytest.raises(ValueError): + app.static("/static", static_file_directory, resource_type="unknown") ++ ++ ++@pytest.mark.skipif( ++ sys.platform == "win32", ++ reason="Windows does not support double dotted directories", ++) ++def test_dotted_dir_ok( ++ app: Sanic, static_file_directory: str, double_dotted_directory_file: Path ++): ++ app.static("/foo", static_file_directory) ++ dot_relative_path = str( ++ double_dotted_directory_file.relative_to(static_file_directory) ++ ) ++ _, response = app.test_client.get("/foo/" + dot_relative_path) ++ assert response.status == 200 ++ assert response.body == b"DOT\n" ++ ++ ++def test_breakout(app: Sanic, static_file_directory: str): ++ app.static("/foo", static_file_directory) ++ ++ _, response = app.test_client.get("/foo/..%2Fstatic/test.file") ++ assert response.status == 400 ++ ++ ++@pytest.mark.skipif( ++ sys.platform != "win32", reason="Block backslash on Windows only" ++) ++def test_double_backslash_prohibited_on_win32( ++ app: Sanic, static_file_directory: str ++): ++ app.static("/foo", static_file_directory) ++ ++ _, response = app.test_client.get("/foo/static/..\\static/test.file") ++ assert response.status == 400 ++ _, response = app.test_client.get("/foo/static\\../static/test.file") ++ assert response.status == 400 |