1
0
mirror of https://github.com/hanxi/xiaomusic.git synced 2026-05-02 23:39:51 +08:00

fix(security): path traversal bypass in safe_join_path prefix c (#820)

The path safety check uses `normalized_directory.startswith(os.path.normpath(safe_root))`, which can be bypassed by sibling paths sharing the same prefix (e.g., `/safe/root2` starts with `/safe/root`). This may permit access outside the intended root.

Affected files: file_utils.py

Signed-off-by: tuanaiseo <221258316+tuanaiseo@users.noreply.github.com>
This commit is contained in:
tuanaiseo
2026-04-07 08:32:25 +07:00
committed by GitHub
parent 97879f512f
commit 178797fd91

View File

@@ -83,13 +83,15 @@ def safe_join_path(safe_root: str, directory: str) -> str:
Raises:
ValueError: 如果路径不在安全根目录内
"""
directory = os.path.join(safe_root, directory)
# Normalize the directory path
normalized_directory = os.path.normpath(directory)
# Ensure the directory is within the safe root
if not normalized_directory.startswith(os.path.normpath(safe_root)):
raise ValueError(f"Access to directory '{directory}' is not allowed.")
return normalized_directory
joined_path = os.path.join(safe_root, directory)
real_safe_root = os.path.realpath(safe_root)
real_directory = os.path.realpath(joined_path)
try:
if os.path.commonpath([real_directory, real_safe_root]) != real_safe_root:
raise ValueError(f"Access to directory '{joined_path}' is not allowed.")
except ValueError as e:
raise ValueError(f"Access to directory '{joined_path}' is not allowed.") from e
return real_directory
def _longest_common_prefix(file_names: list) -> str: