!5 Fix CVE-2024-35178

From: @li_ning_jie 
Reviewed-by: @shinwell_hu 
Signed-off-by: @shinwell_hu
This commit is contained in:
openeuler-ci-bot 2024-10-25 07:15:44 +00:00 committed by Gitee
commit 929951eedf
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
2 changed files with 232 additions and 1 deletions

View File

@ -0,0 +1,227 @@
From 79fbf801c5908f4d1d9bc90004b74cfaaeeed2df Mon Sep 17 00:00:00 2001
From: Min RK <benjaminrk@gmail.com>
Date: Fri, 31 May 2024 03:27:40 +0200
Subject: [PATCH] Merge pull request from GHSA-hrw6-wg82-cm62
* filefind: avoid handling absolute paths
we don't need or want absolute path support,
which we inherited from generic ipython_genutils
only supporting relative paths lets us avoid attempting to accessing files we know we won't accept
* Apply suggestions from code review
Co-authored-by: M Bussonnier <bussonniermatthias@gmail.com>
* filefind: only accept Sequence[str]
we only call it one place, might as well be simple about it
* version_info gate for is_relative_to
* clarify docstring
Co-authored-by: Carol Willing <carolcode@willingconsulting.com>
---------
Co-authored-by: M Bussonnier <bussonniermatthias@gmail.com>
Co-authored-by: Carol Willing <carolcode@willingconsulting.com>
---
jupyter_server/utils.py | 99 +++++++++++++++++------------------------
tests/test_utils.py | 39 ++++++++++++++++
2 files changed, 81 insertions(+), 57 deletions(-)
diff --git a/jupyter_server/utils.py b/jupyter_server/utils.py
index e9225b746..9a1bd89af 100644
--- a/jupyter_server/utils.py
+++ b/jupyter_server/utils.py
@@ -11,6 +11,7 @@ import socket
import sys
import warnings
from contextlib import contextmanager
+from pathlib import Path
from typing import Any, Generator, NewType, Sequence
from urllib.parse import (
SplitResult,
@@ -338,81 +339,65 @@ def is_namespace_package(namespace: str) -> bool | None:
return isinstance(spec.submodule_search_locations, _NamespacePath)
-def filefind(filename: str, path_dirs: Sequence[str] | str | None = None) -> str:
+def filefind(filename: str, path_dirs: Sequence[str]) -> str:
"""Find a file by looking through a sequence of paths.
- This iterates through a sequence of paths looking for a file and returns
- the full, absolute path of the first occurrence of the file. If no set of
- path dirs is given, the filename is tested as is, after running through
- :func:`expandvars` and :func:`expanduser`. Thus a simple call::
- filefind("myfile.txt")
+ For use in FileFindHandler.
- will find the file in the current working dir, but::
+ Iterates through a sequence of paths looking for a file and returns
+ the full, absolute path of the first occurrence of the file.
- filefind("~/myfile.txt")
+ Absolute paths are not accepted for inputs.
- Will find the file in the users home directory. This function does not
- automatically try any paths, such as the cwd or the user's home directory.
+ This function does not automatically try any paths,
+ such as the cwd or the user's home directory.
Parameters
----------
filename : str
- The filename to look for.
- path_dirs : str, None or sequence of str
- The sequence of paths to look for the file in. If None, the filename
- need to be absolute or be in the cwd. If a string, the string is
- put into a sequence and the searched. If a sequence, walk through
- each element and join with ``filename``, calling :func:`expandvars`
- and :func:`expanduser` before testing for existence.
+ The filename to look for. Must be a relative path.
+ path_dirs : sequence of str
+ The sequence of paths to look in for the file.
+ Walk through each element and join with ``filename``.
+ Only after ensuring the path resolves within the directory is it checked for existence.
Returns
-------
- Raises :exc:`IOError` or returns absolute path to file.
+ Raises :exc:`OSError` or returns absolute path to file.
"""
-
- # If paths are quoted, abspath gets confused, strip them...
- filename = filename.strip('"').strip("'")
- # If the input is an absolute path, just check it exists
- if os.path.isabs(filename) and os.path.isfile(filename):
- return filename
-
- if path_dirs is None:
- path_dirs = ("",)
- elif isinstance(path_dirs, str):
- path_dirs = (path_dirs,)
-
- for path in path_dirs:
- if path == ".":
- path = os.getcwd() # noqa: PLW2901
- testname = expand_path(os.path.join(path, filename))
- if os.path.isfile(testname):
- return os.path.abspath(testname)
+ file_path = Path(filename)
+
+ # If the input is an absolute path, reject it
+ if file_path.is_absolute():
+ msg = f"{filename} is absolute, filefind only accepts relative paths."
+ raise OSError(msg)
+
+ for path_str in path_dirs:
+ path = Path(path_str).absolute()
+ test_path = path / file_path
+ # os.path.abspath resolves '..', but Path.absolute() doesn't
+ # Path.resolve() does, but traverses symlinks, which we don't want
+ test_path = Path(os.path.abspath(test_path))
+ if sys.version_info >= (3, 9):
+ if not test_path.is_relative_to(path):
+ # points outside root, e.g. via `filename='../foo'`
+ continue
+ else:
+ # is_relative_to is new in 3.9
+ try:
+ test_path.relative_to(path)
+ except ValueError:
+ # points outside root, e.g. via `filename='../foo'`
+ continue
+ # make sure we don't call is_file before we know it's a file within a prefix
+ # GHSA-hrw6-wg82-cm62 - can leak password hash on windows.
+ if test_path.is_file():
+ return os.path.abspath(test_path)
msg = f"File {filename!r} does not exist in any of the search paths: {path_dirs!r}"
raise OSError(msg)
-def expand_path(s: str) -> str:
- """Expand $VARS and ~names in a string, like a shell
-
- :Examples:
- In [2]: os.environ['FOO']='test'
- In [3]: expand_path('variable FOO is $FOO')
- Out[3]: 'variable FOO is test'
- """
- # This is a pretty subtle hack. When expand user is given a UNC path
- # on Windows (\\server\share$\%username%), os.path.expandvars, removes
- # the $ to get (\\server\share\%username%). I think it considered $
- # alone an empty var. But, we need the $ to remains there (it indicates
- # a hidden share).
- if os.name == "nt":
- s = s.replace("$\\", "IPYTHON_TEMP")
- s = os.path.expandvars(os.path.expanduser(s))
- if os.name == "nt":
- s = s.replace("IPYTHON_TEMP", "$\\")
- return s
-
-
def import_item(name: str) -> Any:
"""Import and return ``bar`` given the string ``foo.bar``.
Calling ``bar = import_item("foo.bar")`` is the functional equivalent of
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 83d2a1d92..fdbfd6058 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -13,6 +13,7 @@ from traitlets.tests.utils import check_help_all_output
from jupyter_server.utils import (
check_pid,
check_version,
+ filefind,
is_namespace_package,
path2url,
run_sync_in_loop,
@@ -125,3 +126,41 @@ def test_unix_socket_in_use(tmp_path):
sock.listen(0)
assert unix_socket_in_use(server_address)
sock.close()
+
+
+@pytest.mark.parametrize(
+ "filename, result",
+ [
+ ("/foo", OSError),
+ ("../c/in-c", OSError),
+ ("in-a", "a/in-a"),
+ ("in-b", "b/in-b"),
+ ("in-both", "a/in-both"),
+ (r"\in-a", OSError),
+ ("not-found", OSError),
+ ],
+)
+def test_filefind(tmp_path, filename, result):
+ a = tmp_path / "a"
+ a.mkdir()
+ b = tmp_path / "b"
+ b.mkdir()
+ c = tmp_path / "c"
+ c.mkdir()
+ for parent in (a, b):
+ with parent.joinpath("in-both").open("w"):
+ pass
+ with a.joinpath("in-a").open("w"):
+ pass
+ with b.joinpath("in-b").open("w"):
+ pass
+ with c.joinpath("in-c").open("w"):
+ pass
+
+ if isinstance(result, str):
+ found = filefind(filename, [str(a), str(b)])
+ found_relative = Path(found).relative_to(tmp_path)
+ assert str(found_relative) == result
+ else:
+ with pytest.raises(result):
+ filefind(filename, [str(a), str(b)])
--
2.42.0.windows.2

View File

@ -1,12 +1,13 @@
Name: python-jupyter-server Name: python-jupyter-server
Version: 2.13.0 Version: 2.13.0
Release: 1 Release: 2
Summary: The backend for Jupyter web applications Summary: The backend for Jupyter web applications
License: BSD-3-Clause License: BSD-3-Clause
URL: https://pypi.org/project/jupyter-server/#files URL: https://pypi.org/project/jupyter-server/#files
Source0: %{url}/archive/%{version}/jupyter_server-%{version}.tar.gz Source0: %{url}/archive/%{version}/jupyter_server-%{version}.tar.gz
Patch1: 0001-modify-the-version-limit-for-jupyter-core.patch Patch1: 0001-modify-the-version-limit-for-jupyter-core.patch
Patch3000: backport-CVE-2024-35178-GHSA-hrw6-wg82-cm62.patch
BuildArch: noarch BuildArch: noarch
%global _description %{expand: %global _description %{expand:
@ -46,6 +47,9 @@ BuildRequires: python3-hatch-jupyter-builder
%{python3_sitelib}/jupyter_server/ %{python3_sitelib}/jupyter_server/
%changelog %changelog
* Fri Oct 25 2024 liningjie <liningjie@xfusion.com> - 2.13.0-2
- Fix CVE-2024-35178
* Wed Mar 6 2024 Dongxing Wang <dongxing.wang_a@thundersoft.com> - 2.13.0-1 * Wed Mar 6 2024 Dongxing Wang <dongxing.wang_a@thundersoft.com> - 2.13.0-1
- Update package with version 2.13.0 - Update package with version 2.13.0
Add an option to have authentication enabled for all endpoints by default Add an option to have authentication enabled for all endpoints by default