Build your first threat model
This is the shortest path to something real: one command that reads a repository’s annotations and produces its threat model, a dashboard, and a SARIF export. It sends no traffic, needs no target, and needs no coding agent.
By the end you can read the three numbers that matter and — more usefully — see which threats a probe would never have been able to test.
Before you start
Section titled “Before you start”bugbon yourPATHandguardlinkinstalled — see What bugb needs.- A repository that already carries guardlink annotations. If yours does not,
bugb annotatewrites them.
Build the model
Section titled “Build the model”-
From the repository root:
Terminal window bugb model .run 20260818-202612-demo · branch bugb/run-20260818-202612-demo663 annotations · 119 exposures · 124 threats trackedreport /Users/you/.bugb/runs/20260818-202612-demo/rounds/1/model-report/threat-model.mdreport (json) /Users/you/.bugb/runs/20260818-202612-demo/rounds/1/model-report/threat-model.jsondashboard /Users/you/.bugb/runs/20260818-202612-demo/rounds/1/model-report/threat-dashboard.htmlsarif /Users/you/.bugb/runs/20260818-202612-demo/rounds/1/findings.sarifMODEL READY — open /Users/you/.bugb/runs/20260818-202612-demo/rounds/1/model-report/threat-dashboard.html→ see it in the Bugb dashboard: bugb dashboardIt takes about a second. The run id is the timestamp plus the directory name.
-
Check what it did to your repository.
Terminal window git status --shortgit branch --show-currentbugb/run-20260818-202612-demoYour working tree is untouched —
git statusprints exactly what it printed before. What changed is the current branch: bugb checked outbugb/run-<run-id>so that anything a later phase writes lands somewhere revertible.bugb model . --no-checkpointskips the branch; either way, the model tier commits nothing. -
Read the three numbers.
663 annotations · 119 exposures · 124 threats trackedNumber Means annotations every guardlink annotation in the repository — assets, threats, flows, mitigations, and exposures together exposures the @exposessubset: a threat hypothesised against an asset at a linethreats tracked rows in this run’s ledger Threats tracked exceeds exposures here because the ledger also carries the exposures that guardlink’s export drops. The next step is where those show up.
Read what the model cannot see
Section titled “Read what the model cannot see”bugb model tells you what is there. bugb inspect tells you where the view is
lossy — which is the part worth your attention.
bugb inspect . /Users/you/demo guardlink 2.0.0 · cxg pins 6 files sarif: /Users/you/demo/whitebox/findings.sarif
SUMMARY exposures 118 (18 critical, 50 high, 45 medium, 5 low) confirmed 7 unique pairs 69 ← what `guardlink diff` can distinguish annotations 663 assets 25 threats 29 flows 44Truncated: the full output lists all 118 exposures between this block and the next.
unique pairs 69 against exposures 118 is the first honest number on the
page. guardlink identifies an exposure by its asset and threat alone, so 118
findings collapse into 69 identities — and a second, different weakness in a
pair that is already known cannot be distinguished from the first.
Then the section that decides what a run can prove:
SUPPRESSED FROM EXPORT (8) A @mitigates or @accepts anywhere in the repo removes every exposure sharing that pair from the SARIF export. cxg never sees these and cannot test them. critical app.benefits::missing-authz ×4 via @mitigates high app.memos::xss ×3 via @mitigates high app.profile::xss ×3 via @mitigates high app.session::session-fixation ×1 via @mitigates medium app.session::xss ×1 via @mitigates critical data.allocationsdao::nosql-injection ×1 via @mitigates high data.userdao::nosql-injection ×2 via @mitigates low ops.securitytest::hardcoded-secret ×1 via @mitigates
REACHABILITY file-anchored 0 usable for goal synthesis asset-guessed 0 route inferred, often wrong no route 118 needs agent enrichment
CXG CORRELATION hypotheses 118 correlated 118/118 okThree things to take from it:
- Suppressed (8 pairs, 16 exposures). One
@mitigatesanywhere removes every exposure sharing that asset/threat pair from the export. A control that is 90% correct is more dangerous than none, because it ends the investigation silently. Themitigation-auditlens exists to attack exactly these. - Reachability. No annotation here carries a route, so every goal will need an agent to work out what to send. That is the slow part of a verify run.
- Correlation. Every hypothesis can be traced back from a cxg finding to
its exposure. When this is short of
118/118, findings arrive that cannot be attributed, and an unattributable finding is never written back.
Open the dashboard
Section titled “Open the dashboard”bugb dashboardA local page over every run on this machine, on http://127.0.0.1:8787 by
default. It is read-only: it displays runs and hands you commands, and it is not
a control plane — nothing in it starts a run. --port moves it; --no-open
stops it launching a browser.
What you have
Section titled “What you have”- A threat model report and dashboard, under
$BUGB_HOME/runs/<run-id>/. - A SARIF export — the file cxg consumes.
- A ledger of every tracked threat, all of it still unverified.
Every threat in that ledger is a hypothesis. Nothing has been tested. Making them true or false is the verify tier’s job, and it sends real exploit traffic:
- Run the loop unattended — intake, a
plan you approve, then
bugb auto. - Authorization and blast radius — read this before pointing it at anything.

