If you discover a security vulnerability in this project, please report it responsibly:
- DO NOT open a public GitHub issue for security vulnerabilities
- Email security reports to the maintainers (check repository for contact details)
- Provide detailed information about the vulnerability and steps to reproduce
We will acknowledge receipt of your report within 48 hours and provide a timeline for resolution.
| Version | Supported |
|---|---|
| 0.x.x | ✅ |
Pre-1.0 versions are under active development. Breaking changes may occur between minor versions.
This library implements archive extraction with security as a primary design goal:
- Path Traversal Prevention: Validates all paths to prevent extraction outside the destination directory
- Symlink Escape Prevention: Validates symlink targets to ensure they stay within bounds
- Hardlink Escape Prevention: Validates hardlink targets (when enabled)
- Null Byte Injection Prevention: Rejects paths containing null bytes
- Zip Bomb Detection: Monitors compression ratios to detect decompression bombs
- File Size Limits: Configurable limits on individual file and total extraction sizes
- File Count Limits: Caps the number of archive entries (files, directories and links), preventing DoS via excessive entry creation
- Path Depth Limits: Prevents deep directory nesting attacks
extract_to_sink and the Python and Node in-memory functions run archive entries through the same validation pipeline but write to an EntrySink instead of the filesystem:
- Memory Cap:
MemorySinkrefuses to grow past itsMemoryLimit(500 MiB by default, counting payload plus per-entry path and overhead bytes) and fails with aQuotaExceededI/O error carryingSinkFull - Path Model:
PathModel::Host(the default) applies the rules of the platform running the extraction; on a Windows host that includes the component rules ofPortable, while other hosts do not restrict component names.PathModel::Portableapplies the strictest rules of every supported platform on every host (characters and names Windows refuses, case and Unicode-normalization folding, length limits). UsePortablewhen the stored entries are read on a different platform
When the destination of a TAR extraction does not exist yet (and its parent does), exarch extract extracts into a hidden staging directory and renames it into place only on success. A refusal anywhere in the archive leaves nothing on disk and is reported with writes: "rolled_back". A process killed mid-extraction leaves its .exarch-XXXXXX staging directory next to the destination; delete it by hand.
- Banned Components: Default deny-list for sensitive directories (
.git,.ssh,.gnupg,.aws,.kube,.docker,.env) - Case-Insensitive Matching: Prevents bypass on case-insensitive filesystems
- Extension Filtering: Optional allowlist for file extensions
The default SecurityConfig implements a defense-in-depth strategy:
use exarch_core::SecurityConfig;
// Use secure defaults
let config = SecurityConfig::default();
// Or customize for trusted sources (use with caution)
let permissive = SecurityConfig::permissive();-
TOCTOU Conditions: Time-of-check-time-of-use race conditions exist in filesystem validation. While mitigated through canonicalization, full elimination requires platform-specific
openat()usage. -
Symlink Resolution: Circular symlinks are not explicitly detected but won't cause infinite loops during validation.
-
Platform Differences: Some security checks are platform-specific (e.g., permission validation on Unix vs Windows).
When using this library:
- Never extract untrusted archives with
SecurityConfig::permissive() - Always use the default configuration or more restrictive settings for untrusted input
- Validate the extraction destination directory is properly isolated
- Monitor resource usage during extraction of large archives
- Review security configuration for your specific use case
- 2025-12-30: Phase 1 security audit completed
- 0 BLOCKING issues
- 8 HIGH priority issues (all fixed)
- 16 MEDIUM priority issues (all fixed)
- 12 LOW priority issues (all fixed)
We follow responsible disclosure practices:
- Security issues are fixed before public disclosure
- Security advisories published after patches are available
- Credit given to reporters who follow responsible disclosure
For security concerns, please contact the maintainers through the repository's designated security channels.