Skip to content

GuardLink

GuardLink keeps a threat model inside the repository it describes. You write the model as annotations in your source, anchored to real code positions, and guardlink parses them into a live model it can validate, diff, and export.

Under the hood it reads a small annotation language called GAL. You declare assets, threats, controls, and actors, then state how they relate: this asset is exposed to that threat, here; this control mitigates it; this risk is accepted and why. Because the statements sit beside the code they describe, they travel with it when it moves.

The problem that solves is rot. A threat model written as a document is accurate on the day it is signed off and decays from then on: the code moves, the document does not, and nobody finds out until an incident. Annotations decay too, but they decay visibly. When an anchored block no longer sits on the symbol it names, guardlink ci reports the drift, guardlink reanchor repairs the ones whose symbol still exists, and what is left needs a human precisely because the function it described is gone. See why annotations live in code.

Terminal window
npm install guardlink@2.0.0

Take a login handler that reads from the database. One line above it records what is at stake:

// @exposes api.auth to SQL Injection [high] cwe:CWE-89

When someone adds input validation, a second line closes it:

// @mitigates api.auth against SQL Injection using Input Validation

Nothing here is inferred. A person stated both, git dates and attributes them, and guardlink ci reports the exposure for as long as the first line stands without the second. Move the handler to another file and both lines move with it.

npx guardlink gal prints the whole language with an example per verb, which is the fastest reference while you are writing annotations.

Once the annotations are in place, one model feeds several consumers.

flowchart TB
    SRC["annotations in your source<br/>@exposes, @mitigates, @confirmed"] --> P["guardlink parse"]
    P --> M["the threat model<br/>.guardlink/model.json"]
    M --> CI["guardlink ci<br/>open exposures, drifted anchors"]
    M --> EX["sarif, report, dashboard, diff"]
    M --> AG["MCP server<br/>an agent reads and extends it"]

    class M emphasis
Output Command For
The model as JSON guardlink parse Anything that wants to read the model directly
A CI gate guardlink ci Failing a build on unmitigated exposures and drifted anchors
SARIF 2.1.0 guardlink sarif GitHub Advanced Security, VS Code
A report with a Mermaid diagram guardlink report A human reading the model
An interactive HTML dashboard guardlink dashboard Browsing the model and its diagrams
What changed since a git ref guardlink diff Reviewing a pull request
What you are doing Reach for Why
Recording what a piece of code puts at risk @exposes and @mitigates in source The statement is dated by git and attributable, and it moves with the code
Gating a build on the model guardlink ci Advisory by default, and --strict makes it fail
Finding annotations that drifted off their symbol guardlink reanchor Reports @source blocks whose file:line no longer holds the symbol they name
Feeding a code-scanning pipeline guardlink sarif Standard SARIF, so existing tooling reads it without adapters
Handing the model to a coding agent guardlink mcp An agent reads and extends the model instead of inferring one
Testing whether an exposure is real cxg pentest guardlink states the hypothesis, cxg tries to confirm it at runtime
Reading the model from your own code The library API Seven subpath exports, from the published TypeScript declarations

Three things surprise people. Each one is covered in full elsewhere.

Install and annotate one function

Install GuardLink, annotate a single function, and finish with a threat model that validates clean in CI.

Install GuardLink

Give an agent the model

Wire the MCP server into a coding agent: 24 tools and 3 resources over stdio.

Wire up the MCP server

These pages describe GuardLink 2.0.0, the current release on npm. Every command shown was run against that version and its real output pasted in.

Each of the three references is produced from the installed package: its --help output, its shipped .d.ts files, and its running MCP server. None of them can claim a behaviour the release does not have.

Reference Covers
CLI reference Both executables, guardlink and guardlink-mcp
API reference The seven subpath exports, from the published TypeScript declarations
MCP tool reference Every tool and resource the MCP server registers

The major version is scoped to the TypeScript type surface and the threat-model JSON schema. No CLI command, flag, or output behaviour was removed, so CLI and MCP users upgrade with no migration.

What 2.0.0 changed
Change Affects
coverage reshaped to {annotation_count, coverage_percent} Anything reading total_symbols, annotated_symbols, or unannotated_critical. See the artifact page
Model schema 1.1.0 to 1.2.0, report schema 1.0.0 to 1.1.0 guardlink merge warns on a mixed-version set and normalises the old shape
UnannotatedSymbol removed from the type surface TypeScript consumers
New unknown-verb diagnostic A misspelled verb now warns instead of vanishing
Every diagnostic carries a machine-readable code Consumers classifying diagnostics. Twelve codes are defined
Version reporting corrected SARIF tool.driver.version reported 1.4.3 regardless of the installed version. It now reports the real one
guardlink-mcp --help and --version Both previously started the server and blocked
parse --no-pretty Compact single-line JSON, which had no flag before
report --format <bogus> now exits 1 Previously wrote nothing and exited 0