archmeld 0.1.6

Secure, memory-safe, type-safe CLI for multi-format archive extraction, inspection and decompression
Documentation

archmeld

Secure, memory-safe, type-safe CLI for multi-format archive extraction, inspection and decompression.

Crates.io License rust-doctor

Features

  • 27 archive and compression formats supported
  • Zero unsafe code (unsafe_code = "forbid")
  • Security-first extraction via safe_unzip (zip-slip, zip-bomb, symlink, encrypted entry protection)
  • 4 output formats: text, JSON, SARIF 2.1.0, Markdown
  • 377 tests, 17 fuzz targets, 0 cargo-audit vulnerabilities
  • 2.3 MiB binary (51% smaller than ouch)
  • CSAF 2.0 advisories for all security findings

Installation

cargo install archmeld

Or download pre-built binaries from the releases page.

Quick Start

# Detect format
archmeld info archive.tar.gz

# List contents
archmeld list archive.zip

# Extract
archmeld extract archive.tar.xz -o output/

# Validate (dry-run, no output written)
archmeld validate archive.7z

# Verify integrity (checksums)
archmeld verify archive.gz

# Compress with Zopfli (high-ratio gzip)
archmeld gz-compress file.txt

# LZ4 compress/decompress
archmeld lz4 compress file.txt
archmeld lz4 decompress file.txt.lz4

# Inspect headers
archmeld gz-inspect archive.gz --verify
archmeld lz4 inspect file.lz4

# Output as JSON, SARIF, or Markdown
archmeld info -O json archive.zip
archmeld list -O sarif archive.tar.gz
archmeld validate -O markdown archive.deb

Supported Formats

Format Extract List Info Inspect
ZIP YES YES YES
TAR YES YES YES
TAR.GZ YES YES YES
TAR.BZ2 YES YES YES
TAR.XZ YES YES YES
TAR.ZSTD YES YES YES
TAR.LZ4 YES YES
7-Zip YES YES YES
GZIP YES YES YES
BZIP2 YES YES
XZ YES YES
LZ4 YES YES YES
Zstandard YES YES
BZip3 YES YES
Brotli YES YES
Snappy YES YES
LZMA YES YES
DEB YES YES YES
AR YES YES YES
CAB YES YES YES
RAR YES YES YES
StuffIt YES YES
Compact Pro YES YES
Lzip YES
ARC YES
ZPAQ YES YES YES
QCOW2 YES
ISO 9660 YES YES YES

RAR support requires the rar feature (enabled by default, bundles C++ unrar library).

ZPAQ support requires the zpaq feature. ISO 9660 support requires the iso feature. QCOW2 images are detected and identified but not extracted (virtual disk, not archive). All three are enabled by default.

Security

archmeld is built with security as a primary goal:

  • unsafe_code = "forbid" in the entire crate
  • Zip-Slip protection via path_jail and sanitize_path
  • Zip-Bomb detection with configurable limits (file size, total size, entry count, compression ratio, path depth)
  • Symlink rejection (configurable policy)
  • Encrypted entry detection (returns error)
  • Filename sanitization (control characters, Windows reserved names)
  • Two-pass validation (ValidateFirst mode)
  • Permission stripping (setuid/setgid removal)
  • Atomic file creation (O_EXCL via safe_unzip)
# Configurable safety limits
archmeld extract archive.zip \
  --max-file-size 50 \
  --max-total-size 500 \
  --max-entries 10000 \
  --max-ratio 500

Benchmark vs ouch

Tested on macOS (Apple Silicon) with hyperfine.

Large File Extraction (curl 8.20.0 source)

File archmeld ouch Winner
curl.tar.gz 2467 ms 5574 ms archmeld 2x
curl.tar.bz2 9302 ms 14773 ms archmeld 2x
curl.tar.xz 4970 ms 5954 ms archmeld 1x
curl.zip 5186 ms 4020 ms ouch 1x

Code Quality (rust-doctor)

Category archmeld ouch
Overall 99 / 100 92 / 100
Security 100 99
Reliability 100 90
Maintainability 98 69
Warnings 24 345

Summary

Metric archmeld ouch
Formats 27 14
Binary size 2.3 MiB 4.7 MiB
Tests 377 N/A
Fuzz targets 17 N/A
unsafe_code Forbidden Used
Security features 14 2
cargo-audit 0 vulns N/A
CSAF advisories 4 0

Full benchmark details in benchmark.md.

Library Usage

use archmeld::archive::Extractor;
use archmeld::format::{self, ArchiveFormat};

// Detect format from bytes
let data = std::fs::read("archive.tar.gz")?;
let fmt = format::detect_format(&data);

// Extract with safety limits
let extractor = Extractor::new()
    .with_max_file_size(100 * 1024 * 1024)
    .with_max_total_size(1024 * 1024 * 1024)
    .with_max_entries(100_000);

let files = extractor.extract(&data, fmt)?;
for file in &files {
    println!("{}: {} bytes", file.path, file.size);
}

// Validate without extracting
let result = extractor.validate(&data, fmt)?;
println!("Valid: {}, entries: {}", result.is_valid,
  result.entry_count);

Building

# Debug build
cargo build

# Release build
cargo build --release

# Without RAR support (no C++ dependency)
cargo build --release --no-default-features

# Without ZPAQ/ISO support (no C++ dependency)
cargo build --release --no-default-features

# Run tests
cargo test

# Run clippy
cargo clippy --all-targets -- -D warnings

# Run fuzz targets (requires nightly)
cargo fuzz run fuzz_extract -- -max_total_time=60

CSAF Security Advisories

All dependency vulnerabilities are documented as CSAF 2.0 advisories in csaf/:

  • ndaal-sa-2026-007: lz4_flex info leak (RUSTSEC-2026-0041) — FIXED
  • ndaal-sa-2026-008: tar PAX header (RUSTSEC-2026-0068) — FIXED
  • ndaal-sa-2026-009: tar symlink chmod (RUSTSEC-2026-0067) — FIXED
  • ndaal-sa-2026-010: time DoS (RUSTSEC-2026-0009) — FIXED

License

MIT OR Apache-2.0

Authors

ndaal GmbH — Pierre Gronau

Security contact: security@ndaal.eu