Skip to main content

exarch

PyPI Python CI License

Memory-safe archive extraction and creation library for Python.

Important: exarch is designed as a secure replacement for vulnerable archive libraries like Python's tarfile, which has known CVEs with CVSS scores up to 9.4.

This package provides Python bindings for exarch-core, a Rust library with built-in protection against common archive vulnerabilities.

Installation

pip install exarch

Tip: Use uv pip install exarch for faster installation.

Alternative Package Managers

# Poetry
poetry add exarch

# Pipenv
pipenv install exarch

Requirements

  • Python >= 3.10

Quick Start

Extraction

import exarch

result = exarch.extract_archive("archive.tar.gz", "/output/path")
print(f"Extracted {result.files_extracted} files")

Creation

import exarch

result = exarch.create_archive("backup.tar.gz", ["src/", "Cargo.toml"])
print(f"Created archive with {result.files_added} files")

Usage

Basic Extraction

import exarch

result = exarch.extract_archive("archive.tar.gz", "/output/path")

print(f"Files extracted: {result.files_extracted}")
print(f"Bytes written: {result.bytes_written}")
print(f"Duration: {result.duration_ms}ms")

With pathlib.Path

from pathlib import Path
import exarch

archive = Path("archive.tar.gz")
output = Path("/output/path")

result = exarch.extract_archive(archive, output)

Custom Security Configuration

import exarch

config = exarch.SecurityConfig()
config = config.with_max_file_size(100 * 1024 * 1024)  # 100 MB

result = exarch.extract_archive("archive.tar.gz", "/output", config)

Error Handling

import exarch

try:
    result = exarch.extract_archive("archive.tar.gz", "/output")
    print(f"Extracted {result.files_extracted} files")
except exarch.PathTraversalError as e:
    print(f"Blocked path traversal: {e}")
except exarch.ZipBombError as e:
    print(f"Zip bomb detected: {e}")
except exarch.SecurityViolationError as e:
    print(f"Security violation: {e}")
except exarch.ArchiveError as e:
    print(f"Extraction failed: {e}")

API Reference

extract_archive(archive_path, output_dir, config=None)

Extract an archive to the specified directory with security validation.

Parameters:

Name Type Description
archive_path str | Path Path to the archive file
output_dir str | Path Directory where files will be extracted
config SecurityConfig Optional security configuration

Returns: ExtractionReport

Attribute Type Description
files_extracted int Number of files extracted
directories_created int Number of directories created
symlinks_created int Number of symlinks created
bytes_written int Total bytes written
duration_ms int Extraction duration in milliseconds
files_skipped int Number of files skipped (e.g. duplicates)
warnings list[str] Warning messages generated during extraction

Raises:

Exception Description
PathTraversalError Path traversal attempt detected
SymlinkEscapeError Symlink points outside extraction directory
HardlinkEscapeError Hardlink target outside extraction directory
ZipBombError Potential zip bomb detected
QuotaExceededError Resource quota exceeded
SecurityViolationError Security policy violation
UnsupportedFormatError Archive format not supported
UnknownFormatError Archive format cannot be determined from path or magic bytes (subclass of UnsupportedFormatError)
InvalidArchiveError Archive is corrupted
IOError I/O operation failed

Note: Since v0.4.0, create_archive raises FileNotFoundError for missing sources, FileExistsError when the output already exists without overwrite, and ValueError for invalid compression levels — matching standard Python conventions.

extract_archive_with_progress(archive_path, output_dir, config, progress)

Extract an archive with a progress callback. The GIL is held when a callback is provided and released otherwise.

Parameters:

Name Type Description
archive_path str | Path Path to the archive file
output_dir str | Path Directory where files will be extracted
config SecurityConfig | None Optional security configuration
progress Callable[[str, int, int, int], None] | None Optional progress callback: (path, total_files, current_file, bytes_written)
import exarch


def on_progress(path: str, total: int, current: int, bytes_written: int) -> None:
    print(f"[{current}/{total}] {path} ({bytes_written} bytes)")


result = exarch.extract_archive_with_progress(
    "archive.tar.gz", "/output", config=None, progress=on_progress
)

