trash-forensic 0.1.0

Forensic anomaly analysis for Windows Recycle Bin $I/$R artifacts — purged-content detection, path-traversal in stored names, and deletion-time anomalies, emitting forensicnomicon findings
Documentation

trash-forensic

trash-forensic trash-core Docs.rs License: Apache-2.0 CI Sponsor

Point it at a $Recycle.Bin, get back severity-graded Recycle Bin anomalies — content purged out from under its surviving metadata, path-traversal in a stored name, and missing deletion times — as forensicnomicon::report::Findings.

[dependencies]
trash-forensic = "0.1"   # pulls in trash-core
use trash_core::{parse_index, scan_pairs};
use trash_forensic::audit_pair;

for pair in scan_pairs(recycle_bin_dir)? {
    let bytes = std::fs::read(&pair.index_path)?;
    if let Ok(index) = parse_index(&bytes) {
        for finding in audit_pair(&index, &pair) {
            println!("[{:?}] {}{}", finding.severity, finding.code, finding.note);
        }
    }
}
# Ok::<(), std::io::Error>(())

audit_pair grades a parsed $I record together with its $I/$R pairing. A well-formed record — content present, deletion time set, no traversal — yields no findings. Damaged or hostile $I bytes surface from parse_index as a typed error, never a panic.

The anomaly codes

Each finding is an observation ("consistent with …"); the examiner draws the conclusions. Codes are a stable, published contract.

Code Category Severity What it observes
RECYCLEBIN-CONTENT-PURGED Residue Medium A $I index survives but its $R content file is gone — consistent with the content having been purged while its metadata remains
RECYCLEBIN-PATH-TRAVERSAL Concealment High The stored original path escapes its directory via a .. component — consistent with a crafted name rather than a normal shell deletion
RECYCLEBIN-DELETION-TIME-MISSING Integrity Low The deletion FILETIME is zero — recorded but never set, or cleared

audit_pair returns one graded report::Finding per anomaly, each stamped with the analyzer name, version, and the offending $I filename as scope, and carrying the offending original_path as evidence. The typed AnomalyKind (with code, severity, category, and note) is public for callers that want the domain enum before conversion.

The two-crate split

This crate is the analyzer; the reader is trash-core (parses the $I index and pairs $I/$R by a directory scan). The split mirrors ntfs-core/ntfs-forensic. Together they feed issen for cross-artifact correlation, so Recycle Bin evidence aggregates uniformly with the rest of the forensic fleet.

Trust, but verify

Built for $Recycle.Bin directories lifted from potentially hostile systems: #![forbid(unsafe_code)]; panic-free on crafted input (the workspace denies clippy::unwrap_used / expect_used in production code); both the reader and the full parse → audit pipeline are fuzzed with cargo-fuzz, and trash-core is cross-checked against the C tool rifiuti2. See docs/validation.md.


Privacy Policy · Terms of Service · © 2026 Security Ronin Ltd