Dependency Domino
Inspiration
Modern applications rely on large chains of third-party packages, including dependencies that developers may never choose directly or even notice. A problem in one upstream package can have consequences far beyond that single package, but those relationships are hard to see in a lockfile alone.
We built Dependency Domino to make that hidden supply chain easier to explore. The core question behind the project is: If one package became untrustworthy, how far could the impact reach?
What it does
Dependency Domino turns a project's dependency lockfile into an interactive graph. It reads npm, pnpm, Yarn, and Bun lockfiles, either uploaded, dropped onto the canvas, or fetched from a public GitHub repository by URL. Two built-in demos are included: a small hand-written example for learning the basics, and the real lockfile from the yargs repository with 562 installed packages.
Users can search for and select any installed package to see its version, source, and the packages it depends on and that depend on it. Selecting Simulate compromise runs a hypothetical scenario: the graph animates, layer by layer, every package that depends on the selection, directly or indirectly. The results show how many packages are affected, how many are development-only, the distance to the project root, sample paths from the root, and the packages that every path passes through.
Beyond the core simulation, users can explore the packages around a selection, show only the simulated impact, rank packages by how many others depend on them, and preview which packages would become unreachable if one were removed. Results can be exported as JSON, Markdown, or PNG images, including a summary card for sharing.
The app also queries OSV.dev for known security advisories on exact package versions. Advisories are displayed separately from simulation results so users can tell known advisory records apart from a hypothetical exposure scenario.
Dependency Domino is an exposure visualization tool, not a vulnerability scanner. A scanner such as npm audit starts from known advisories and lists flagged versions. Dependency Domino starts from any package and shows what depends on it, and through which paths. It does not detect exploits, analyze malware, or prove that a dependent package is vulnerable.
How we built it
We built Dependency Domino with SvelteKit, TypeScript, Vite, Tailwind CSS, and Cytoscape.js. Lockfiles are parsed in a browser worker and turned into graph data, where each node is an installed package instance and each edge points from a consumer to its dependency. Separate parsers handle npm v1 to v3, pnpm v6 and v9, Yarn Classic and Berry, and Bun's text lockfile, each preserving that format's identity rules and reporting its limitations as warnings.
The simulation is a reverse breadth-first search over those edges, which produces both the affected set and the animation layers. Cytoscape.js provides the interactive graph, and progressive reveal, focused views, a minimap, and layout caching keep larger graphs usable.
For vulnerability context, a small server endpoint forwards validated package names and versions to OSV.dev. Lockfiles themselves never leave the browser. The parser and graph logic are pure TypeScript covered by Vitest unit tests, and Playwright browser tests cover the main workflows.
Challenges we ran into
A key challenge was representing dependency relationships accurately. Projects can contain multiple installed copies or versions of the same package, and collapsing them into a single node would create misleading connections. Resolution also involves nested and hoisted packages, workspaces, aliases, peer dependencies, and rules that differ between npm, pnpm, Yarn, and Bun.
We also needed to make two different kinds of information understandable at a glance: hypothetical compromise propagation and known vulnerability advisories. Keeping them visually and textually separate matters, so the app never implies that a simulated impact is a confirmed vulnerability.
Finally, real dependency graphs get crowded quickly, and external lookups can fail or return partial results. We added progressive reveal, focused views, and filters for readability, and lookup status and warnings so users know when information is incomplete.
Accomplishments that we're proud of
- Built an interactive dependency graph from real lockfiles in four formats, plus live import from GitHub.
- Implemented a hypothetical compromise simulation that traces dependents through every level of the graph, with animated playback.
- Explained results with counts, sample paths, packages every path passes through, distance grouping, and a removal preview.
- Integrated OSV.dev advisory lookup as a separate, clearly labeled source of security information.
- Added JSON, Markdown, and PNG exports so results can be shared in issues and pull requests.
- Kept lockfiles in the browser, sending only package names and versions for advisory lookup.
- Deployed a live version at dependency.toolsmith.online.
What we learned
We learned that dependency visualization is not just about drawing nodes and edges. Correctly identifying installed package instances and resolving relationships for each package manager matters if the graph is going to communicate anything useful.
We also learned to be precise about security claims. A package's presence in a dependency chain does not, by itself, prove that vulnerable code is reachable or that a project is exploitable. Separating known advisories from hypothetical simulations helps communicate that uncertainty honestly.
Finally, a useful security tool needs to explain its results, not just display them. Paths, counts, warnings, and clear visual distinctions make complex dependency relationships much easier to understand.
What's next for Dependency Domino
Next, we want to compare dependency graphs between two versions of a lockfile, so teams can see how a change affects their exposure. We also want to add SBOM import, CI-friendly reports, and support for package ecosystems beyond JavaScript.
Any expansion will build on the same principle: show dependency relationships clearly, explain potential exposure, and keep verified advisory information distinct from hypothetical outcomes.
Built With
- claude
- cytoscape
- gemini
- iconify
- osv.dev
- prettier
- python
- sveltekit
- tailwind
- typescript
- vite
- vitetest
Log in or sign up for Devpost to join the conversation.