supply-chain incident console

A compromised package. One page of answers.

Reachable reads your lockfiles and commit history and tells you which services are exposed, which pulled the package in while it was still installable, and what the same maintainers could reach next — with the statement that produced every number.

every answer carries its statementnumbers are measured, never estimateddark, read-only console
MAL-2025-46974present only31 statements · 50 rows · 16.5s
3
services exposed
0
act now
3
resolved while live
32
maintainer packages
2
look-alike names
0
unscanned
blast radius
versiondependencylockfileservicedebug@4.4.2affecteddirect dependencyresolved directlyeslint@8.57.1dependency@typescript-eslint/type-utils@7.18.0dependencyagent-base@6.0.2dependencyhttp-proxy-agent@5.0.0dependencyai-research-automation@6681e87pins erased versionai-research-automation@5b74cd6pins erased versionai-research-automation@80fc6d0pins erased versionn8n-node-gomake@c361ccfin windowcakestory-api@5789d20pins erased versioncakestory-api@458e59ein windowChrisTregaskis/ai-research-automationChrisTregaskis/ai-research-automa…L0GoMake-ltd/n8n-node-gomakeGoMake-ltd/n8n-node-gomakeL0LVQT-ss/cakestory-apiLVQT-ss/cakestory-apiL0
resolved while installableL2 act nowL1 importedL0 present onlyunscanned
the report

Six questions, answered on one page.

Q16 rows · 6.34 ms

Which of my services are exposed, and at what level?

A verdict per service, highest across its lockfiles, with the dependency that pulled it in.

Q21 row · 9.05 ms

Which versions were installable, and for how long?

Exact publish times, the last moment each version was observed installable, and an explicit upper bound.

Q36 rows · 4.81 ms

Who pulled it in while it was still installable?

Every lockfile write intersected with the window, down to the commit that wrote it.

Q432 rows · 13.60 s

What else could the same maintainers reach?

The other packages those accounts publish, and how many of your services each one would reach.

Q52 rows · 2.60 ms

Which look-alike names exist?

Names one edit away, scope confusion, hyphen and homoglyph swaps — grouped by kind with edit distance.

Q63 rows · 0.68 ms

What is the blast radius, service by service?

The final ledger: act now, imported, present only, unscanned — plus the provenance that produced it.

the hard question

Who pulled it in while it was still installable?

A removed version is not a resolved incident. Reachable intersects every lockfile write with the window the version was actually installable in — and marks the edge of that window as an upper bound, because registries do not record removal times.

2 lockfiles committed inside the window
4 lockfiles more pin the erased version — only possible while it was live
the dashed edge is an upper bound, never a claim
Q3 · installable window6 rows · 4.81 ms
12:0013:0014:0015:0016:0017:0018:00installable · 1 version · sep 08 utcupper bound · advisory publishedcakestory-api +1ai-research-automationai-research-automation+2 later · sep 09, sep 13
hydradbwho pulled it in while it was still installable?6 rows · 4.81 ms
MATCH (a:Advisory {id: 2971413083072216})-[af:AFFECTS]->(v:Version)<-[r:RESOLVED]-(l:Lockfile)<-[:HAS_LOCKFILE]-(sv:Service)
WHERE r.at >= af.live_from AND r.at <= af.live_to
RETURN sv.key AS service, l.key AS lockfile, l.sha AS sha, r.at AS resolved_at, v.key AS version, v.removed AS removed, af.live_from AS live_from, af.live_to AS live_to, af.live_to_kind AS live_to_kind
ORDER BY r.at ASC
no black boxes

Every number ships with the statement behind it.

Each answer card carries the executed query, the row count and the measured latency. Collapse it if you trust it. It is never hidden, and nothing on the page is an estimate: an uncomputed value reads “not computed”, an unread service reads “unscanned”.

four verdicts

Colour means one thing here.

A page with no red is the message. Verdicts are computed per service — the highest level across its lockfiles — and never softened.

0 act now0 imported3 present only0 unscanned
L2
act now

First-party code references the affected package's vulnerable symbol. This is the level that needs action now.

L1
imported

First-party code imports the package; the vulnerable symbol is not referenced.

L0
present only

In the install tree, never imported by any scanned file.

unscanned

Exposed, but its source was not read. Styled as unknown, never as safe, and never counted as zero.

13
services watched
246
lockfiles parsed
657
advisories in the graph
16.5s
full report, wall-clock
what runs where

One node. One console. Nothing else to install.

01

Console

Incidents · report · board · ask · graph. Every page reads the graph and shows the statement that produced it.

02

Self-hosted core

One HydraDB node and one worker: GitHub lockfile history, npm versions and maintainers, OSV advisories, an import scan at the exposed commit. Single-tenant — the token never leaves it.

03

Coding agents

An MCP server exposes the same questions to Claude Code, Codex, Cursor and others, so an answer arrives where the fix is written.

in the editor

Twelve tools, for the agent fixing it.

An MCP server over stdio, on the official SDK. It computes nothing — each tool is one call to the worker, so an agent gets the same answers as the console, with the statement that produced them. Eleven read; one writes, and says so.

exposed_serviceswhich watched services resolved an affected version
resolved_while_livewhich committed the pin while it was still installable
affected_versionsthe versions, the removal and the installable window
maintainer_fanoutwhat else the same maintainers publish
typosquatsnames within one edit, by kind and distance
why_pulled_inthe dependency chain that put it in the tree
who_depends_onwhich services pin an exact version
list_servicesthe watched registry and its latest commits
job_statusprogress and log of an ingest
find_public_victimspublic repos pinning an affected version today
cypherany read-only statement against the graph
watch_repositorystart watching a repositorywrites
Claude Code · Codex · Cursor · OpenCode — same command and arguments.How to point it at a worker

Point it at one repository and read the first report tonight.

Read-only GitHub access, lockfiles and commit metadata linked into one graph, six answers per advisory from the first ingest onward.

Connect a repositoryOpen the consoleread-only GitHub access · self-hosted