If progress raises: extraction is not aborted early — the progress-callback contract has no cancellation signal, so extraction always runs to completion first, and progress is not called again for the remaining entries once it has raised. If extraction otherwise succeeded, progress's own exception propagates unchanged, with files_extracted/bytes_written attributes describing what was written and a progress_callback_error = True marker attribute (check this marker before treating the presence of files_extracted as a partial-extraction signal, since a genuine partial-extraction failure carries the same two attribute names). If extraction also failed, the extraction error takes priority — a raising progress can never mask a security error such as SymlinkEscapeError — and progress's exception is attached as __cause__ instead of being dropped. create_archive_with_progress behaves the same way, using files_added in place of files_extracted.

SecurityConfig

Builder-style security configuration.

config = exarch.SecurityConfig()
config = config.with_max_file_size(100 * 1024 * 1024)  # 100 MB per file
config = config.with_max_total_size(1024 * 1024 * 1024)  # 1 GB total
config = config.with_max_file_count(10_000)  # Max 10k files
config = config.with_max_compression_ratio(50.0)  # Zip bomb threshold
config = config.add_allowed_extension(".txt")  # Extension allowlist
config = config.add_allowed_extension(".md")
config = config.add_banned_component("__MACOSX")  # Skip components
config = config.with_allow_solid_archives(True)  # Allow solid 7z archives

Security Features

The library provides built-in protection against:

Protection Description
Path traversal Blocks ../ and absolute paths
Symlink attacks Prevents symlinks escaping extraction directory
Hardlink attacks Validates hardlink targets
Zip bombs Detects high compression ratios
TAR metadata bombs Bounds GNU long-name/long-link and PAX header record reads
Permission sanitization Strips setuid/setgid bits
Size limits Enforces file and total size limits

Caution: Unlike Python's standard tarfile module, exarch applies security validation by default.

Supported Formats

Format Extensions Extract Create List Verify
TAR .tar
TAR+GZIP .tar.gz, .tgz
TAR+BZIP2 .tar.bz2, .tbz2
TAR+XZ .tar.xz, .txz
TAR+ZSTD .tar.zst, .tzst
ZIP .zip
ZIP-family .jar, .war, .ear, .nar, .nbm, .apk, .aab, .ipa, .appx, .msix, .whl, .vsix, .xpi, .epub
7z .7z

Note: ZIP-family formats share the ZIP container but add extra structure (signing, checksum manifests, ordering rules) that exarch doesn't produce, so creation is rejected for those extensions. 7z creation is not yet supported. Solid and encrypted 7z archives are rejected for security reasons. Unix symlinks inside 7z archives are reported as regular files (sevenz-rust2 API limitation).

Comparison with tarfile

# UNSAFE - tarfile has known vulnerabilities (CVE-2007-4559)
import tarfile

with tarfile.open("archive.tar.gz") as tar:
    tar.extractall("/output")  # May extract outside target directory!

# SAFE - exarch validates all paths
import exarch

exarch.extract_archive("archive.tar.gz", "/output")  # Protected by default

Development

This package is built using PyO3 and maturin.

# Clone repository
git clone https://github.com/bug-ops/exarch
cd exarch/crates/exarch-python

# Build with maturin
pip install maturin
maturin develop

# Run tests
pytest tests/

Related Packages

License

Licensed under either of:

at your option.

Download files

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

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

exarch-0.6.0-cp39-abi3-win_amd64.whl (1.3 MB view details)

Uploaded CPython 3.9+Windows x86-64

exarch-0.6.0-cp39-abi3-musllinux_1_2_x86_64.whl (1.7 MB view details)

Uploaded CPython 3.9+musllinux: musl 1.2+ x86-64

exarch-0.6.0-cp39-abi3-musllinux_1_2_aarch64.whl (1.6 MB view details)

Uploaded CPython 3.9+musllinux: musl 1.2+ ARM64

exarch-0.6.0-cp39-abi3-manylinux_2_34_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.34+ x86-64

