3
0
Fork
You've already forked safeuploads
0
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. http://safeuploads.endurain.com
  • Python 100%
João Vitória Silva ef841e9d5b
All checks were successful
Lint & Test / Lint (push) Successful in 53s
Deploy documentation / deploy (push) Successful in 1m19s
Lint & Test / Test (push) Successful in 1m32s
chore: update actions/checkout and actions/setup-python to v6 in workflow files
2026年06月03日 15:53:19 +01:00
.forgejo chore: update actions/checkout and actions/setup-python to v6 in workflow files 2026年06月03日 15:53:19 +01:00
.github ci: add validation for Conventional Commits format in PRs and commits 2026年06月03日 15:16:54 +01:00
docs Add GitHub Actions workflows for documentation deployment, fuzz testing, linting, testing, publishing to PyPI, and dependency updates; update README and documentation links to Codeberg 2026年04月30日 13:46:26 +01:00
examples chore: bump version to 1.0.1 in project files 2026年06月03日 15:25:27 +01:00
safeuploads fix: ensure original file position is reset after reading in FileValidator #3 2026年06月03日 15:17:10 +01:00
tests Lint 2026年03月26日 22:01:12 +00:00
.gitignore Add Hypothesis fuzz tests and test enhancements 2026年03月25日 17:50:10 +00:00
CODE_OF_CONDUCT.md Add documentation, conduct, and funding files 2025年10月30日 12:22:56 +00:00
CONTRIBUTING.md Update CONTRIBUTING.md 2026年05月13日 11:51:17 +02:00
LICENSE.md first commit 2025年10月24日 15:04:16 +01:00
mkdocs.yml Add GitHub Actions workflows for documentation deployment, fuzz testing, linting, testing, publishing to PyPI, and dependency updates; update README and documentation links to Codeberg 2026年04月30日 13:46:26 +01:00
pyproject.toml chore: bump version to 1.0.1 in project files 2026年06月03日 15:25:27 +01:00
README.md fix: update documentation URLs to point to the new site 2026年06月03日 15:34:12 +01:00
renovate.json Add GitHub Actions workflows for documentation deployment, fuzz testing, linting, testing, publishing to PyPI, and dependency updates; update README and documentation links to Codeberg 2026年04月30日 13:46:26 +01:00
SECURITY.md Add documentation, conduct, and funding files 2025年10月30日 12:22:56 +00:00
uv.lock chore: bump version to 1.0.1 in project files 2026年06月03日 15:25:27 +01:00

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