Skip to main content

A Python package to identify potentially dangerous file paths

Project description

bad_path

Tests Coverage Status Codacy coverage Documentation PyPI version Anaconda Version Codacy Badge Platform License

A Python package to identify potentially dangerous file paths.

Overview

bad_path provides functions to test whether a supplied file path points to a system-sensitive location, taking into account different OS platforms (Windows, macOS, Linux).

Installation

From PyPI

pip install bad_path

From Conda

conda install -c phygbu bad_path
# or
mamba install -c phygbu bad_path

From Source

git clone https://github.com/stonerlab/bad_path.git
cd bad_path
pip install -e .

Quick Start

from bad_path import is_dangerous_path, DangerousPathError

# Check if a path is dangerous
if is_dangerous_path("/etc/passwd"):
    print("Warning: This path points to a sensitive location!")

# Raise an exception for dangerous paths
try:
    is_dangerous_path("/etc/passwd", raise_error=True)
except DangerousPathError as e:
    print(f"Error: {e}")

# Use the PathChecker class for more details
from bad_path import PathChecker

checker = PathChecker("/etc/passwd")
if not checker:
    print(f"Dangerous path detected!")
    print(f"Platform system path: {checker.is_system_path}")
    print(f"User-defined sensitive path: {checker.is_sensitive_path}")

# Check path accessibility
checker = PathChecker("/tmp/myfile.txt")
if checker:
    print("Safe path!")
print(f"Readable: {checker.is_readable}")
print(f"Writable: {checker.is_writable}")
print(f"Creatable: {checker.is_creatable}")

Features

  • ✅ Cross-platform support (Windows, macOS, Linux)
  • ✅ Simple API for checking dangerous paths
  • ✅ Object-oriented PathChecker class with detailed information
  • ✅ Path accessibility checks (read, write, create permissions)
  • Invalid character detection (platform-specific)
  • Path traversal protection (optional cwd_only flag)
  • ✅ Customizable error handling
  • ✅ Lightweight with no external dependencies
  • ✅ Works with both strings and pathlib.Path objects
  • ✅ User-defined dangerous paths support

Usage Examples

Basic Path Checking

from bad_path import is_dangerous_path

# Simple boolean check
if is_dangerous_path("/etc/passwd"):
    print("This is a dangerous system path!")

if not is_dangerous_path("/tmp/myfile.txt"):
    print("Safe to use!")

Read vs Write Validation

The mode parameter makes it easy to validate paths for different purposes:

from bad_path import PathChecker

# Validate for reading - allows system configuration files
checker = PathChecker("/etc/passwd", mode="read")
if checker:
    print("Safe to read from this path!")
    # Read the file...

# Validate for writing - strict validation
checker = PathChecker("/tmp/output.txt", mode="write")
if checker:
    print("Safe to write to this path!")
    # Write to the file...

# Attempting to write to system paths is blocked
checker = PathChecker("/etc/myconfig.txt", mode="write")
if not checker:
    print("Blocked: Cannot write to system paths!")

Checking Path Accessibility

from bad_path import PathChecker

# Check if a file is readable
checker = PathChecker("/etc/passwd")
if checker.is_readable:
    print("File can be read")

# Check if a file is writable
checker = PathChecker("/tmp/test.txt")
if checker.is_writable:
    print("File can be written to")

# Check if a new file can be created
checker = PathChecker("/tmp/newfile.txt")
if checker.is_creatable:
    print("File can be created in this location")

Combining Safety and Accessibility Checks

from bad_path import PathChecker

def safe_to_write(filepath):
    """Check if a path is both safe and writable."""
    checker = PathChecker(filepath)
    
    # PathChecker evaluates to True for safe paths
    if not checker:
        return False  # Dangerous location
    
    # Must be writable or creatable
    return checker.is_writable or checker.is_creatable

# Usage
safe_to_write("/tmp/myfile.txt")  # True - safe and creatable
safe_to_write("/etc/passwd")       # False - dangerous location

Checking for Invalid Characters

from bad_path import PathChecker

