API Reference¶
Main Functions¶
A Python package to identify potentially dangerous file paths.
This package provides functions to test whether a supplied file path points to a system-sensitive location, taking into account different OS platforms. The package includes platform-specific checkers for Windows, macOS (Darwin), and POSIX systems, along with support for user-defined sensitive paths.
- class bad_path.PathChecker(path: str | Path, raise_error: bool = False, mode: str | None = None, system_ok: bool = False, user_paths_ok: bool = False, not_writeable: bool = False, cwd_only: bool = False)[source]¶
Bases:
objectA class to check if a path is dangerous and provide details about why.
This is a factory that creates platform-specific PathChecker instances based on the current operating system.
The class can be used in boolean context where it evaluates to True if the path is safe (not dangerous), False otherwise.
The class distinguishes between platform-specific system paths and user-defined sensitive paths through separate properties.
- Parameters:
path (str | Path) – The file path to check.
- Keyword Parameters:
- raise_error (bool):
If True, raise DangerousPathError if the path is dangerous. Defaults to False.
- mode (str | None):
Validation mode for common use cases: “read”, “write”, or None. Use “read” when validating paths for read operations (allows reading from system directories and user-defined paths). Use “write” when validating paths for write operations (strict validation to prevent overwriting critical files). Use None to manually control validation via individual flags. When mode is specified, it overrides the system_ok, user_paths_ok, and not_writeable flags. Defaults to None.
- system_ok (bool):
If True, allow paths within system directories. Defaults to False.
- user_paths_ok (bool):
If True, allow paths within user-defined sensitive locations. Defaults to False.
- not_writeable (bool):
If True, allow paths that are readable but not writeable. Defaults to False.
- cwd_only (bool):
If True, only allow paths within the current working directory to prevent path traversal attacks. Paths that resolve outside the CWD (e.g., ‘../../../etc/passwd’) are considered dangerous. Defaults to False.
- Raises:
DangerousPathError – If raise_error is True and the path is dangerous.
ValueError – If mode is not None, “read”, or “write”.
Notes
When mode is specified, individual flag parameters (system_ok, user_paths_ok, not_writeable) are ignored in favour of the mode’s preset values.
Examples
>>> # Default strict validation - dangerous for system paths >>> checker = PathChecker("/etc/passwd") >>> if not checker: ... print(f"Dangerous path! System path: {checker.is_system_path}") Dangerous path! System path: True >>> # Read mode - convenient for validating read operations >>> checker = PathChecker("/etc/passwd", mode="read") >>> if checker: ... print("Safe to read from this path!") Safe to read from this path! >>> # Write mode - strict validation to prevent overwriting critical files >>> checker = PathChecker("/tmp/myfile.txt", mode="write") >>> if checker: ... print("Safe to write to this path!") Safe to write to this path! >>> # Manual flag control (backward compatible) >>> checker = PathChecker( ... "/etc/passwd", system_ok=True, not_writeable=True ... ) >>> if checker: ... print("Safe with custom flags!") Safe with custom flags! >>> # Path traversal protection >>> checker = PathChecker("../../../etc/passwd", cwd_only=True) >>> if not checker: ... print("Dangerous: path traversal attempt detected!") Dangerous: path traversal attempt detected!
- bad_path.is_dangerous_path(path: str | Path, raise_error: bool = False) bool[source]¶
Check if a path is dangerous (points to a system-sensitive location).
- Parameters:
path (str | Path) – The file path to check.
- Keyword Parameters:
- raise_error (bool):
If True, raise DangerousPathError instead of returning True. Defaults to False.
- Returns:
True if the path is dangerous, False otherwise.
- Return type:
(bool)
- Raises:
DangerousPathError – If raise_error is True and the path is dangerous.
Examples
>>> is_dangerous_path("/home/user/file.txt") False >>> is_dangerous_path("/etc/passwd") # On POSIX systems True >>> is_dangerous_path("/etc/passwd", raise_error=True) Traceback (most recent call last): ... DangerousPathError: Path '/etc/passwd' points to a dangerous system location
- bad_path.is_system_path(path: str | Path) bool[source]¶
Check if a path is within a system directory.
- Parameters:
path (str | Path) – The file path to check.
- Returns:
True if the path is within a system directory, False otherwise.
- Return type:
(bool)
Notes
Despite the name, this function checks BOTH system paths and user-defined paths for backward compatibility (originally used get_dangerous_paths() which returns both). Use PathChecker class for fine-grained control.
Examples
>>> is_system_path("/etc/passwd") # On POSIX systems True >>> is_system_path("/home/user/file.txt") False
- bad_path.is_sensitive_path(path: str | Path) bool[source]¶
Check if a path points to a sensitive location.
This is an alias for is_system_path() for backwards compatibility and semantic clarity.
- Parameters:
path (str | Path) – The file path to check.
- Returns:
True if the path is sensitive, False otherwise.
- Return type:
(bool)
Notes
This function checks BOTH system and user-defined paths (same as is_system_path) for backward compatibility. Use PathChecker class for fine-grained control.
Examples
>>> is_sensitive_path("/etc/passwd") # On POSIX systems True >>> add_user_path("/custom/sensitive") >>> is_sensitive_path("/custom/sensitive/file.txt") True
- bad_path.get_dangerous_paths() list[str][source]¶
Get a list of dangerous and sensitive paths based on the current OS.
Includes both platform-specific system paths and user-defined paths.
- Returns:
List of dangerous path patterns for the current operating system, combined with user-defined paths (duplicates removed).
- Return type:
Examples
>>> paths = get_dangerous_paths() >>> any("/etc" in p or "etc" in p for p in paths) # POSIX/Darwin True >>> add_user_path("/custom/path") >>> "/custom/path" in get_dangerous_paths() True
- exception bad_path.DangerousPathError[source]¶
Bases:
PermissionErrorException raised when a dangerous path is detected.
- bad_path.add_user_path(path: str | Path) None[source]¶
Add a user-defined path to the list of dangerous paths.
- Parameters:
path (str | Path) – The path to add as a dangerous location.
Examples
>>> add_user_path("/home/user/sensitive") >>> add_user_path(Path("/var/app/data"))
- bad_path.remove_user_path(path: str | Path) None[source]¶
Remove a user-defined path from the list of dangerous paths.
- Parameters:
path (str | Path) – The path to remove from the dangerous locations list.
- Raises:
ValueError – If the path is not in the user-defined paths list.
Examples
>>> add_user_path("/home/user/sensitive") >>> remove_user_path("/home/user/sensitive")
- bad_path.clear_user_paths() None[source]¶
Clear all user-defined dangerous paths.
Examples
>>> add_user_path("/home/user/sensitive") >>> clear_user_paths() >>> get_user_paths() []
Checker Module¶
Core functionality for checking dangerous file paths.
This module provides the main PathChecker class and supporting functions for identifying dangerous or sensitive file paths. It includes platform-specific implementations for Windows, macOS (Darwin), and POSIX systems, along with support for user-defined paths and validation of platform-specific invalid characters.
- exception bad_path.checker.DangerousPathError[source]¶
Bases:
PermissionErrorException raised when a dangerous path is detected.
- bad_path.checker.add_user_path(path: str | Path) None[source]¶
Add a user-defined path to the list of dangerous paths.
- Parameters:
path (str | Path) – The path to add as a dangerous location.
Examples
>>> add_user_path("/home/user/sensitive") >>> add_user_path(Path("/var/app/data"))
- bad_path.checker.remove_user_path(path: str | Path) None[source]¶
Remove a user-defined path from the list of dangerous paths.
- Parameters:
path (str | Path) – The path to remove from the dangerous locations list.
- Raises:
ValueError – If the path is not in the user-defined paths list.
Examples
>>> add_user_path("/home/user/sensitive") >>> remove_user_path("/home/user/sensitive")
- bad_path.checker.clear_user_paths() None[source]¶
Clear all user-defined dangerous paths.
Examples
>>> add_user_path("/home/user/sensitive") >>> clear_user_paths() >>> get_user_paths() []
- bad_path.checker.get_user_paths() list[str][source]¶
Get the list of user-defined dangerous paths.
Examples
>>> add_user_path("/home/user/sensitive") >>> paths = get_user_paths() >>> "/home/user/sensitive" in paths True
- bad_path.checker.get_dangerous_paths() list[str][source]¶
Get a list of dangerous and sensitive paths based on the current OS.
Includes both platform-specific system paths and user-defined paths.
- Returns:
List of dangerous path patterns for the current operating system, combined with user-defined paths (duplicates removed).
- Return type:
Examples
>>> paths = get_dangerous_paths() >>> any("/etc" in p or "etc" in p for p in paths) # POSIX/Darwin True >>> add_user_path("/custom/path") >>> "/custom/path" in get_dangerous_paths() True
- bad_path.checker.is_system_path(path: str | Path) bool[source]¶
Check if a path is within a system directory.
- Parameters:
path (str | Path) – The file path to check.
- Returns:
True if the path is within a system directory, False otherwise.
- Return type:
(bool)
Notes
Despite the name, this function checks BOTH system paths and user-defined paths for backward compatibility (originally used get_dangerous_paths() which returns both). Use PathChecker class for fine-grained control.
Examples
>>> is_system_path("/etc/passwd") # On POSIX systems True >>> is_system_path("/home/user/file.txt") False
- bad_path.checker.is_sensitive_path(path: str | Path) bool[source]¶
Check if a path points to a sensitive location.
This is an alias for is_system_path() for backwards compatibility and semantic clarity.
- Parameters:
path (str | Path) – The file path to check.
- Returns:
True if the path is sensitive, False otherwise.
- Return type:
(bool)
Notes
This function checks BOTH system and user-defined paths (same as is_system_path) for backward compatibility. Use PathChecker class for fine-grained control.
Examples
>>> is_sensitive_path("/etc/passwd") # On POSIX systems True >>> add_user_path("/custom/sensitive") >>> is_sensitive_path("/custom/sensitive/file.txt") True
- bad_path.checker.is_dangerous_path(path: str | Path, raise_error: bool = False) bool[source]¶
Check if a path is dangerous (points to a system-sensitive location).
- Parameters:
path (str | Path) – The file path to check.
- Keyword Parameters:
- raise_error (bool):
If True, raise DangerousPathError instead of returning True. Defaults to False.
- Returns:
True if the path is dangerous, False otherwise.
- Return type:
(bool)
- Raises:
DangerousPathError – If raise_error is True and the path is dangerous.
Examples
>>> is_dangerous_path("/home/user/file.txt") False >>> is_dangerous_path("/etc/passwd") # On POSIX systems True >>> is_dangerous_path("/etc/passwd", raise_error=True) Traceback (most recent call last): ... DangerousPathError: Path '/etc/passwd' points to a dangerous system location
- class bad_path.checker.BasePathChecker(path: str | Path, raise_error: bool = False, mode: str | None = None, system_ok: bool = False, user_paths_ok: bool = False, not_writeable: bool = False, cwd_only: bool = False)[source]¶
Bases:
ABCBase class for platform-specific path checkers.
A class to check if a path is dangerous and provide details about why. The class can be used in boolean context where it evaluates to True if the path is safe (not dangerous), False otherwise.
The class distinguishes between platform-specific system paths and user-defined sensitive paths through separate properties.
- Parameters:
path (str | Path) – The file path to check.
- Keyword Parameters:
- raise_error (bool):
If True, raise DangerousPathError if the path is dangerous. Defaults to False.
- mode (str | None):
Validation mode for common use cases: “read”, “write”, or None. Use “read” when validating paths for read operations (allows reading from system directories and user-defined paths). Use “write” when validating paths for write operations (strict validation to prevent overwriting critical files). Use None to manually control validation via individual flags. When mode is specified, it overrides the system_ok, user_paths_ok, and not_writeable flags. Defaults to None.
- system_ok (bool):
If True, allow paths within system directories. Defaults to False.
- user_paths_ok (bool):
If True, allow paths within user-defined sensitive locations. Defaults to False.
- not_writeable (bool):
If True, allow paths that are readable but not writeable. Defaults to False.
- cwd_only (bool):
If True, only allow paths within the current working directory to prevent path traversal attacks. Paths that resolve outside the CWD (e.g., ‘../../../etc/passwd’) are considered dangerous. Defaults to False.
- Raises:
DangerousPathError – If raise_error is True and the path is dangerous.
ValueError – If mode is not None, “read”, or “write”.
Notes
When mode is specified, individual flag parameters (system_ok, user_paths_ok, not_writeable) are ignored in favour of the mode’s preset values.
Examples
>>> # Strict validation (default) - dangerous for system paths >>> checker = PathChecker("/etc/passwd") >>> if not checker: ... print(f"Dangerous path! System path: {checker.is_system_path}") Dangerous path! System path: True >>> # Read mode - allow reading system configuration files >>> checker = PathChecker("/etc/passwd", mode="read") >>> if checker: ... print("Safe for reading!") Safe for reading! >>> # Write mode - strict validation to prevent overwriting >>> checker = PathChecker("/tmp/myfile.txt", mode="write") >>> if checker: ... print("Safe for writing!") Safe for writing!
- __init__(path: str | Path, raise_error: bool = False, mode: str | None = None, system_ok: bool = False, user_paths_ok: bool = False, not_writeable: bool = False, cwd_only: bool = False)[source]¶
Initialise the PathChecker with a path to check.
- property is_system_path: bool¶
Check if the path is within a platform-specific system directory.
This checks against OS-specific dangerous paths like /etc, /bin on Linux/Unix, C:Windows on Windows, or /System on macOS.
- Returns:
True if the path is within a platform system directory, False otherwise.
- Return type:
(bool)
- property is_sensitive_path: bool¶
Check if the path matches a user-defined sensitive location.
This checks against paths added by the user via add_user_path().
- Returns:
True if the path matches a user-defined sensitive path, False otherwise.
- Return type:
(bool)
- property path: str | Path¶
Get the original path that was checked.
- Returns:
The original path supplied to the constructor.
- Return type:
(str | Path)
- property has_invalid_chars: bool¶
Check if the path contains invalid characters for the current platform.
This checks for platform-specific invalid characters (e.g., <, >, :, “, etc. on Windows, null byte on POSIX systems, colon on macOS). Also checks for reserved names on Windows.
- Returns:
True if the path contains invalid characters, False otherwise.
- Return type:
(bool)
- property is_readable: bool¶
Check if the path is accessible for read operations.
For existing files and directories, checks read permission. For non-existing paths, returns False.
- Returns:
True if the path exists and is readable, False otherwise.
- Return type:
(bool)
- property is_writable: bool¶
Check if the path is accessible for write operations.
For existing files and directories, checks write permission. For non-existing paths, returns False (use is_creatable instead).
- Returns:
True if the path exists and is writable, False otherwise.
- Return type:
(bool)
- property is_creatable: bool¶
Check if the path can be created (for non-existing paths).
For non-existing paths, checks if the parent directory exists and is writable. For existing paths, returns False (use is_writable instead).
- Returns:
True if the path doesn’t exist and can be created, False otherwise.
- Return type:
(bool)
- class bad_path.checker.PathChecker(path: str | Path, raise_error: bool = False, mode: str | None = None, system_ok: bool = False, user_paths_ok: bool = False, not_writeable: bool = False, cwd_only: bool = False)[source]¶
Bases:
objectA class to check if a path is dangerous and provide details about why.
This is a factory that creates platform-specific PathChecker instances based on the current operating system.
The class can be used in boolean context where it evaluates to True if the path is safe (not dangerous), False otherwise.
The class distinguishes between platform-specific system paths and user-defined sensitive paths through separate properties.
- Parameters:
path (str | Path) – The file path to check.
- Keyword Parameters:
- raise_error (bool):
If True, raise DangerousPathError if the path is dangerous. Defaults to False.
- mode (str | None):
Validation mode for common use cases: “read”, “write”, or None. Use “read” when validating paths for read operations (allows reading from system directories and user-defined paths). Use “write” when validating paths for write operations (strict validation to prevent overwriting critical files). Use None to manually control validation via individual flags. When mode is specified, it overrides the system_ok, user_paths_ok, and not_writeable flags. Defaults to None.
- system_ok (bool):
If True, allow paths within system directories. Defaults to False.
- user_paths_ok (bool):
If True, allow paths within user-defined sensitive locations. Defaults to False.
- not_writeable (bool):
If True, allow paths that are readable but not writeable. Defaults to False.
- cwd_only (bool):
If True, only allow paths within the current working directory to prevent path traversal attacks. Paths that resolve outside the CWD (e.g., ‘../../../etc/passwd’) are considered dangerous. Defaults to False.
- Raises:
DangerousPathError – If raise_error is True and the path is dangerous.
ValueError – If mode is not None, “read”, or “write”.
Notes
When mode is specified, individual flag parameters (system_ok, user_paths_ok, not_writeable) are ignored in favour of the mode’s preset values.
Examples
>>> # Default strict validation - dangerous for system paths >>> checker = PathChecker("/etc/passwd") >>> if not checker: ... print(f"Dangerous path! System path: {checker.is_system_path}") Dangerous path! System path: True >>> # Read mode - convenient for validating read operations >>> checker = PathChecker("/etc/passwd", mode="read") >>> if checker: ... print("Safe to read from this path!") Safe to read from this path! >>> # Write mode - strict validation to prevent overwriting critical files >>> checker = PathChecker("/tmp/myfile.txt", mode="write") >>> if checker: ... print("Safe to write to this path!") Safe to write to this path! >>> # Manual flag control (backward compatible) >>> checker = PathChecker( ... "/etc/passwd", system_ok=True, not_writeable=True ... ) >>> if checker: ... print("Safe with custom flags!") Safe with custom flags! >>> # Path traversal protection >>> checker = PathChecker("../../../etc/passwd", cwd_only=True) >>> if not checker: ... print("Dangerous: path traversal attempt detected!") Dangerous: path traversal attempt detected!
Exceptions¶
- exception bad_path.DangerousPathError[source]¶
Bases:
PermissionErrorException raised when a dangerous path is detected.