exarch-0.6.0-cp39-abi3-manylinux_2_34_aarch64.whl (1.4 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.34+ ARM64

exarch-0.6.0-cp39-abi3-macosx_11_0_arm64.whl (1.3 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

exarch-0.6.0-cp39-abi3-macosx_10_12_x86_64.whl (1.4 MB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file exarch-0.6.0-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: exarch-0.6.0-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for exarch-0.6.0-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 2ea54379b91d69dab08b0fbe2232581ea6405d9a30c922685bdb259b4ae3d0c2
MD5 6515d20a6254e8982f94bd607be84853
BLAKE2b-256 a3cffad61cc7db2347d08edf10fb8173dfe1eac75536abc02c6ee2955f46c14b

See more details on using hashes here.

Provenance

The following attestation bundles were made for exarch-0.6.0-cp39-abi3-win_amd64.whl:

Publisher: release.yml on bug-ops/exarch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file exarch-0.6.0-cp39-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for exarch-0.6.0-cp39-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 84f3f297519b885ca88eae086c55101a2d7982457c37fd6de3173b6e8e3b063b
MD5 f1e1c4dc49376b2c256104dc3f7f6826
BLAKE2b-256 b64ac66418784f0f7d24d257520fc2e6e6852e274b4d2a6999a4b588a187253a

See more details on using hashes here.

Provenance

The following attestation bundles were made for exarch-0.6.0-cp39-abi3-musllinux_1_2_x86_64.whl:

Publisher: release.yml on bug-ops/exarch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file exarch-0.6.0-cp39-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for exarch-0.6.0-cp39-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 477b3107abfeeb14c18cbafa2972c9dee9bbabc98c5d1e75c38c3e07c8ff0703
MD5 99d3a5c80431f197637cfdd6388a7537
BLAKE2b-256 aaba4038662e6651832d1235e680eee96ca7540be8f1bad1194698528899eecf

See more details on using hashes here.

Provenance

The following attestation bundles were made for exarch-0.6.0-cp39-abi3-musllinux_1_2_aarch64.whl:

Publisher: release.yml on bug-ops/exarch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file exarch-0.6.0-cp39-abi3-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for exarch-0.6.0-cp39-abi3-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 004bb74cdc2d8209172b06b7992abc7984a198c64fcba4aee38fce7892f6c255
MD5 640b11a00ac2493dbae724cb02b1e8fd
BLAKE2b-256 642378a0923705a6609cbe16648fba9044dc51ae04a36b1d0ad8893d7b2baa59

See more details on using hashes here.

Provenance

The following attestation bundles were made for exarch-0.6.0-cp39-abi3-manylinux_2_34_x86_64.whl:

Publisher: release.yml on bug-ops/exarch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file exarch-0.6.0-cp39-abi3-manylinux_2_34_aarch64.whl.

File metadata

File hashes

Hashes for exarch-0.6.0-cp39-abi3-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 e0cd3ecbceee3085c5a0cb75e12950cd66640a8f5cde7af9e9682873b85d3ed9
MD5 0166a922fc153390095232d4c38dff82
BLAKE2b-256 991b321d32578218ad350549af4dcb0db32f7963ce0a173ba2008420a53eadb9

See more details on using hashes here.

Provenance

The following attestation bundles were made for exarch-0.6.0-cp39-abi3-manylinux_2_34_aarch64.whl:

Publisher: release.yml on bug-ops/exarch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file exarch-0.6.0-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for exarch-0.6.0-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 57f6de462a12c596560869d245df2728cafa4c228e706728e7fea8d7ddd67126
MD5 536ae2ff5664d3bb85b336eea0374cf0
BLAKE2b-256 fb1186d069799c389494cfc009a2e69d7d70efcfa79c6a266bdcf7eb813930fb

See more details on using hashes here.

Provenance

The following attestation bundles were made for exarch-0.6.0-cp39-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on bug-ops/exarch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file exarch-0.6.0-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for exarch-0.6.0-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 8a099edb4b9798a379adedb48cbf63c835db7b19717073174d7604a7af3c030b
MD5 9b538ffa37d5fe19c86cfe77cac4e765
BLAKE2b-256 c76d972abb67dda92a567209850a9f26eedaa4fa202b65956bef9b92bffa6e62

See more details on using hashes here.

Provenance

The following attestation bundles were made for exarch-0.6.0-cp39-abi3-macosx_10_12_x86_64.whl:

Publisher: release.yml on bug-ops/exarch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.6.0 This release

7 files

0.5.2

7 files

0.5.1

7 files

0.5.0

7 files

0.4.1

7 files

0.4.0

7 files

0.3.1

7 files

0.3.0

7 files

0.2.9

7 files

0.2.8

7 files

0.2.7

7 files

0.2.6

7 files

0.2.5

7 files

0.2.4

7 files

0.2.3

7 files

0.2.2

5 files

0.2.1

5 files

0.2.0

5 files

0.1.2

5 files

0.1.1

5 files

0.1.0

2 files

Supported by

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