# Check if a path contains invalid characters for the platform
checker = PathChecker("/tmp/test\x00file.txt")  # Null byte is invalid on all platforms
print(f"Has invalid characters: {checker.has_invalid_chars}")  # True
print(f"Is safe: {bool(checker)}")  # False - dangerous due to invalid char

# Platform-specific invalid characters:
# - POSIX (Linux): null byte (\0)
# - macOS (Darwin): null byte (\0) and colon (:)
# - Windows: < > : " | ? * and control characters (0-31)
#            Also checks for reserved names: CON, PRN, AUX, NUL, COM1-9, LPT1-9

# Windows example - reserved name check
checker = PathChecker("C:\\tmp\\CON.txt")  # CON is a reserved name
print(f"Has invalid characters: {checker.has_invalid_chars}")  # True on Windows

# Paths ending with space or period are invalid on Windows
checker = PathChecker("C:\\tmp\\file. ")
print(f"Has invalid characters: {checker.has_invalid_chars}")  # True on Windows

Path Traversal Protection

The cwd_only flag provides protection against path traversal attacks by restricting paths to the current working directory and its subdirectories. This is disabled by default to maintain backward compatibility.

from bad_path import PathChecker

# Enable path traversal protection
checker = PathChecker("../../../etc/passwd", cwd_only=True)
if not checker:
    print("Blocked: Path traversal attempt detected!")

# Paths outside CWD are blocked
checker = PathChecker("/tmp/file.txt", cwd_only=True)
if not checker:
    print("Blocked: Path is outside current working directory!")

# Paths within CWD and its subdirectories are allowed
checker = PathChecker("./data/file.txt", cwd_only=True)
if checker:
    print("Safe: Path is within current working directory")

# Works with raise_error for automatic exception handling
from bad_path import DangerousPathError
try:
    checker = PathChecker("../../sensitive.txt", cwd_only=True, raise_error=True)
except DangerousPathError as e:
    print(f"Error: {e}")

Use cases for cwd_only:

  • Web applications handling user-provided file paths
  • CLI tools that should only operate on files in the current project
  • Sandboxed environments where file access should be restricted
  • Any scenario where you need to prevent directory traversal attacks
# Example: Secure file handler for a web application
def handle_user_file_request(user_path):
    """Safely handle user-provided file paths."""
    # Validate the path is within CWD to prevent traversal attacks
    checker = PathChecker(user_path, cwd_only=True, raise_error=True)
    
    # Additional checks
    if not checker.is_readable:
        raise PermissionError("File is not readable")
    
    # Safe to proceed with file operations
    with open(checker.path, 'r') as f:
        return f.read()

Documentation

Full documentation is available at https://stonerlab.github.io/bad_path/

Development

For development, install with the optional development dependencies:

pip install -e ".[dev]"

Run tests:

pytest

Build documentation:

cd docs
make html

License

MIT License - see LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bad_path-0.2.1.tar.gz (30.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bad_path-0.2.1-py3-none-any.whl (19.4 kB view details)

Uploaded Python 3

File details

Details for the file bad_path-0.2.1.tar.gz.

File metadata

  • Download URL: bad_path-0.2.1.tar.gz
  • Upload date:
  • Size: 30.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.19

File hashes

Hashes for bad_path-0.2.1.tar.gz
Algorithm Hash digest
SHA256 073ccd8f7e6f929dc66d15a277437dfd3be804cef14208da13fa3abf6a2dfdc3
MD5 be8d165e52c9a523cf4d2ffb167a437c
BLAKE2b-256 9ce12354d5ea1150217e62bd5235fa4f3b3d237deb7bf42ab12407572bda1480

See more details on using hashes here.

File details

Details for the file bad_path-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: bad_path-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 19.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.19

File hashes

Hashes for bad_path-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9baaf2eab82c0bc1a2891f3461c9eed9275ca1dca43d8258bdcc6daf9eb4d54e
MD5 4b657cd8995788a9a0ed0665a9919fb6
BLAKE2b-256 da31280db75db820cdc7427898df576589b0d85e81d08190589ae544b5089f0d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page