diff --git a/.changeset/witty-walls-brake.md b/.changeset/witty-walls-brake.md new file mode 100644 index 0000000000..e9da2190bc --- /dev/null +++ b/.changeset/witty-walls-brake.md @@ -0,0 +1,5 @@ +--- +"gradio": patch +--- + +feat:Prevent paths beginning with `//` or `\\` diff --git a/gradio/route_utils.py b/gradio/route_utils.py index 2dccb5900e..25d99eb81c 100644 --- a/gradio/route_utils.py +++ b/gradio/route_utils.py @@ -581,9 +581,9 @@ def compare_passwords_securely(input_password: str, correct_password: str) -> bo def starts_with_protocol(string: str) -> bool: """This regex matches strings that start with a scheme (one or more characters not including colon, slash, or space) - followed by :// + followed by ://, or start with just // or \\ as they are interpreted as SMB paths on Windows. """ - pattern = r"^[a-zA-Z][a-zA-Z0-9+\-.]*://" + pattern = r"^(?:[a-zA-Z][a-zA-Z0-9+\-.]*://|//|\\\\)" return re.match(pattern, string) is not None diff --git a/gradio/routes.py b/gradio/routes.py index 591a30b0b8..bec55debaa 100644 --- a/gradio/routes.py +++ b/gradio/routes.py @@ -856,7 +856,8 @@ def safe_join(directory: str, path: str) -> str: if path == "": raise HTTPException(400) - + if route_utils.starts_with_protocol(path): + raise HTTPException(403) filename = posixpath.normpath(path) fullpath = os.path.join(directory, filename) if ( diff --git a/test/test_routes.py b/test/test_routes.py index 26f321663c..9867be75be 100644 --- a/test/test_routes.py +++ b/test/test_routes.py @@ -953,6 +953,9 @@ def test_compare_passwords_securely(): ("localhost:7860", False), ("localhost", False), ("C:/Users/username", False), + ("//path", True), + ("\\\\path", True), + ("/usr/bin//test", False), ], ) def test_starts_with_protocol(string, expected):