Phase 4's detection core, as a standalone crate. This is the part with no
competitor on Linux, and deliberately the part with no Linux in it —
file parsing and logic only, no fanotify, no /proc, no eBPF — so the
macOS and Windows port is weeks rather than a second product.
Five detectors, 88 tests:
pickle GLOBAL/STACK_GLOBAL walk over .pt/.ckpt/.pkl/.joblib.
torch.load runs a stack machine; a model file is a
program and downloading weights is a code-execution
decision.
injection Instructions aimed at a coding agent in CLAUDE.md,
AGENTS.md, .cursorrules, copilot-instructions.
installscript preinstall/postinstall hooks that curl|sh, decode and
run, reach for credentials, or install persistence.
typosquat Damerau-Levenshtein against popular names, plus
slopsquat detection: new + near-zero downloads + one
edit from something popular is the signature of a name
a model invented and somebody then registered.
mcp Servers fetched unpinned at launch, handed secrets, or
pointed at $HOME or credential paths.
Wired through `supply.sweep` on the socket and `hound supply-chain
<path>`, which exits 1 on a critical so it drops into CI.
Three things worth recording:
* Scoring is by independent category, not by keyword count. One
suspicious phrase is a phrase; two categories at once is an attack.
A file that only says "ignore previous instructions about formatting"
is a warning, not a critical.
* Proximity matters more than presence. The first version flagged an
entirely ordinary conventions file, because it mentioned ".env" in
one paragraph and "prefer small commits" in another. A credential and
a movement verb now have to appear within a sentence of each other.
The test that caught it is kept as the regression.
* Pickle call detection has to come out of the opcode walk, not a byte
search. REDUCE, INST and OBJ are the ASCII letters R, i and o, which
also occur inside every string the stream carries — searching raw
bytes finds the o in "os" and reports a call that never happens,
turning every warning into a critical.
Every finding carries a plain-language explanation and a next step, and
there is a test asserting explanations do not leak rule identifiers or
jargon. The audience includes people who cannot triage a YARA match and
should never be shown one.
Verified against a demo project holding a squatted @vue plugin with a
curl|sh postinstall, a poisoned CLAUDE.md in a vendored repo, an
unpinned MCP server holding a GitHub token, and a pickle calling
os.system — four criticals and one warning, while the legitimate
CLAUDE.md, the real express manifest and the properly-scoped MCP server
beside them stayed clean.
189 tests pass across the workspace.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
11 lines
336 B
TOML
11 lines
336 B
TOML
[package]
|
|
name = "hound-supply"
|
|
description = "Supply-chain and agent-era threat detection: typosquats, install scripts, pickle RCE, prompt injection, MCP overreach"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
license.workspace = true
|
|
repository.workspace = true
|
|
|
|
[dependencies]
|
|
serde.workspace = true
|
|
serde_json.workspace = true
|