Skip to Content

Graph

Cytoscape-rendered transitive dependency graph — dagre + cose-bilkent layouts, URL-driven filters, focus-CVE contamination mode.

Default view

Graph — default view across the workspace

Cose-bilkent layout by default — force-directed, clusters nodes by coupling so tightly-connected subgraphs visually group together. Dagre (left-to-right DAG) stays available in the Layout dropdown for reviews that favour hierarchy over cohesion. Node fills encode ecosystem (npm blue / pypi green / malware purple / typosquat magenta / CVE ember). Edge styles encode kind (runtime solid / dev stroked / peer dashed / optional dotted).

Filters

ControlEffect
KindToggle runtime / dev / peer / optional edges. Defaults to runtime only.
DepthLimit the BFS depth from workspace roots. Default 2 — direct deps + one transitive level. Raise the slider to go deeper on large monorepos.
Layoutdagre (DAG-style) / cose-bilkent (force-directed).
SearchHighlights any node whose name substring-matches.

Every filter is in the URL, so a shared link reproduces the same view.

Legend — dynamic and clickable

The legend only surfaces categories actually present in the current render (post-filter, post-depth). If no optional edges are in view, the optional item isn’t in the legend — no dead controls. Click an item to hide that category from the canvas; the item desaturates with a strikethrough so you keep the handle to restore it. Re-click to bring it back.

The state lives in the URL: ?hide=<keys> for client-side categories (ecosystem / status), ?kind= for edge kinds (shared source of truth with the Kind row above). Share a URL, share the exact filtered view.

Focus-CVE contamination mode

Graph focus — CVE contamination chain to lodash

Press Cmd+K (or Ctrl+K on Linux / Windows) to open the CVE command palette. Fuzzy search across every advisory present in the current workspace scope — each row shows CVE-YYYY-NNNNN · <package> · <severity> · <N chains>. Arrow keys to navigate, Enter to select, Escape to close without touching the URL.

Selecting an entry writes ?focus_cve=<id> into the URL and the graph:

  1. Looks up every (ecosystem, name, version) touched by the advisory in the local store.
  2. Runs the inverse contamination BFS — same algorithm as packguard graph --contaminated-by.
  3. Highlights every root-to-leaf chain in ember red, dims everything else.

The banner at the top tells you how many packages were hit and how many chains were surfaced — CVE-2026-4800: 1 package hit · 3 contamination chains · cached.

Cache is per-advisory, 15 minutes — a subsequent trace of the same CVE is instant. When the store has no advisories in scope, the palette shows a callout pointing at packguard sync to fetch the database.

Empty state

A freshly-scanned workspace with zero transitive edges (yarn.lock-only, or pip declared-only with no lock) shows a banner pointing at the limitation. The scanner will surface the workspace roots and their direct deps but can’t render transitive chains without a real lockfile.

Performance

  • ~5000 nodes renders in well under a second on a mid-range laptop.
  • Above that, the dashboard warns and suggests toggling off peer + optional edges to slim the graph before rendering.
  • The BFS cache is shared with the CLI — same store, same traversal, same result.
Last updated on