Security

uploadkit-security provides size, extension, MIME, filename, and checksum validators (sync + async). Pair it with Core or any framework adapter.

Install

Shell
pip install uploadkit-security
Shell
uv add uploadkit-security
Shell
poetry add uploadkit-security

System requirements — libmagic

For comprehensive MIME detection, install OS libmagic and uploadkit-security[magic] (uses python-magic). Without it, a built-in signature checker covers common types. See uploadkit-security.

Ubuntu / Debian libmagic1
Fedora / RHEL file-libs
Alpine libmagic
macOS (Homebrew) libmagic
Shell
sudo apt install libmagic1
pip install 'uploadkit-security[magic]'
Shell
sudo dnf install file-libs
pip install 'uploadkit-security[magic]'
Shell
sudo apk add libmagic
pip install 'uploadkit-security[magic]'
Shell
brew install libmagic
pip install 'uploadkit-security[magic]'

Optional: prefer uv add 'uploadkit-security[magic]' or poetry add uploadkit-security -E magic.

Examples

Attach validators on UploadPolicy. Sync pipelines use validators; async pipelines use async_validators.

Default stack

Size → extension → MIME → filename → checksum. Policy allow-lists are read by the validators.

policy_sync.py
from uploadkit import UploadPolicy
from uploadkit_security import default_validators

policy = UploadPolicy(
    max_size=5 * 1024 * 1024,
    allowed_extensions=frozenset({"png", "jpg"}),
    allowed_mime_types=frozenset({"image/png", "image/jpeg"}),
    validators=default_validators(),
)
policy_async.py
from uploadkit import UploadPolicy
from uploadkit_security import default_async_validators

policy = UploadPolicy(
    max_size=5 * 1024 * 1024,
    allowed_extensions=frozenset({"png", "jpg"}),
    allowed_mime_types=frozenset({"image/png", "image/jpeg"}),
    async_validators=default_async_validators(),
)

Customize the stack

Use include, exclude, and extra on default_validators() / default_async_validators().

customize_sync.py
from uploadkit import UploadPolicy
from uploadkit_security import (
    ChecksumValidator,
    FileNameValidator,
    FileSizeValidator,
    default_validators,
)

# Drop checksum from the full stack
validators = default_validators(exclude=ChecksumValidator)

# Keep only size + filename
validators = default_validators(
    include=(FileSizeValidator, FileNameValidator),
)

policy = UploadPolicy(
    max_size=5 * 1024 * 1024,
    validators=validators,
)
customize_async.py
from uploadkit import UploadPolicy
from uploadkit_security import (
    AsyncChecksumValidator,
    AsyncFileNameValidator,
    AsyncFileSizeValidator,
    default_async_validators,
)

# Drop checksum from the full stack
async_validators = default_async_validators(exclude=AsyncChecksumValidator)

# Keep only size + filename
async_validators = default_async_validators(
    include=(AsyncFileSizeValidator, AsyncFileNameValidator),
)

policy = UploadPolicy(
    max_size=5 * 1024 * 1024,
    async_validators=async_validators,
)

MIME detection

MimeTypeValidator / AsyncMimeTypeValidator call detect_mime_type. With uploadkit-security[magic] and OS libmagic installed, sniffing uses python-magic; otherwise a built-in signature table covers common types.

mime_sync.py
from uploadkit import UploadPolicy
from uploadkit_security import detect_mime_type, default_validators

# Requires: pip install 'uploadkit-security[magic]' + OS libmagic
head = open("photo.png", "rb").read(2048)
print(detect_mime_type(head, "photo.png"))  # e.g. "image/png"

policy = UploadPolicy(
    max_size=5 * 1024 * 1024,
    allowed_extensions=frozenset({"png", "pdf"}),
    allowed_mime_types=frozenset({"image/png", "application/pdf"}),
    validators=default_validators(),  # MimeTypeValidator uses detect_mime_type
)
mime_async.py
from uploadkit import UploadPolicy
from uploadkit_security import detect_mime_type, default_async_validators

# Requires: pip install 'uploadkit-security[magic]' + OS libmagic
head = open("photo.png", "rb").read(2048)
print(detect_mime_type(head, "photo.png"))  # e.g. "image/png"

policy = UploadPolicy(
    max_size=5 * 1024 * 1024,
    allowed_extensions=frozenset({"png", "pdf"}),
    allowed_mime_types=frozenset({"image/png", "application/pdf"}),
    async_validators=default_async_validators(),  # AsyncMimeTypeValidator
)

Filename and checksum

Harden names with FileNameValidator / sanitize_filename. Compute SHA-256 with ChecksumValidator so result.sha256 is set after upload.

filename_checksum_sync.py
from uploadkit import UploadPolicy
from uploadkit_security import (
    ChecksumValidator,
    FileNameValidator,
    default_validators,
    sanitize_filename,
)

print(sanitize_filename("../../evil name!!.txt"))  # "evil name__.txt"

# Filename hardening only
validators = default_validators(include=(FileNameValidator,))

# Checksum only — result.sha256 after upload
validators = default_validators(include=(ChecksumValidator,))

policy = UploadPolicy(validators=validators)
filename_checksum_async.py
from uploadkit import UploadPolicy
from uploadkit_security import (
    AsyncChecksumValidator,
    AsyncFileNameValidator,
    default_async_validators,
    sanitize_filename,
)

print(sanitize_filename("../../evil name!!.txt"))  # "evil name__.txt"

# Filename hardening only
async_validators = default_async_validators(include=(AsyncFileNameValidator,))

# Checksum only — result.sha256 after upload
async_validators = default_async_validators(include=(AsyncChecksumValidator,))

policy = UploadPolicy(async_validators=async_validators)

Shared policy and error conventions: Common patterns. Full reference: uploadkit-security README.