taintgraph
Supports scanning Bun lockfiles (bun.lock) to analyze dependencies for supply-chain risks.
Allows scanning a public GitHub repository by URL to analyze its dependency lockfiles and MCP configs for supply-chain risks.
Provides tools for analyzing npm dependencies: scans npm lockfiles, pulls advisories and registry history from the npm registry, and traces supply-chain routes through installed npm packages.
Integrates with NVIDIA's API as an LLM provider for the Analyst agent, enabling natural-language answers checked against the dependency graph.
Integrates with Ollama as a local LLM provider for the Analyst agent, enabling natural-language answers checked against the dependency graph.
Supports scanning Poetry lockfiles (poetry.lock) to analyze Python dependencies for supply-chain risks.
Provides tools for analyzing PyPI dependencies: scans Python lockfiles (uv.lock, poetry.lock, requirements.txt), pulls advisories and package metadata from PyPI, and traces supply-chain routes through installed Python packages.
Supports scanning Yarn lockfiles (v1 and Berry) to analyze dependencies for supply-chain risks.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@taintgraphtrace how chalk@5.6.1 could reach my project from this lockfile"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
In September 2025, a phished maintainer pushed malware into chalk, debug and 16 other npm packages with billions of weekly downloads. A week later the Shai-Hulud worm began stealing npm tokens and republishing every package its victims maintained. In 2026, the same playbook hit TanStack and LiteLLM.
When that happens, a list of bad versions isn't enough. You need to know:
Am I hit, and how? Which of my 400 dependencies pulls the bad version in, and through which chain?
Who else could do this to me? Which single maintainer account can publish the biggest share of my tree?
What if it spreads? If that account is phished, what does a worm reach in one wave, two, four?
Is my AI tooling exposed? The MCP servers my coding assistant starts with
npxevery morning are a supply chain too.
Those are graph questions. Taintgraph loads the lockfile into FalkorDB: every installed version, who can publish it, who actually did, how each release changed from the last one, and every advisory that touches it. Then a set of agents answers them, remembers what you decided, and keeps watching.
What it does
Traces the route. Each finding shows the exact chain from your project to the bad version, using only the dependency edges your own lockfile declared.
Ranks who can poison you, and simulates the worm. Accounts are weighted by the PageRank of everything they can publish; community detection groups them into maintainer teams, and connected components show how far a worm could ever travel. Pick one and watch a Shai-Hulud style worm spread wave by wave.
Answers questions, and shows its work. An Analyst agent uses fixed, read-only Cypher tools. Every step shows the tool, the query and what came back, and the evidence subgraph is drawn. Answers that name anything the graph didn't return are rebuilt from the graph.
Remembers. Your verdicts, past investigations and learned triage rules live in the graph and change the next scan. It never skips malware automatically. Agents hand work to each other through Task nodes.
Plans the fix. For every compromised, tampered or high-severity version: the version to move to (the release before a malicious one, or the version that fixes every advisory), re-checked against OSV.dev so it never recommends another bad release. You get a paste-ready overrides block for npm, pnpm or yarn, or a uv lock command, plus incident-response steps when malware was installed.
Rescan after a lockfile update and it shows what changed since the last scan, and which of the new versions are flagged, which is usually how a compromise arrives.
It also flags tampered releases that no advisory covers yet:
Signal | When |
Removed from the registry | npm or PyPI no longer serves the version you pinned (registries delete malware), or npm replaced it with a security placeholder |
Account takeover | the publisher changed and an install script appeared |
Risky install script | the install hook downloads and executes, decodes base64, or reads credentials |
Dropped provenance | the previous release had a build attestation and this one doesn't |
Typosquat | one edit away from a top package, with a tiny fraction of its downloads |
Unpinned MCP server | an AI tool launches |
Related MCP server: DepHealth MCP
Tested on real incidents
pnpm bench scans the exact versions shipped in 19 real supply-chain incidents (2018 to 2026), plus 10 clean controls that include the releases just before and just after a compromise. Full results.
19 of 19 incidents detected, 0 false alarms on 10 clean controls. And Taintgraph's own lockfile scans clean: 297 versions, 0 advisories.
Incident | Version | Detected as |
event-stream (2018) |
| malware |
ua-parser-js hijack (2021) |
| malware advisory (range) |
node-ipc protestware (2022) |
| malware advisory (range) |
@solana/web3.js key theft (2024) |
| malware |
Ultralytics cryptominer (2024) |
| malware advisory (by its wording) |
s1ngularity, AI-CLI secret theft (2025) |
| malware |
chalk / debug phishing (2025) |
| malware |
Shai-Hulud worm (2025) |
| malware |
LiteLLM credential stealer (2026) |
| malware |
TanStack token hijack (2026) |
| malware |
…and 9 more |
Every case is also a test: pnpm test fails if any incident is missed or any control is flagged.
It also scans real repositories straight from GitHub: React, Astro, Vite, LangChain, FastAPI, Flask, Bun, TypeScript and more. Every lockfile format parses, large monorepos finish in about two minutes, and only the two genuinely compromised lockfiles are called compromised. Results.
How it compares
Taintgraph doesn't try to out-detect commercial scanners. Socket, Snyk and Aikido analyze package contents and catch new malware before an advisory exists; Taintgraph relies on OSV.dev plus release signals. What it adds is the reasoning around a finding, for your project:
Advisory scannersnpm audit, pip-audit, OSV-Scanner | Org-wide SBOM graphsGUAC | Taintgraph | |
Is a known-bad version installed? | ✅ | ✅ | ✅ |
The route into your app, through your own lockfile edges | partial | ✅ | ✅ |
Which maintainer accounts can publish the most of your tree | ✅ | ||
Worm simulation from one account, wave by wave | ✅ | ||
Release tampering without an advisory (takeover, provenance, removed) | ✅ | ||
npm, PyPI and AI-tool MCP configs in one graph | partial | ✅ | |
A fix plan with re-checked safe versions |
| ✅ | |
Agent that answers questions and shows its queries | ✅ | ||
Memory of your verdicts that changes the next scan | ✅ |
Quick start
You need Docker. No API key is required.
git clone https://github.com/kalash33/taintgraph && cd taintgraph
cp .env.example .env # optional: add a Gemini, NVIDIA or OpenRouter key
docker compose up --buildOpen http://localhost:8787 and click chalk and debug, September 2025: a real public lockfile caught by that attack.
docker compose up -d falkordb # FalkorDB on 127.0.0.1:6380
pnpm install
pnpm build && pnpm start # http://localhost:8787
pnpm test # 80 tests: unit, integration, real incidentsTurn on the LLM Analyst
Without a key, a built-in investigator answers with the same tools. With one, answers read naturally and are still checked against the graph.
GEMINI_API_KEY=... # Google AI Studio; default model gemini-3.5-flash
NVIDIA_API_KEY=nvapi-... # build.nvidia.com; default model nvidia/nemotron-3-super-120b-a12b
OPENROUTER_API_KEY=sk-or-... # default model openai/gpt-oss-120b
ANTHROPIC_API_KEY=sk-ant-...
LLM_PROVIDER=openai LLM_BASE_URL=http://localhost:11434/v1 LLM_MODEL=qwen3:32b # Ollama, vLLM…Use it where you work
pnpm scan package-lock.json # any lockfile or MCP config
pnpm scan https://github.com/owner/repo # a public repo; finds lockfiles in subfolders
pnpm scan package-lock.json --fix # the fix plan: safe versions + overrides
pnpm scan uv.lock --fail-on malware --sarif taintgraph.sarif # CI gate + GitHub code scanning
pnpm scan chalk-2025 --ask "What if qix is phished?" # ask the Analyst from the terminalAnd as an MCP server, so a coding agent can check a dependency before adding it:
{ "mcpServers": { "taintgraph": { "command": "pnpm", "args": ["-C", "/path/to/taintgraph/server", "mcp"] } } }Supported inputs: package-lock.json, pnpm-lock.yaml, yarn.lock (v1 and Berry), bun.lock, uv.lock, poetry.lock, pinned requirements.txt, and MCP configs from Claude Code, Claude Desktop, Cursor and VS Code.
How it works
flowchart LR
IN[Lockfile · MCP config · GitHub URL] --> S[Scout]
F[OSV.dev · npm · PyPI · deps.dev · ecosyste.ms] --> S
S -->|graph + findings| DB[(FalkorDB)]
S -->|Task: analyze| A[Analyst]
A -->|read-only tools| DB
A -->|Task: report| R[Reporter]
N[Sentinel] -->|new advisories → re-triage| DB
N -->|Task: analyze| A
DB --> UI[Web app · CLI · MCP · API]Scout parses the input, pulls advisories and registry history, writes the graph, runs PageRank and triages.
Analyst answers questions with fourteen fixed tools, including workspace-wide ones ("which of our projects install chalk@5.6.1, and what else can its maintainer reach?"), over
GRAPH.RO_QUERY. It resolves names first, returns typed outcomes (answered,from_memory,not_in_graph,unknown_name) and checks its answer against the tool results.Reporter writes an incident report you can forward.
Sentinel re-checks every version any project ever installed against OSV, so an advisory published today finds the app that installed the package last month.
The graph
graph LR
Project -- DEPENDS_ON --> Version
Version -- "DEPENDS_ON {projects}" --> Version
Version -- OF --> Package
Version -- PRECEDES --> Version
Account -- MAINTAINS --> Package
Account -- PUBLISHED --> Version
Advisory -- "AFFECTS {explicit, fixed}" --> Version
Scan -- OF_PROJECT --> Project
Scan -- SAW --> Version
McpServer -- RUNS --> Version
Finding -- ABOUT --> Version
Investigation -- HAS_STEP --> Step
Investigation -- FOLLOWS --> Investigation
Rule -- LEARNED_FROM --> Finding
Task -- FOR_PROJECT --> ProjectThe first ten edges are the supply chain. Finding, Investigation, Step, Rule and Task are the agents' memory and shared state, kept in the same graph next to the facts they're about. Every property and query: docs/graph-model.md.
Where every decision comes from
Nothing the agents conclude comes from the model's own knowledge. Each answer is a graph query or algorithm, and the UI shows which one:
Decision | How the graph makes it | Query |
Is a malicious version installed? |
| |
How does it reach the app? |
| |
Was the release tampered with? | compare a version with the one it | |
Who could poison the tree? |
| |
Which maintainers act as one team? |
| |
How far could a worm go? | repeated hops account → version → dependents → their maintainers; | |
What should we pin to? | fixed versions on | |
Which other projects are hit? | every project whose latest | |
Should memory skip this finding? | earlier human verdicts on the same | |
Which agent works next? | an atomic claim on an open |
All 77 Cypher queries are plain files in queries/. They use shortestPath, allShortestPaths, variable-length paths, algo.pageRank, algo.betweenness, algo.labelPropagation (community detection), algo.WCC (connected components), full-text search and CALL {} subqueries.
Documentation
components, scan flow, workspaces, code map | |
every node and relationship, the key queries, FalkorDB notes | |
the Analyst's tools and checks, memory, coordination, the Sentinel | |
web app, CLI, GitHub Actions, MCP server, HTTP API, configuration | |
Docker Compose on a VM, Railway, and what to lock down first | |
real incidents and controls, with results | |
how Taintgraph handles hostile package data, and how to run it safely | |
setup, checks, conventions |
More screenshots
AI tool supply chain (dark mode) | Phone |
Graph Hacks 2026
Built for Graph Hacks: Context for AI Agents (WeMakeDevs × FalkorDB), entered in:
Track 01: Agents That Act on Connected Data. The Analyst answers from multi-hop paths, account reach and worm spread; the Sentinel acts on new advisories.
Track 02: Agent Memory and Coordination. Verdicts, conversations, investigations and learned rules live in the graph and change future triage. Agents coordinate only through Task nodes, and claims stay exclusive under concurrency.
AI disclosure. Built during the event with an AI coding assistant (Claude Code). The idea and research were prepared before the event, as the rules allow; all code was written during it.
Data: OSV.dev, the npm registry, PyPI, deps.dev, ecosyste.ms. Graph: FalkorDB.
License
This server cannot be deployed
Maintenance
Related MCP Connectors
Trust-check any dependency for agents: OpenSSF Scorecard, licenses, CVEs, deps. 7 ecosystems.
Protects AI coding agents from installing malicious open source packages. Every npm and PyPI package is checked against SafeDep’s real-time threat intelligence before installation.
Check an npm/PyPI package before an AI agent installs it: 5 focused supply-chain tools.
Audit GitHub repos for malicious and supply-chain code before you depend on them.
Related MCP Servers
- AlicenseAqualityDmaintenanceVerify-before-act safety tools for AI coding agents, providing MCP tools to check packages, lockfiles, manifests, and CI workflows for supply chain risks.410 npmMIT
- AlicenseAqualityFmaintenanceDependency security & health auditing for AI agents with no account or API key required.22MIT
- AlicenseNot gradedqualityCmaintenanceSecurity scanner for MCP servers — vet an MCP before you wire it into an agent. Detects prompt-injection, credential exfiltration (via taint analysis), RCE, and supply-chain risks, and catches cross-server exfil chains no single server reveals. Zero-dependency local CLI, SARIF output, CI-gateable, no account.32 npmMIT
- AlicenseAqualityAmaintenanceEnables AI coding agents and CI to vet npm dependencies before they reach the lockfile, flagging hallucinated, slopsquatted, or otherwise risky packages with evidence-backed verdicts.323 npm4MIT