Skip to content
← Projects

OZINT

A local OSINT investigation cockpit in Rust and React: type a seed, and a tree of sourced findings grows one deliberate click at a time.

OZINT is an OSINT investigation cockpit that I build in the evenings. You type a seed value (a username, an email, an IP, a domain, a file hash, an image, a coordinate pair, a CVE id, a phone number) and a tree of typed findings grows from it. The engine is written in Rust, the cockpit in React, and everything runs on your own machine: no hosted service, no account, no telemetry.

The problem

Automated OSINT tools tend to drown you. They recurse on their own and hand you a thousand nodes of which four matter, with no way to tell where each one came from. I wanted the opposite: a tool where the tree keeps the shape of the analyst's actual reasoning.

How it works

A seed is classified into one of twelve entity types. Each type has a plan, and a "layer" of tools fires against the seed in parallel, in phases, with later phases conditional on what earlier ones found. Findings become child nodes, and every child stays idle until you decide it is worth pursuing. Nothing recurses on its own, by design.

The catalogue has 62 tools, 45 of which need no API key. Each one is an HTTP call to a documented API plus a parser, with no model in the loop. A language model is used in exactly two optional places (narrating a settled layer, and disambiguating a seed whose type is unclear), and both degrade cleanly when none is configured.

Decisions I care about

The workspace is five Rust crates (core, database, LLM client, engine, axum server) plus the cockpit, which has no CSS framework and takes all its styling from one token table. About 1,100 Rust tests and 183 cockpit tests pass, and clippy is warning-free.

Honest limits

A green suite is weaker evidence than it looks: most source tests feed an already-parsed response to the parser, so they do not catch an upstream changing its format. I fire real seeds against a real server before trusting a source. The biggest known gap is that some tools return findings as readable rows instead of pursuable child nodes, so firing on an email grows the tree less than the product promises. I have tracked it tool by tool and fixed part of it, but it is not closed.

I wrote down what the tool refuses to do (no crawl mode, no credential stuffing, no breach dumps, no monitoring) and a responsible-use section, because aggregating public data about a person can be harmful. Next is closing that gap, then testing the network layer itself.