Skip to main content

A comprehensive file security system for validating uploads and preventing attacks

Project description

safeuploads

License Release PyPI version PyPI downloads Python Docs Stars

Secure file upload validation for Python 3.13+ applications. Catches dangerous filenames, malicious extensions, Windows reserved names, and compression-based attacks before you accept an upload.

Features

  • Framework-agnostic async validation (FastAPI, generic)
  • Filename sanitization and Unicode security checks
  • Extension validation with configurable allow/block lists
  • ZIP bomb detection, nested archive inspection, and recursive structure protection
  • MIME type verification with file signature validation
  • Activity file support (.gpx, .tcx, .fit) with XXE-safe XML parsing
  • Gzip archive validation with decompression bomb detection
  • Streaming validation for memory-efficient large file processing
  • Resource monitoring (CPU time and memory limits)
  • Content analysis with malware signature and polyglot detection
  • Structured audit logging with correlation IDs
  • Rich exception hierarchy with machine-readable error codes
  • Zero configuration required—secure defaults out of the box

Installation

pip install safeuploads

For FastAPI integration:

pip install safeuploads[fastapi]

Quick Start

from fastapi import FastAPI, UploadFile, HTTPException
from safeuploads import FileValidator
from safeuploads.exceptions import FileValidationError

app = FastAPI()
validator = FileValidator()

@app.post("/upload")
async def upload_image(file: UploadFile):
    try:
        await validator.validate_image_file(file)
    except FileValidationError as e:
        raise HTTPException(status_code=400, detail=str(e))
    
    return {"status": "success", "filename": file.filename}

Configuration

from safeuploads import FileValidator, FileSecurityConfig

# Use default secure configuration
validator = FileValidator()

# Or customize limits
config = FileSecurityConfig()
config.limits.max_image_size = 10 * 1024 * 1024  # 10 MiB
config.limits.max_compression_ratio = 50

validator = FileValidator(config=config)

Exception Handling

from safeuploads.exceptions import (
    FileValidationError,      # Base exception
    FileSizeError,            # File too large
    ExtensionSecurityError,   # Dangerous extension
    ZipBombError,             # Compression attack
)

try:
    await validator.validate_image_file(file)
except FileSizeError as err:
    return {"error": "File too large", "max_size": err.max_size}
except ExtensionSecurityError as err:
    return {"error": "File type not allowed", "extension": err.extension}
except FileValidationError as err:
    return {"error": str(err), "code": err.error_code}

Current Status

Implemented

  • Filename Security: Unicode normalization, directory traversal prevention, Windows reserved names blocking
  • Extension Validation: Allow/block lists with configurable rules, dangerous extension detection
  • Compression Security: ZIP bomb detection, nested archive inspection, recursive structure and quine detection, size and ratio limits
  • Content Inspection: Deep ZIP content analysis with configurable depth and entry limits
  • MIME Type Verification: Magic number validation for images, ZIP, activity files, and gzip
  • Streaming Validation: Memory-efficient processing via SpooledTemporaryFile for large files
  • Resource Monitoring: CPU time and memory limits enforced via ResourceMonitor
  • Activity File Support: GPX, TCX, and FIT file validation with XXE-safe XML parsing
  • Gzip Support: Gzip archive validation with decompression bomb detection
  • Content Analysis: Optional malware signature, web shell, and polyglot file detection
  • Audit Logging: Structured security event logging with correlation IDs via contextvars
  • Performance Optimizations: Pre-compiled pattern sets, frozenset lookups, LRU-cached MIME guessing
  • Rich Exception System: Machine-readable error codes with detailed context
  • Fuzzing Tests: Hypothesis-based property testing for filenames, ZIP, images, and config

Known Limitations

  • No built-in rate limiting (application-level concern — see documentation)
  • MIME detection covers first 8 KB; advanced polyglot attacks may require enable_content_analysis
  • SpooledTemporaryFile uses the system default temp directory

Documentation

Full documentation is available at the safeuploads docs site.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Contributing

Contributions welcome! See Contributing Guidelines for guidelines.

Built with ❤️ from Portugal | Part of the Endurain ecosystem

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

safeuploads-1.0.1.tar.gz (178.4 kB view details)

Uploaded Source

Built Distribution

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

safeuploads-1.0.1-py3-none-any.whl (48.7 kB view details)

Uploaded Python 3

File details

Details for the file safeuploads-1.0.1.tar.gz.

File metadata

  • Download URL: safeuploads-1.0.1.tar.gz
  • Upload date:
  • Size: 178.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for safeuploads-1.0.1.tar.gz
Algorithm Hash digest
SHA256 3d7eb433fb9cb04c96e3535e0ca5bf4e499d7fc18eb06dc39ee80dc3e55a6861
MD5 fe657a50968ad6e576c69c420e993695
BLAKE2b-256 238f4686e77b6f72efe7f84eb395f83f28cbfbb79eba4047a79347bcad7fbf67

See more details on using hashes here.

File details

Details for the file safeuploads-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: safeuploads-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 48.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for safeuploads-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d3074ccd85fee4c4577e4fc2a6586347b5680d5589f5226403d546c72e2a6b7d
MD5 b25e115440a79c7a582107b5b2e622af
BLAKE2b-256 f4294316c3c1a876552babe67c6a82fe94ec80c0732733dcb48eb0f93b1a0cdd

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