rename unvalidated paths from unsafe to unvalidated
This commit is contained in:
parent
ef497b8fdd
commit
8367c40b90
1 changed files with 22 additions and 22 deletions
|
|
@ -115,47 +115,47 @@ _WINDOWS_RESERVED_NAMES = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def is_path_safe(unsafe_path_string: str) -> bool:
|
def is_path_safe(unvalidated_path: str) -> bool:
|
||||||
"""Check if a file path has any unsafe elements in it.
|
"""Check if a file path has any unsafe elements in it.
|
||||||
|
|
||||||
The path is not coerced into a safe form because if we ask
|
The path is not coerced into a safe form because if we ask
|
||||||
for a file to be written to a location we shouldn't be changing
|
for a file to be written to a location we shouldn't be changing
|
||||||
that location as we have no "consent" to write to this other location.
|
that location as we have no "consent" to write to this other location.
|
||||||
|
|
||||||
:param unsafe_path_string: The original path string to sanitise.
|
:param unvalidated_path: The original path string to sanitise.
|
||||||
|
|
||||||
:returns: A boolean indicating if any unsafe features were found.
|
:returns: A boolean indicating if any unsafe features were found.
|
||||||
"""
|
"""
|
||||||
return all(
|
return all(
|
||||||
[
|
[
|
||||||
_path_normalised(unsafe_path_string),
|
_path_normalised(unvalidated_path),
|
||||||
_no_trailing_dots_or_whitespaces(unsafe_path_string),
|
_no_trailing_dots_or_whitespaces(unvalidated_path),
|
||||||
_no_unsafe_characters(unsafe_path_string),
|
_no_unsafe_characters(unvalidated_path),
|
||||||
_no_reserved_name(unsafe_path_string),
|
_no_reserved_name(unvalidated_path),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _path_normalised(unsafe_path_string: str) -> bool:
|
def _path_normalised(unvalidated_path: str) -> bool:
|
||||||
"""Check that the path starts normalised.
|
"""Check that the path starts normalised.
|
||||||
|
|
||||||
Warn and return false if . or .. is not at the start of the path.
|
Warn and return false if . or .. is not at the start of the path.
|
||||||
"""
|
"""
|
||||||
original_path = unsafe_path_string
|
original_path = unvalidated_path
|
||||||
# Ensure correct path separators before normalisation:
|
# Ensure correct path separators before normalisation:
|
||||||
if sys.platform.startswith("win"):
|
if sys.platform.startswith("win"):
|
||||||
unsafe_path_string = unsafe_path_string.replace("/", "\\")
|
unvalidated_path = unvalidated_path.replace("/", "\\")
|
||||||
normalised = os.path.normpath(unsafe_path_string)
|
normalised = os.path.normpath(unvalidated_path)
|
||||||
|
|
||||||
# Allow starting with ./ (or .\ on Windows)
|
# Allow starting with ./ (or .\ on Windows)
|
||||||
if unsafe_path_string.startswith("." + os.path.sep):
|
if unvalidated_path.startswith("." + os.path.sep):
|
||||||
normalised = "." + os.path.sep + normalised
|
normalised = "." + os.path.sep + normalised
|
||||||
|
|
||||||
# Allow trailing path separator
|
# Allow trailing path separator
|
||||||
if unsafe_path_string.endswith(os.path.sep):
|
if unvalidated_path.endswith(os.path.sep):
|
||||||
normalised += os.path.sep
|
normalised += os.path.sep
|
||||||
|
|
||||||
if normalised != unsafe_path_string:
|
if normalised != unvalidated_path:
|
||||||
LOGGER.warning(
|
LOGGER.warning(
|
||||||
f"File path {original_path} may be unsafe due to unexpected relative "
|
f"File path {original_path} may be unsafe due to unexpected relative "
|
||||||
"navigation."
|
"navigation."
|
||||||
|
|
@ -164,18 +164,18 @@ def _path_normalised(unsafe_path_string: str) -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def _no_trailing_dots_or_whitespaces(unsafe_path_string: str) -> bool:
|
def _no_trailing_dots_or_whitespaces(unvalidated_path: str) -> bool:
|
||||||
"""Disallow trailing dots or whitespace."""
|
"""Disallow trailing dots or whitespace."""
|
||||||
# Use PurePath from Python's standard library to iterate over each element
|
# Use PurePath from Python's standard library to iterate over each element
|
||||||
# in the path as separated by path separators. For example:
|
# in the path as separated by path separators. For example:
|
||||||
# "foo/bar/tada.py" -> ("foo", "bar", "tada.py")
|
# "foo/bar/tada.py" -> ("foo", "bar", "tada.py")
|
||||||
for component in PurePath(unsafe_path_string).parts:
|
for component in PurePath(unvalidated_path).parts:
|
||||||
if component == "..":
|
if component == "..":
|
||||||
continue
|
continue
|
||||||
bad_trailing_chars = ". " if sys.platform.startswith("win") else "."
|
bad_trailing_chars = ". " if sys.platform.startswith("win") else "."
|
||||||
if component.rstrip(bad_trailing_chars) != component:
|
if component.rstrip(bad_trailing_chars) != component:
|
||||||
LOGGER.warning(
|
LOGGER.warning(
|
||||||
f"File path {unsafe_path_string} may be unsafe due to trailing dots "
|
f"File path {unvalidated_path} may be unsafe due to trailing dots "
|
||||||
"or whitespace."
|
"or whitespace."
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
@ -183,12 +183,12 @@ def _no_trailing_dots_or_whitespaces(unsafe_path_string: str) -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def _no_unsafe_characters(unsafe_path_string: str) -> bool:
|
def _no_unsafe_characters(unvalidated_path: str) -> bool:
|
||||||
"""Disallow unsafe characters."""
|
"""Disallow unsafe characters."""
|
||||||
for component in PurePath(unsafe_path_string).parts:
|
for component in PurePath(unvalidated_path).parts:
|
||||||
if UNSAFE_PATTERN.search(component):
|
if UNSAFE_PATTERN.search(component):
|
||||||
LOGGER.warning(
|
LOGGER.warning(
|
||||||
f"{unsafe_path_string} contains characters that may be unsafe on this "
|
f"{unvalidated_path} contains characters that may be unsafe on this "
|
||||||
"platform."
|
"platform."
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
@ -196,12 +196,12 @@ def _no_unsafe_characters(unsafe_path_string: str) -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def _no_reserved_name(unsafe_path_string: str) -> bool:
|
def _no_reserved_name(unvalidated_path: str) -> bool:
|
||||||
"""Disallow use of Windows reserved names (e.g., CON, PRN, LPT1)."""
|
"""Disallow use of Windows reserved names (e.g., CON, PRN, LPT1)."""
|
||||||
for component in PurePath(unsafe_path_string).parts:
|
for component in PurePath(unvalidated_path).parts:
|
||||||
if _sanitise_reserved(component, is_filename=False) != component:
|
if _sanitise_reserved(component, is_filename=False) != component:
|
||||||
LOGGER.warning(
|
LOGGER.warning(
|
||||||
f"{unsafe_path_string} contains a reserved system name and may cause "
|
f"{unvalidated_path} contains a reserved system name and may cause "
|
||||||
"issues."
|
"issues."
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue