tangled
alpha
login
or
join now
pyrox.dev
/
nixpkgs
0
fork
atom
lol
0
fork
atom
overview
issues
pulls
pipelines
python310Packages.sanic: 22.3.2 -> 22.6.2
Jonas Heinrich
3 years ago
3149b6ff
2da64a81
+7
-157
2 changed files
expand all
collapse all
unified
split
pkgs
development
python-modules
sanic
22.3.2-CVE-2022-35920.patch
default.nix
-141
pkgs/development/python-modules/sanic/22.3.2-CVE-2022-35920.patch
···
1
-
Based on upstream 9d415e4ec63d31b3749fd540e2c2ac7c98dedcdd and
2
-
2fa28f1711a8e59c6f4d3468e9c2f8b6991188a2, adjusted to apply to
3
-
v22.3.2, raise the same exception as before and not remove any
4
-
imports.
5
-
6
-
diff --git a/sanic/mixins/routes.py b/sanic/mixins/routes.py
7
-
index 9e2cf96..e0cf86b 100644
8
-
--- a/sanic/mixins/routes.py
9
-
+++ b/sanic/mixins/routes.py
10
-
@@ -3,7 +3,7 @@ from contextlib import suppress
11
-
from functools import partial, wraps
12
-
from inspect import getsource, signature
13
-
from mimetypes import guess_type
14
-
-from os import path
15
-
+from os import path, sep
16
-
from pathlib import PurePath
17
-
from re import sub
18
-
from textwrap import dedent
19
-
@@ -775,23 +775,23 @@ class RouteMixin(metaclass=SanicMeta):
20
-
content_type=None,
21
-
__file_uri__=None,
22
-
):
23
-
- # Using this to determine if the URL is trying to break out of the path
24
-
- # served. os.path.realpath seems to be very slow
25
-
- if __file_uri__ and "../" in __file_uri__:
26
-
- raise InvalidUsage("Invalid URL")
27
-
# Merge served directory and requested file if provided
28
-
- # Strip all / that in the beginning of the URL to help prevent python
29
-
- # from herping a derp and treating the uri as an absolute path
30
-
- root_path = file_path = file_or_directory
31
-
+ root_path = file_path = path.abspath(unquote(file_or_directory))
32
-
+
33
-
if __file_uri__:
34
-
- file_path = path.join(
35
-
- file_or_directory, sub("^[/]*", "", __file_uri__)
36
-
- )
37
-
+ # Strip all / that in the beginning of the URL to help prevent
38
-
+ # python from herping a derp and treating the uri as an
39
-
+ # absolute path
40
-
+ unquoted_file_uri = unquote(__file_uri__).lstrip("/")
41
-
+
42
-
+ segments = unquoted_file_uri.split("/")
43
-
+ if ".." in segments or any(sep in segment for segment in segments):
44
-
+ raise InvalidUsage("Invalid URL")
45
-
+
46
-
+ file_path = path.join(file_or_directory, unquoted_file_uri)
47
-
+ file_path = path.abspath(file_path)
48
-
49
-
- # URL decode the path sent by the browser otherwise we won't be able to
50
-
- # match filenames which got encoded (filenames with spaces etc)
51
-
- file_path = path.abspath(unquote(file_path))
52
-
- if not file_path.startswith(path.abspath(unquote(root_path))):
53
-
+ if not file_path.startswith(root_path):
54
-
error_logger.exception(
55
-
f"File not found: path={file_or_directory}, "
56
-
f"relative_url={__file_uri__}"
57
-
diff --git a/tests/test_static.py b/tests/test_static.py
58
-
index 36a98e1..aeb625b 100644
59
-
--- a/tests/test_static.py
60
-
+++ b/tests/test_static.py
61
-
@@ -1,6 +1,7 @@
62
-
import inspect
63
-
import logging
64
-
import os
65
-
+import sys
66
-
67
-
from collections import Counter
68
-
from pathlib import Path
69
-
@@ -8,7 +9,7 @@ from time import gmtime, strftime
70
-
71
-
import pytest
72
-
73
-
-from sanic import text
74
-
+from sanic import Sanic, text
75
-
from sanic.exceptions import FileNotFound
76
-
77
-
78
-
@@ -21,6 +22,22 @@ def static_file_directory():
79
-
return static_directory
80
-
81
-
82
-
+@pytest.fixture(scope="module")
83
-
+def double_dotted_directory_file(static_file_directory: str):
84
-
+ """Generate double dotted directory and its files"""
85
-
+ if sys.platform == "win32":
86
-
+ raise Exception("Windows doesn't support double dotted directories")
87
-
+
88
-
+ file_path = Path(static_file_directory) / "dotted.." / "dot.txt"
89
-
+ double_dotted_dir = file_path.parent
90
-
+ Path.mkdir(double_dotted_dir, exist_ok=True)
91
-
+ with open(file_path, "w") as f:
92
-
+ f.write("DOT\n")
93
-
+ yield file_path
94
-
+ Path.unlink(file_path)
95
-
+ Path.rmdir(double_dotted_dir)
96
-
+
97
-
+
98
-
def get_file_path(static_file_directory, file_name):
99
-
return os.path.join(static_file_directory, file_name)
100
-
101
-
@@ -578,3 +595,40 @@ def test_resource_type_dir(app, static_file_directory):
102
-
def test_resource_type_unknown(app, static_file_directory, caplog):
103
-
with pytest.raises(ValueError):
104
-
app.static("/static", static_file_directory, resource_type="unknown")
105
-
+
106
-
+
107
-
+@pytest.mark.skipif(
108
-
+ sys.platform == "win32",
109
-
+ reason="Windows does not support double dotted directories",
110
-
+)
111
-
+def test_dotted_dir_ok(
112
-
+ app: Sanic, static_file_directory: str, double_dotted_directory_file: Path
113
-
+):
114
-
+ app.static("/foo", static_file_directory)
115
-
+ dot_relative_path = str(
116
-
+ double_dotted_directory_file.relative_to(static_file_directory)
117
-
+ )
118
-
+ _, response = app.test_client.get("/foo/" + dot_relative_path)
119
-
+ assert response.status == 200
120
-
+ assert response.body == b"DOT\n"
121
-
+
122
-
+
123
-
+def test_breakout(app: Sanic, static_file_directory: str):
124
-
+ app.static("/foo", static_file_directory)
125
-
+
126
-
+ _, response = app.test_client.get("/foo/..%2Fstatic/test.file")
127
-
+ assert response.status == 400
128
-
+
129
-
+
130
-
+@pytest.mark.skipif(
131
-
+ sys.platform != "win32", reason="Block backslash on Windows only"
132
-
+)
133
-
+def test_double_backslash_prohibited_on_win32(
134
-
+ app: Sanic, static_file_directory: str
135
-
+):
136
-
+ app.static("/foo", static_file_directory)
137
-
+
138
-
+ _, response = app.test_client.get("/foo/static/..\\static/test.file")
139
-
+ assert response.status == 400
140
-
+ _, response = app.test_client.get("/foo/static\\../static/test.file")
141
-
+ assert response.status == 400
···
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
+7
-16
pkgs/development/python-modules/sanic/default.nix
···
20
, uvicorn
21
, uvloop
22
, websockets
0
23
}:
24
25
buildPythonPackage rec {
26
pname = "sanic";
27
-
version = "22.3.2";
28
format = "setuptools";
29
30
disabled = pythonOlder "3.7";
···
33
owner = "sanic-org";
34
repo = pname;
35
rev = "v${version}";
36
-
hash = "sha256-4zdPp3X22dfZ5YlW3G5/OqeUxrt+NiFO9dk2XjEKXEg=";
37
};
38
39
-
patches = [
40
-
./22.3.2-CVE-2022-35920.patch
41
-
];
42
-
43
-
postPatch = ''
44
-
# Loosen dependency requirements.
45
-
substituteInPlace setup.py \
46
-
--replace "pytest==6.2.5" "pytest" \
47
-
--replace "gunicorn==20.0.4" "gunicorn"
48
-
'';
49
-
50
propagatedBuildInputs = [
51
aiofiles
0
52
httptools
53
multidict
54
sanic-routing
···
88
];
89
90
disabledTests = [
0
0
91
# Fails to parse cmdline arguments
92
"test_dev"
93
"test_auto_reload"
···
130
# for the same local port
131
__darwinAllowLocalNetworking = true;
132
133
-
pythonImportsCheck = [
134
-
"sanic"
135
-
];
136
137
meta = with lib; {
138
broken = stdenv.isDarwin;
···
20
, uvicorn
21
, uvloop
22
, websockets
23
+
, aioquic
24
}:
25
26
buildPythonPackage rec {
27
pname = "sanic";
28
+
version = "22.6.2";
29
format = "setuptools";
30
31
disabled = pythonOlder "3.7";
···
34
owner = "sanic-org";
35
repo = pname;
36
rev = "v${version}";
37
+
hash = "sha256-krEQd0ak9Uua+r+pYmLStlizgE4HmZBO8Q0I2/gWAwU=";
38
};
39
0
0
0
0
0
0
0
0
0
0
0
40
propagatedBuildInputs = [
41
aiofiles
42
+
aioquic
43
httptools
44
multidict
45
sanic-routing
···
79
];
80
81
disabledTests = [
82
+
# Require networking
83
+
"test_full_message"
84
# Fails to parse cmdline arguments
85
"test_dev"
86
"test_auto_reload"
···
123
# for the same local port
124
__darwinAllowLocalNetworking = true;
125
126
+
pythonImportsCheck = [ "sanic" ];
0
0
127
128
meta = with lib; {
129
broken = stdenv.isDarwin;