← All articles

Designing a Forensically Sound Evidence Container

How we designed macfor's evidence container format to meet ISO 27037 requirements while remaining practical for real-world investigations.

Toby VervaartFounder & Lead Developer

One of the most critical aspects of forensic collection is ensuring evidence integrity. This post explains the design decisions behind macfor's evidence container format.

Design Requirements

We started with several non-negotiable requirements:

  1. Tamper evidence: Any modification must be detectable
  2. Self-documenting: The container must explain what it contains
  3. Chain of custody: Every action must be logged
  4. Portable: Standard formats that any tool can read
  5. Practical: Fast to create and reasonable in size

The Container Structure

macfor produces a ZIP archive with a specific internal structure:

evidence-container.zip
├── manifest.json              # What was collected
├── chain-of-custody.json      # Action log
├── hashes.json                # SHA-256 of every file
├── artifacts/                 # Raw collected files
├── records/                   # Parsed structured data
└── logs/                      # Collection logs

Why ZIP?

ZIP was chosen for several reasons:

  • Universal support: Every OS can open ZIP files natively
  • Streaming creation: Files can be added without buffering the entire archive
  • Per-file compression: Each file can be compressed independently
  • Metadata preservation: Timestamps and attributes are stored

Manifest Design

The manifest.json file documents the collection:

{
  "collection_id": "550e8400-e29b-41d4-a716-446655440000",
  "tool_version": "1.0.0",
  "collection_time": "2026-01-28T10:30:00Z",
  "source": {
    "type": "live",
    "hostname": "macbook-pro.local",
    "os_version": "14.2.1"
  },
  "plugins": [
    {
      "id": "shell.history",
      "files_collected": 3,
      "records_created": 1250
    }
  ]
}

Hash Verification

Every file added to the container is hashed with SHA-256:

{
  "artifacts/shell/bash_history": "sha256:abc123...",
  "artifacts/shell/zsh_history": "sha256:def456..."
}

This allows verification that no files have been modified since collection.

Chain of Custody

The chain-of-custody.json file logs every significant action:

{
  "entries": [
    {
      "timestamp": "2026-01-28T10:30:01Z",
      "action": "collection_started",
      "actor": "macfor 1.0.0"
    },
    {
      "timestamp": "2026-01-28T10:30:02Z",
      "action": "file_added",
      "target": "artifacts/shell/bash_history",
      "actor": "shell.history"
    }
  ]
}

ISO 27037 Alignment

Our format aligns with ISO 27037 (Guidelines for identification, collection, acquisition and preservation of digital evidence):

| Requirement | Implementation | |-------------|----------------| | Reproducibility | Deterministic collection with manifest | | Justifiability | Chain of custody documents all actions | | Auditability | Hash verification proves integrity | | Repeatability | Same input produces same artifacts |

Practical Considerations

Compression Trade-offs

We use ZIP's DEFLATE compression for text files but store binary files uncompressed. This balances size reduction with extraction speed.

Large File Handling

For very large files (like database dumps), we stream directly to the ZIP writer rather than buffering in memory.

Atomic Operations

If collection fails midway, the partial container is automatically removed. You either get a complete, valid container or nothing.

Conclusion

The evidence container format is central to macfor's value proposition. By combining standard formats with forensic best practices, we provide evidence that stands up to scrutiny.

For implementation details, see the technical documentation.