A model, not an engine
Knowledge and reasoning change at different speeds. The fact that memcpy's size argument is dangerous does not change when a graph engine gets rewritten, and it is useful to anything that can resolve a symbol, not just one tool. So the models live on their own, as data.
Atropos figures out none of it by itself. The engine (Lachesis) owns propagation, reachability and guard reasoning. Atropos is the lookup table that says this specific argument is dangerous, and here is why. Keeping it in its own permissively licensed repo means the taxonomy can be versioned, reviewed and grown on its own schedule.
What you get
A catalog you read, not a library you import.
Just data
One row per fact: a resolvable symbol, an access path, and a role. No engine, no import, no dependency. Consuming it is reading JSON.
It says "watch this", not "this is a bug"
Models mark sources, sinks and sanitizers. The verdict is left to the engine and the human, so there is no false confidence baked in.
Precise attachment
Each fact names exactly what to watch: Argument[n], ReturnValue, Receiver, or in→out for a flow summary.
Four languages, 27 kinds
C, Python, JavaScript and TypeScript across buffer overflow, command, SQL and template injection, path traversal, SSRF, deserialization, prototype pollution, weak crypto, and more.
Validated on every change
Schema shape, unique ids and grammatical access paths are gated in CI, so the catalog stays consistent as it grows past a thousand facts.
Versioned and reviewable
Kept in its own repo so the taxonomy can be reviewed and grown on its own schedule, decoupled from any single engine.
Pack-ready
A versioned manifest, deterministic archive, license file, checksum and provenance sidecar make the catalog portable beyond one checkout.
Quickstart
The tooling is standard-library Python, zero dependencies. Contributors can validate the catalog, see coverage, and bind models to real graph nodes; consumers can download the verified model pack from Releases.
git clone https://github.com/UnboundCompute/atropos && cd atropos python3 tools/validate.py # schema, unique ids, access paths python3 tools/validate_pack.py # pack version and coverage python3 tools/stats.py # coverage by language / role / kind python3 tools/bind.py fixtures/c_buffer.index.json # resolve models to graph nodes python3 tools/build_pack.py --output /tmp/atropos-core.zip # portable pack python3 tools/install_pack.py /tmp/atropos-core.zip --sha256 <digest> # install it safely
What a fact looks like
One entry is one row of data: a resolvable symbol, an access path, and a role.
{
"id": "c.mem.memcpy.n",
"language": "c", "method": "memcpy",
"signature": "void *memcpy(void *dest, const void *src, size_t n)",
"access_path": "Argument[2]", "role": "sink", "kind": "buffer-size",
"cwe": ["CWE-787", "CWE-120", "CWE-190"], "confidence": "high"
}
memcpy's third argument, the size, is a buffer-size sink. Atropos only says watch this. Whether a given call is a real bug is up to the engine, does tainted data reach it, and the human, is the length actually bounded upstream.
Atropos is the taint knowledge base our hosted autonomous security researcher reasons over. On its own it is just data; paired with Lachesis, each fact resolves against a real graph. Candidate rows stay separate from verified consumer models.
Pairs with Lachesis →