From 28a37cfb227dda85d42971b4e268038129116b10 Mon Sep 17 00:00:00 2001 From: UncleSp1d3r Date: Sun, 15 Feb 2026 17:47:34 -0500 Subject: [PATCH 01/15] chore: add do-not-merge label exclusion to auto-queue rules Add label != do-not-merge condition to release-plz and dependabot auto-queue rules for consistency with the approved PRs rule. Signed-off-by: UncleSp1d3r --- .mergify.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.mergify.yml b/.mergify.yml index 8a04dbef..5c074d60 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -24,6 +24,7 @@ pull_request_rules: conditions: - base = main - "head ~= ^release-plz-" + - label != do-not-merge actions: queue: name: default @@ -32,6 +33,7 @@ pull_request_rules: conditions: - base = main - author = dependabot[bot] + - label != do-not-merge actions: queue: name: default From 57da090f65d2b1b5149ef2828b1cb48219ab1831 Mon Sep 17 00:00:00 2001 From: UncleSp1d3r Date: Sun, 15 Feb 2026 17:48:42 -0500 Subject: [PATCH 02/15] chore: auto-update PRs when main advances Keep open PRs rebased against main automatically. Excludes drafts, conflicting PRs, and dependabot (which handles its own rebases). Signed-off-by: UncleSp1d3r --- .mergify.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.mergify.yml b/.mergify.yml index 5c074d60..54faadd5 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -38,6 +38,15 @@ pull_request_rules: queue: name: default + - name: Keep PRs up to date with main + conditions: + - base = main + - -conflict + - -draft + - -author = dependabot[bot] + actions: + update: + merge_protections: - name: CI must pass description: >- From 3056c96ef382961f68293d082306086835798e42 Mon Sep 17 00:00:00 2001 From: UncleSp1d3r Date: Sun, 15 Feb 2026 17:53:43 -0500 Subject: [PATCH 03/15] chore: auto-approve dependabot PRs and disable dependabot rebases - Add review: APPROVE action to dependabot auto-queue rule so PRs can merge even if branch protection requires approvals - Disable dependabot's own rebase-strategy since Mergify handles rebasing via the merge queue Signed-off-by: UncleSp1d3r --- .github/dependabot.yml | 7 +++++-- .mergify.yml | 5 ++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2e334460..1b912e93 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,16 +1,19 @@ version: 2 updates: - - package-ecosystem: "cargo" # See documentation for possible values - directory: "/" # Location of package manifests + - package-ecosystem: "cargo" + directory: "/" schedule: interval: "weekly" + rebase-strategy: "disabled" - package-ecosystem: "github-actions" directory: "/" schedule: interval: weekly + rebase-strategy: "disabled" - package-ecosystem: "devcontainers" directory: "/" schedule: interval: weekly + rebase-strategy: "disabled" diff --git a/.mergify.yml b/.mergify.yml index 54faadd5..ca16fc85 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -29,12 +29,15 @@ pull_request_rules: queue: name: default - - name: Auto-queue dependabot PRs + - name: Auto-approve and queue dependabot PRs conditions: - base = main - author = dependabot[bot] - label != do-not-merge actions: + review: + type: APPROVE + message: Automatically approved by Mergify queue: name: default From a4d65caf916efb06d1713ca3b098ddce4b80335b Mon Sep 17 00:00:00 2001 From: UncleSp1d3r Date: Sun, 15 Feb 2026 17:59:02 -0500 Subject: [PATCH 04/15] chore: add DCO remediation commit config Allow contributors to fix forgotten sign-offs by pushing an additional signed-off commit instead of force-pushing. Also allow maintainers to sign off on behalf of contributors. Signed-off-by: UncleSp1d3r --- .github/dco.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .github/dco.yml diff --git a/.github/dco.yml b/.github/dco.yml new file mode 100644 index 00000000..1f94d940 --- /dev/null +++ b/.github/dco.yml @@ -0,0 +1,3 @@ +allowRemediationCommits: + individual: true + thirdParty: true From d2dc863bb94a1b48e39e065478b6b5227c9e4cff Mon Sep 17 00:00:00 2001 From: UncleSp1d3r Date: Sun, 15 Feb 2026 18:02:13 -0500 Subject: [PATCH 05/15] docs(readme): add Mergify status badge and link Signed-off-by: UncleSp1d3r --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 1b0e5135..bf01f709 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,10 @@ [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/EvilBit-Labs/libmagic-rs/badge)](https://scorecard.dev/viewer/?uri=github.com/EvilBit-Labs/libmagic-rs) [![Crates.io](https://img.shields.io/crates/v/libmagic-rs)](https://crates.io/crates/libmagic-rs) [![License](https://img.shields.io/crates/l/libmagic-rs)](https://github.com/EvilBit-Labs/libmagic-rs/blob/main/LICENSE) +[![Mergify Status][mergify-status]][mergify] + +[mergify]: https://mergify.com +[mergify-status]: https://img.shields.io/endpoint.svg?url=https://api.mergify.com/v1/badges/EvilBit-Labs/libmagic-rs A pure-Rust implementation of libmagic, the library that powers the `file` command for identifying file types. This project provides a memory-safe, efficient alternative to the C-based libmagic library. From e1f2aabaa90a7c9c9a73160db72798701ad480d8 Mon Sep 17 00:00:00 2001 From: UncleSp1d3r Date: Sun, 15 Feb 2026 18:08:14 -0500 Subject: [PATCH 06/15] docs: update AGENTS.md CI/CD section for Mergify merge queue Replace outdated .kiro/hooks reference with Mergify merge queue description. Add merge queue details to quick reference section. Signed-off-by: UncleSp1d3r --- AGENTS.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 60605577..06f8289f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -399,7 +399,7 @@ This pattern ensures build-time failures (e.g., invalid magic files) are properl ### Automated Checks -The project includes automated CI checks via `.kiro/hooks/ci-auto-fix.kiro.hook`: +The project uses GitHub Actions CI with Mergify merge queue: 1. **Formatting**: `cargo fmt` for consistent code style 2. **Linting**: `cargo clippy -- -D warnings` for best practices @@ -430,7 +430,9 @@ All pull requests require review before merging. Reviews are performed by mainta - **Style**: Follows project conventions, passes `cargo fmt` and `cargo clippy -- -D warnings` - **Documentation**: Public APIs have rustdoc with examples, AGENTS.md updated if architecture changes -CI must pass before merge. Branch protection enforces these checks on the `main` branch. +CI must pass before merge. Mergify merge queue and merge protections enforce these checks. +PRs enter the merge queue when approved (or automatically for release-plz/dependabot). +Mergify rebases against main, runs CI, and squash-merges on success. ## Project Context @@ -509,6 +511,9 @@ This guide ensures consistent, high-quality development practices for the libmag ## Quick Reference +- Merging is managed by Mergify merge queue -- PRs are squash-merged after CI passes +- `.mergify.yml` configures merge queue rules, auto-queue, and merge protections +- `cargo deny check` uses `deny.toml` (default) -- do not specify a custom config path - `.github/workflows/release.yml` is auto-generated by cargo-dist -- do not modify manually - All `.rs` files must have copyright and SPDX headers (see any source file for format) - `Cargo.lock` and `mise.lock` are committed for reproducible builds -- do not gitignore From 0afa92f85ed6d6dac061e283bd3442a09a1b7d57 Mon Sep 17 00:00:00 2001 From: UncleSp1d3r Date: Sun, 15 Feb 2026 18:10:53 -0500 Subject: [PATCH 07/15] chore: add do-not-merge exclusion to auto-update rule Also use explicit empty mapping for update action per YAML best practice. Signed-off-by: UncleSp1d3r --- .mergify.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.mergify.yml b/.mergify.yml index ca16fc85..4622ae29 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -47,8 +47,9 @@ pull_request_rules: - -conflict - -draft - -author = dependabot[bot] + - label != do-not-merge actions: - update: + update: {} merge_protections: - name: CI must pass From 35b44ebc1e90253278ed294c9270f280bc9ed822 Mon Sep 17 00:00:00 2001 From: UncleSp1d3r Date: Sun, 15 Feb 2026 18:23:22 -0500 Subject: [PATCH 08/15] chore: require maintainer team approval to queue PRs Change the approval condition from any reviewer to a member of the @maintainers team. Prevents external PRs from being queued based solely on bot approvals (e.g., CodeRabbit). Signed-off-by: UncleSp1d3r --- .mergify.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.mergify.yml b/.mergify.yml index 4622ae29..d5ded79d 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -11,10 +11,10 @@ queue_rules: - check-success = coverage pull_request_rules: - - name: Queue PRs when approved + - name: Queue PRs when approved by maintainer conditions: - base = main - - "#approved-reviews-by >= 1" + - "approved-reviews-by=@maintainers" - label != do-not-merge actions: queue: From de6f600c646b75fe2e33f0769362f3a01232f389 Mon Sep 17 00:00:00 2001 From: UncleSp1d3r Date: Sun, 15 Feb 2026 18:28:33 -0500 Subject: [PATCH 09/15] ci(dist.github-action-commits): update actions/checkout and actions/upload-artifact versions Signed-off-by: UncleSp1d3r --- dist-workspace.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dist-workspace.toml b/dist-workspace.toml index bebb1174..13795241 100644 --- a/dist-workspace.toml +++ b/dist-workspace.toml @@ -50,7 +50,7 @@ publish-jobs = [ "homebrew" ] # GitHub release configuration [dist.github-action-commits] -"actions/checkout" = "v6" +"actions/checkout" = "v6.0.2" "actions/download-artifact" = "v7" "actions/attest-build-provenance" = "v3" -"actions/upload-artifact" = "v6" +"actions/upload-artifact" = "v6.0.0" From a8f11b94158e873b983538c985c597bdd6e6ee3a Mon Sep 17 00:00:00 2001 From: UncleSp1d3r Date: Sun, 15 Feb 2026 18:31:10 -0500 Subject: [PATCH 10/15] chore: exclude release.yml from dependabot auto-queue release.yml is auto-generated by cargo-dist. Dependabot PRs that modify it would break the release workflow, so they require manual review instead of auto-queueing. Signed-off-by: UncleSp1d3r --- .mergify.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.mergify.yml b/.mergify.yml index d5ded79d..d4e07be3 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -34,6 +34,7 @@ pull_request_rules: - base = main - author = dependabot[bot] - label != do-not-merge + - -files~=\.github/workflows/release\.yml actions: review: type: APPROVE From 5a714477866b86f7a98539e5beead899b870a55a Mon Sep 17 00:00:00 2001 From: UncleSp1d3r Date: Sun, 15 Feb 2026 18:36:22 -0500 Subject: [PATCH 11/15] chore(docs): update maintainer role in CONTRIBUTING.md Signed-off-by: UncleSp1d3r --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cf4a3fc3..c14cd780 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -344,7 +344,7 @@ libmagic-rs uses a **maintainer-driven** governance model. Decisions are made by | Role | Responsibilities | Current | |------|-----------------|---------| -| **Maintainer** | Merge PRs, manage releases, set project direction, review security reports | [@unclesp1d3r](https://github.com/unclesp1d3r), [@kmelton](https://github.com/kmelton) | +| **Maintainer** | Merge PRs, manage releases, set project direction, review security reports | [@unclesp1d3r](https://github.com/unclesp1d3r), [@KryptoKat08](https://github.com/KryptoKat08) | | **Contributor** | Submit issues, PRs, and participate in discussions | Anyone following this guide | ### How Decisions Are Made From e32905422bf0f449ea8a67865e13a18ba9aa0a80 Mon Sep 17 00:00:00 2001 From: UncleSp1d3r Date: Sun, 15 Feb 2026 18:36:49 -0500 Subject: [PATCH 12/15] docs: streamline README for consumer audience Remove development/contributing sections (already in CONTRIBUTING.md), fix inaccurate stats (test count, supported types/operators), trim architecture and compatibility to essentials. 455 lines -> 199 lines. Signed-off-by: UncleSp1d3r --- README.md | 426 +++++++++++------------------------------------------- 1 file changed, 85 insertions(+), 341 deletions(-) diff --git a/README.md b/README.md index bf01f709..2cbf019f 100644 --- a/README.md +++ b/README.md @@ -16,125 +16,62 @@ A pure-Rust implementation of libmagic, the library that powers the `file` comma ## Project Status -**Active Development (Phase 1 MVP)** - The core file identification pipeline is functional. You can identify common file types using text magic files today. +**v0.1.1** -- The core file identification pipeline is functional. Common file types can be identified using text magic files today. -**Current Metrics:** - -- 17,000+ lines of Rust code -- 650+ tests with comprehensive coverage -- Zero unsafe code with memory safety guarantees +- 1,068 tests with >94% line coverage +- Zero unsafe code (`unsafe_code = "forbid"` enforced project-wide) - Zero warnings with strict clippy linting - -### What Works Today - -- **File type identification** - Identify files using text magic file databases -- **Text and JSON output** - Both output formats supported via `--json` flag -- **Custom magic files** - Use `--magic-file` to specify your own rules -- **Memory-mapped I/O** - Efficient file reading with bounds checking -- **Hierarchical rule matching** - Full nested rule evaluation -- **Platform detection** - Automatic magic file discovery on Unix systems - -### In Progress (Phase 1 Completion) - -- Multiple file support - Process multiple files in one command -- Stdin input - Pipe data via `rmagic -` -- Built-in fallback rules - Work without external magic files via `--use-builtin` -- Magdir directory loading - Load all files from a magic directory -- Compatibility testing - Validation against GNU `file` command output - -### Phase 1 Goals - -- 95%+ compatibility with GNU `file` for common file types -- >85% test coverage across all modules -- Complete documentation with rustdoc and mdbook site - -## Overview - -libmagic-rs is designed to replace libmagic with a safe, efficient Rust implementation that: - -- **Memory Safety**: Pure Rust with no unsafe code (except vetted crates) -- **Performance**: Uses memory-mapped I/O for efficient file reading -- **Compatibility**: Supports common magic file syntax (offsets, types, operators, nesting) -- **Extensibility**: Designed for modern use cases (PE resources, Mach-O, Go build info) -- **Multiple Output Formats**: Classic text output and structured JSON +- Published on [crates.io](https://crates.io/crates/libmagic-rs) ## Features -### Core Capabilities - -- Parse text magic files (DSL for byte-level file type detection) -- Evaluate magic rules against file buffers to identify file types -- Absolute offset specifications (indirect/relative in Phase 2) -- Multiple data types: byte, short, long, quad, string -- Hierarchical rule evaluation with proper nesting -- Memory-mapped file I/O for efficient processing -- Confidence scoring based on match depth +- Parse and evaluate text magic files (the stable, documented format) +- Identify files via CLI (`rmagic`) or as a library dependency +- Text and JSON output formats +- Built-in fallback rules for 10 common formats (ELF, PE, ZIP, TAR, GZIP, JPEG, PNG, GIF, BMP, PDF) +- Custom magic files via `--magic-file` +- Memory-mapped I/O with bounds checking +- Hierarchical rule evaluation with confidence scoring +- Stdin support (`rmagic -`) -### Output Formats +### Supported Magic File Syntax -**Text Output (Default)**: - -```text -ELF 64-bit LSB executable, x86-64, version 1 (SYSV) -``` - -**JSON Output**: - -```json -{ - "filename": "example.bin", - "matches": [ - { - "text": "ELF 64-bit LSB executable", - "offset": 0, - "value": "7f454c46", - "tags": [ - "executable", - "elf" - ], - "score": 90, - "mime_type": "application/x-executable" - } - ], - "metadata": { - "file_size": 8192, - "evaluation_time_ms": 2.3, - "rules_evaluated": 45 - } -} -``` +| Category | Supported | +|----------|-----------| +| **Types** | `byte`, `short`, `long`, `string` (with endianness and sign options) | +| **Operators** | `=`, `!=`, `&` (bitwise AND with optional mask) | +| **Offsets** | Absolute, from-end (indirect and relative are parsed but not yet evaluated) | +| **Directives** | `!:strength` (parsed; `!:mime`, `!:ext`, `!:apple` planned) | ## Quick Start ### Installation ```bash -# Clone the repository -git clone https://github.com/EvilBit-Labs/libmagic-rs.git -cd libmagic-rs - -# Build the project -cargo build --release - -# Run tests -cargo test +cargo install libmagic-rs ``` ### CLI Usage ```bash # Basic file identification -./target/release/rmagic file.bin +rmagic file.bin -# JSON output with metadata -./target/release/rmagic file.bin --json +# JSON output +rmagic file.bin --json -# Use custom magic file -./target/release/rmagic file.bin --magic-file custom.magic -``` +# Use built-in rules (no external magic file needed) +rmagic --use-builtin file.bin -> [!NOTE] -> Multiple file support (`rmagic file1.bin file2.bin`) and stdin input (`cat file | rmagic -`) are planned for Phase 1 completion. +# Custom magic file +rmagic --magic-file custom.magic file.bin + +# Multiple files +rmagic file1.bin file2.bin file3.bin + +# Read from stdin +cat file.bin | rmagic - +``` ### Library Usage @@ -155,63 +92,39 @@ let result = db.evaluate_buffer(&buffer)?; if let Some(mime) = result.mime_type { println!("MIME type: {}", mime); } -``` -> [!NOTE] -> The library currently supports text-format magic files. Binary `.mgc` format support is planned for Phase 2, following the proven OpenBSD approach of parsing text format directly. +// Or use built-in rules (no external files needed) +let db = MagicDatabase::with_builtin_rules(); +let result = db.evaluate_file("example.bin")?; +``` ## Architecture -The project follows a parser-evaluator architecture: - ```text -Magic File → Parser → AST → Evaluator → Match Results → Output Formatter - ↓ -Target File → Memory Mapper → File Buffer +Magic File --> Parser --> AST --> Evaluator --> Match Results --> Output Formatter + | +Target File --> Memory Mapper --> File Buffer ``` -### Core Modules - -- **Parser** (`src/parser/`): Magic file DSL parsing into Abstract Syntax Tree - - `ast.rs`: Core AST data structures - - `grammar.rs`: nom-based parsing components - - `mod.rs`: Parser interface with text magic file support -- **Evaluator** (`src/evaluator/`): Rule evaluation engine - - Offset resolution (absolute offsets supported, indirect in Phase 2) - - Type interpretation with endianness handling - - Comparison and bitwise operations - - Confidence scoring based on match depth -- **Output** (`src/output/`): Result formatting - - Text formatter (GNU `file` compatible) - - JSON formatter with metadata -- **IO** (`src/io/`): File access utilities - - Memory-mapped file buffers with FileBuffer - - Safe bounds checking with comprehensive error handling - - Resource management with RAII patterns - -### Key Data Structures +| Module | Purpose | +|--------|---------| +| `parser/` | Magic file DSL parsing into AST (nom-based) | +| `evaluator/` | Rule evaluation with offset resolution, type interpretation, operator matching | +| `output/` | Text (GNU `file` compatible) and JSON formatting | +| `io/` | Memory-mapped file buffers with safe bounds checking | + +### Key Types ```rust pub struct MagicRule { - pub offset: OffsetSpec, - pub typ: TypeKind, - pub op: Operator, - pub value: Value, - pub message: String, - pub children: Vec, - pub level: u32, -} - -pub enum OffsetSpec { - Absolute(i64), - Indirect { - base_offset: i64, - pointer_type: TypeKind, - adjustment: i64, - endian: Endianness, - }, - Relative(i64), - FromEnd(i64), + pub offset: OffsetSpec, // Where to look in the file + pub typ: TypeKind, // How to interpret the bytes + pub op: Operator, // How to compare + pub value: Value, // What to compare against + pub message: String, // Output on match + pub children: Vec, // Nested sub-rules + pub level: u32, // Nesting depth + pub strength_modifier: Option, } pub enum TypeKind { @@ -221,182 +134,30 @@ pub enum TypeKind { String { max_length: Option }, } -pub enum Value { - Uint(u64), - Int(i64), - Bytes(Vec), - String(String), +pub enum OffsetSpec { + Absolute(i64), + FromEnd(i64), + Indirect { base_offset, pointer_type, adjustment, endian }, + Relative(i64), } ``` -## Development - -### Prerequisites - -- Rust 1.85+ (2024) -- Cargo -- Git - -### Building - -```bash -# Development build -cargo build - -# Release build with optimizations -cargo build --release - -# Check without building -cargo check -``` - -### Testing - -```bash -# Run all tests (650+ tests) -cargo test - -# Run with nextest (faster test runner) -cargo nextest run - -# Run specific test module -cargo test parser::grammar::tests -cargo test parser::ast::tests - -# Test with coverage reporting -cargo llvm-cov --html - -# Run compatibility tests against GNU file -cargo test --test compatibility -``` - -**Current Test Coverage:** - -- 650+ tests covering parser, evaluator, I/O, and CLI components -- Parser testing for numbers, offsets, operators, values, and rule hierarchies -- Evaluator testing for rule matching and confidence scoring -- I/O testing for FileBuffer, memory mapping, and error handling -- CLI testing for argument parsing and output formatting -- Compatibility testing against GNU `file` command output -- Target: >85% test coverage for Phase 1 completion - -### Compatibility Testing - -We maintain strict compatibility with the original [file project](https://github.com/file/file/blob/7ed3febfcd616804a2ec6495b3e5f9ccb6fc5f8f/tests/README) by testing against their complete test suite. This ensures our implementation produces identical results to the original libmagic library. - -The compatibility test suite includes: - -- All test files from the original file project -- Expected output validation against GNU file command -- Performance regression testing -- Edge case handling verification - -### Code Quality - -```bash -# Format code -cargo fmt - -# Lint code (strict mode) -cargo clippy -- -D warnings - -# Generate documentation -cargo doc --open - -# Run benchmarks -cargo bench -``` - -### Project Structure - -```text -libmagic-rs/ -├── Cargo.toml # Project manifest and dependencies -├── src/ -│ ├── lib.rs # Library root and public API -│ ├── main.rs # CLI binary entry point -│ ├── parser/ # Magic file parser module -│ ├── evaluator/ # Rule evaluation engine -│ ├── output/ # Output formatting -│ ├── io/ # Memory-mapped file I/O -│ └── error.rs # Error types and handling -├── tests/ # Integration tests -├── benches/ # Performance benchmarks -├── magic/ # Magic file databases -└── docs/ # Documentation -``` - -## Performance - -The implementation includes: - -- **Memory-mapped I/O**: Efficient file access without loading entire files -- **Zero-copy operations**: Minimize allocations during evaluation -- **Early termination**: Stop evaluation at first match when appropriate - -**Planned optimizations (Phase 2+):** - -- Aho-Corasick indexing for fast multi-pattern string search -- Compiled rule caching for repeated use -- Performance benchmarking against libmagic - -### Benchmarks - -Performance targets (Phase 3): - -- Match or exceed libmagic performance within 10% -- Memory usage comparable to libmagic -- Fast startup with large magic databases - ## Compatibility -### Magic File Support - -**Supported (Phase 1):** - -- Text magic file format (the stable, documented format) -- Hierarchical rule nesting with indentation levels -- Absolute offset specifications -- Core types: byte, short, long, quad, string -- Core operators: `=`, `!=`, `&`, `<`, `>` -- Endianness handling for multi-byte types -- Magdir-style directory loading - -**Phase 2:** - -- Binary `.mgc` compiled format -- Indirect offset resolution -- Regex patterns - -### Text-First Approach +libmagic-rs follows the **OpenBSD approach**: parse text magic files directly, prioritizing simplicity and correctness. Text magic files are stable across libmagic versions and work unchanged from system installations (`/usr/share/misc/magic`). -libmagic-rs follows the **OpenBSD approach**: parse text magic files directly, prioritizing simplicity and correctness over binary format complexity. This is the same strategy used by OpenBSD's `file` implementation and other successful reimplementations like PolyFile. - -**Why text format first?** - -- Text magic format is stable across libmagic versions -- Binary `.mgc` has version lock-in issues (format changes between releases) -- Simpler codebase (~1,500 lines vs ~3,000 for binary parsing) -- Easier debugging and testing - -### Migration from libmagic - -The library provides a migration path from C-based libmagic: - -- Similar API patterns where possible -- Compatibility testing with GNU `file` command results -- Text magic files work unchanged from system installations +Compatibility is validated against the [original file project](https://github.com/file/file) test suite. ## Security -- **Memory Safety**: No unsafe code except in vetted dependencies -- **Bounds Checking**: All buffer access protected by bounds checking -- **Safe File Handling**: Graceful handling of truncated/corrupted files -- **Fuzzing Integration**: Robustness testing with malformed inputs +- **Memory Safety**: `unsafe_code = "forbid"` enforced project-wide +- **Bounds Checking**: All buffer access protected +- **Resource Limits**: Configurable recursion depth, string length, and per-file timeout +- **Fuzzing**: Robustness testing with malformed inputs ### Verifying Releases -All release artifacts are cryptographically signed via [Sigstore](https://www.sigstore.dev/) using GitHub Attestations. To verify a downloaded artifact: +All release artifacts are signed via [Sigstore](https://www.sigstore.dev/) using GitHub Attestations: ```bash gh attestation verify --repo EvilBit-Labs/libmagic-rs @@ -404,51 +165,34 @@ gh attestation verify --repo EvilBit-Labs/libmagic-rs See the [release verification guide](https://evilbitlabs.io/libmagic-rs/release-verification.html) for details. -## Contributing - -1. Fork the repository -2. Create a feature branch (`git checkout -b feature/amazing-feature`) -3. Make your changes -4. Run tests and ensure they pass (`cargo test`) -5. Run clippy to check for issues (`cargo clippy -- -D warnings`) -6. Commit your changes (`git commit -m 'Add amazing feature'`) -7. Push to the branch (`git push origin feature/amazing-feature`) -8. Open a Pull Request - -### Development Guidelines - -- Follow Rust naming conventions -- Add tests for new functionality -- Update documentation for API changes -- Ensure all code passes `cargo clippy -- -D warnings` -- Maintain >85% test coverage - -## License - -This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details. - ## Roadmap -See [ROADMAP.md](ROADMAP.md) for the full roadmap with linked issues, or [GitHub Milestones](https://github.com/EvilBit-Labs/libmagic-rs/milestones) for detailed issue tracking. +See [ROADMAP.md](ROADMAP.md) for the full roadmap, or [GitHub Milestones](https://github.com/EvilBit-Labs/libmagic-rs/milestones) for issue tracking. | Milestone | Focus | |-----------|-------| -| **v0.1.0** (current) | MVP: parser, evaluator, CLI, built-in rules, 94%+ test coverage | +| **v0.1.x** (current) | MVP: parser, evaluator, CLI, built-in rules, 94%+ test coverage | | **v0.2.0** | Comparison operators, bitwise XOR/NOT, indirect/relative offsets, 64-bit integers | | **v0.3.0** | Regex, float/double, date/timestamp, pascal strings, meta-types | | **v0.4.0** | Builder API, JSON metadata, parse warnings, improved errors | -| **v1.0.0** | 95%+ GNU `file` compatibility, stable API, crates.io publication | +| **v1.0.0** | 95%+ GNU `file` compatibility, stable API | + +## Contributing + +See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, coding guidelines, and submission process. + +## License + +Licensed under the Apache License 2.0 - see [LICENSE](LICENSE) for details. ## Support -- **Documentation**: [Project Documentation](docs/) -- **Issues**: [GitHub Issues](https://github.com/EvilBit-Labs/libmagic-rs/issues) -- **Discussions**: [GitHub Discussions](https://github.com/EvilBit-Labs/libmagic-rs/discussions) +- [Documentation](https://evilbitlabs.io/libmagic-rs/) +- [GitHub Issues](https://github.com/EvilBit-Labs/libmagic-rs/issues) +- [GitHub Discussions](https://github.com/EvilBit-Labs/libmagic-rs/discussions) ## Acknowledgments -- [Ian Darwin](https://www.darwinsys.com/file/) for the original file command and libmagic implementation +- [Ian Darwin](https://www.darwinsys.com/file/) for the original file command and libmagic - [Christos Zoulas](https://www.darwinsys.com/file/) and the current libmagic maintainers -- The original libmagic project for establishing the magic file format standard -- Rust community for excellent tooling and ecosystem -- Contributors and testers who help improve the project +- The Rust community for excellent tooling and ecosystem From 3a1f21c0bd8412fe7e9138f61b40a7debd8733ab Mon Sep 17 00:00:00 2001 From: UncleSp1d3r Date: Sun, 15 Feb 2026 18:41:11 -0500 Subject: [PATCH 13/15] chore: normalize quoting in dependabot.yml Signed-off-by: UncleSp1d3r --- .github/dependabot.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1b912e93..5f6b2bd2 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,11 +9,11 @@ updates: - package-ecosystem: "github-actions" directory: "/" schedule: - interval: weekly + interval: "weekly" rebase-strategy: "disabled" - package-ecosystem: "devcontainers" directory: "/" schedule: - interval: weekly + interval: "weekly" rebase-strategy: "disabled" From f2e62c177cd0c42cd54020824edaba7c5ecc38a8 Mon Sep 17 00:00:00 2001 From: UncleSp1d3r Date: Sun, 15 Feb 2026 18:47:03 -0500 Subject: [PATCH 14/15] ci: implement three-tier PR queueing in Mergify Tier 1 (maintainers): queue when 'lgtm' label added -- lets maintainers hold PRs until ready without self-approval issues. Tier 2 (trusted bots): dependabot and release-plz auto-queue when checks pass, unchanged from before. Tier 3 (everyone else): external contributors and copilot require approval from a @maintainers team member before queueing. Signed-off-by: UncleSp1d3r --- .mergify.yml | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/.mergify.yml b/.mergify.yml index d4e07be3..a8b23c12 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -11,15 +11,18 @@ queue_rules: - check-success = coverage pull_request_rules: - - name: Queue PRs when approved by maintainer + # Tier 1: Maintainer PRs -- queue when maintainer adds 'lgtm' label + - name: Queue maintainer PRs with lgtm label conditions: - base = main - - "approved-reviews-by=@maintainers" + - "author=@maintainers" + - label = lgtm - label != do-not-merge actions: queue: name: default + # Tier 2: Trusted bot PRs -- auto-queue when checks pass - name: Auto-queue release-plz PRs conditions: - base = main @@ -42,6 +45,19 @@ pull_request_rules: queue: name: default + # Tier 3: All other PRs (external contributors, copilot) -- require maintainer approval + - name: Queue external PRs when approved by maintainer + conditions: + - base = main + - -"author=@maintainers" + - author != dependabot[bot] + - -"head ~= ^release-plz-" + - "approved-reviews-by=@maintainers" + - label != do-not-merge + actions: + queue: + name: default + - name: Keep PRs up to date with main conditions: - base = main From 7aa194eb799b163ed3eb1ec987fcafaf409c2a64 Mon Sep 17 00:00:00 2001 From: UncleSp1d3r Date: Sun, 15 Feb 2026 18:49:34 -0500 Subject: [PATCH 15/15] fix(ci): correct Mergify negation syntax for conditions The `-` negation prefix must be inside YAML quotes, not outside. Signed-off-by: UncleSp1d3r --- .mergify.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.mergify.yml b/.mergify.yml index a8b23c12..bdd69f71 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -49,9 +49,9 @@ pull_request_rules: - name: Queue external PRs when approved by maintainer conditions: - base = main - - -"author=@maintainers" + - "-author=@maintainers" - author != dependabot[bot] - - -"head ~= ^release-plz-" + - "-head ~= ^release-plz-" - "approved-reviews-by=@maintainers" - label != do-not-merge actions: