{"id":51595160,"url":"https://github.com/securityronin/forensic-vfs","last_synced_at":"2026-07-11T18:01:37.007Z","repository":{"id":369777740,"uuid":"1291586178","full_name":"SecurityRonin/forensic-vfs","owner":"SecurityRonin","description":"Read-only forensic VFS contracts — the ImageSource positioned-read byte source, PathSpec locators, and the FileSystem trait; the KNOWLEDGE leaf every fleet reader implements.","archived":false,"fork":false,"pushed_at":"2026-07-06T23:55:23.000Z","size":0,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-07T00:04:55.708Z","etag":null,"topics":["dfir","digital-forensics","disk-image","filesystem","forensics","incident-response","rust","vfs"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SecurityRonin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-07-06T23:49:06.000Z","updated_at":"2026-07-06T23:49:19.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/SecurityRonin/forensic-vfs","commit_stats":null,"previous_names":["securityronin/forensic-vfs"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/SecurityRonin/forensic-vfs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SecurityRonin%2Fforensic-vfs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SecurityRonin%2Fforensic-vfs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SecurityRonin%2Fforensic-vfs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SecurityRonin%2Fforensic-vfs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SecurityRonin","download_url":"https://codeload.github.com/SecurityRonin/forensic-vfs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SecurityRonin%2Fforensic-vfs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35370428,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-11T02:00:05.354Z","response_time":104,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dfir","digital-forensics","disk-image","filesystem","forensics","incident-response","rust","vfs"],"created_at":"2026-07-11T18:01:35.429Z","updated_at":"2026-07-11T18:01:36.998Z","avatar_url":"https://github.com/SecurityRonin.png","language":"Rust","funding_links":["https://github.com/sponsors/h4x0r"],"categories":[],"sub_categories":[],"readme":"# forensic-vfs\n\n[![Crates.io](https://img.shields.io/crates/v/forensic-vfs.svg)](https://crates.io/crates/forensic-vfs)\n[![docs.rs](https://img.shields.io/docsrs/forensic-vfs)](https://docs.rs/forensic-vfs)\n[![Rust 1.85+](https://img.shields.io/badge/rust-1.85%2B-blue.svg)](https://www.rust-lang.org)\n[![License: Apache-2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)\n[![Sponsor](https://img.shields.io/badge/sponsor-h4x0r-ea4aaa?logo=github-sponsors)](https://github.com/sponsors/h4x0r)\n\n[![CI](https://github.com/SecurityRonin/forensic-vfs/actions/workflows/ci.yml/badge.svg)](https://github.com/SecurityRonin/forensic-vfs/actions/workflows/ci.yml)\n[![Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen.svg)](https://github.com/SecurityRonin/forensic-vfs/actions/workflows/ci.yml)\n[![unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/)\n\n**One read-only, positioned-read byte edge — `ImageSource` — that every disk, container, and filesystem reader in the fleet speaks, so a whole evidence stack (`E01 → GPT → BitLocker → NTFS`) composes as a single `Arc\u003cdyn ImageSource\u003e` that N workers read in parallel and no code path can write.**\n\n`forensic-vfs` is the KNOWLEDGE-leaf contract crate of the universal forensic VFS. It defines the layered model — byte source, volume system, crypto layer, filesystem, and the recursive `PathSpec` locator — and nothing else: no format parsing, no reader dependencies. Readers implement these traits; the engine (`forensic-vfs-engine`) and the `disk4n6` CLI compose them.\n\n## The one decision that shapes everything\n\n```rust\npub trait ImageSource: Send + Sync {\n    fn len(\u0026self) -\u003e u64;\n    fn read_at(\u0026self, offset: u64, buf: \u0026mut [u8]) -\u003e Result\u003cusize, VfsError\u003e;\n    // no seek cursor, and no write method — anywhere\n}\n```\n\nPositioned reads (`read_at`) carry no cursor, so one source is shared across threads by `\u0026self` — a `Read + Seek` cursor's `\u0026mut self` cannot. And there is no write method to misuse: **evidence is read-only in the type system, not by convention.** A write is uncompilable.\n\n## Implement a reader in 30 seconds\n\n```rust\nuse forensic_vfs::{ImageSource, VfsResult};\n\nstruct RawFile(std::fs::File, u64);\n\nimpl ImageSource for RawFile {\n    fn len(\u0026self) -\u003e u64 { self.1 }\n    fn read_at(\u0026self, offset: u64, buf: \u0026mut [u8]) -\u003e VfsResult\u003cusize\u003e {\n        use std::os::unix::fs::FileExt;\n        Ok(self.0.read_at(buf, offset)?)   // positioned, lock-free, parallel-safe\n    }\n}\n```\n\n`forensic-vfs` ships `FileSource` (this, cross-platform), `SubRange` (a byte window that is itself an `ImageSource`), and `SourceCursor` (a `Read + Seek` bridge for legacy call sites) — so most readers wrap an existing source rather than write one.\n\n## Address any node with a `PathSpec`\n\nA `PathSpec` is the recursive, self-describing locator a finding cites and a session re-opens. It round-trips byte-for-byte through a canonical URI:\n\n```rust\nuse forensic_vfs::PathSpec;\n\nlet spec = PathSpec::from_uri(\n    \"fvfs:os:%2Fevidence%2FDC01.E01|container:ewf|volume:gpt,1|fs:ntfs,p/Windows/System32/config/SYSTEM\",\n)?;\nassert_eq!(PathSpec::from_uri(\u0026spec.to_uri())?, spec); // lossless\n# Ok::\u003c(), forensic_vfs::VfsError\u003e(())\n```\n\nEvery byte outside `[A-Za-z0-9._-]` is percent-encoded, so a Windows path containing `/` or a non-UTF-8 filename survives intact. Credentials never live in the address — they are supplied out-of-band at resolve time.\n\n## Trust but verify\n\n- **Panic-free.** `unsafe_code = forbid`; no `unwrap`/`expect`/`panic!` in production; every offset/length read goes through bounded readers that return 0, never panic, out of range.\n- **Fuzzed.** The `PathSpec` URI parser and the bounded readers are fuzzed — 15.7M + 20.2M executions with no panic, the round-trip invariant holding throughout.\n- **100% line coverage**, object-safety of every trait proven by a reader double driven through `Arc\u003cdyn Trait\u003e`.\n\n## Where this fits\n\n`forensic-vfs` realizes Phase 1 of the universal forensic VFS. The layers above it are in development:\n\n| Crate | Role | Status |\n|---|---|---|\n| **`forensic-vfs`** | byte source, volume/crypto/filesystem traits, `PathSpec` | this crate |\n| `forensic-vfs-engine` | registry + graph resolver over every reader | planned |\n| `disk-forensic` / `disk4n6` | thin CLI over the engine | evolving |\n\nSee the design in [`disk-forensic`](https://github.com/SecurityRonin/disk-forensic/blob/main/docs/design/2026-07-06-universal-forensic-vfs.md).\n\n---\n\n[Privacy Policy](https://securityronin.github.io/forensic-vfs/privacy/) · [Terms of Service](https://securityronin.github.io/forensic-vfs/terms/) · © 2026 Security Ronin Ltd\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsecurityronin%2Fforensic-vfs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsecurityronin%2Fforensic-vfs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsecurityronin%2Fforensic-vfs/lists"}