Skip to content
Generated from guardlink gal. Report problems against guardlink, not this page.

GAL reference

Every verb in the GuardLink Annotation Language as guardlink 2.0.0 defines it. npx guardlink gal prints the same thing in your terminal, which is faster while you are actually writing annotations.

For what the language is for, and how the verbs compose into a finding, see the annotation language.

Annotations live in source comments or standalone .gal files. GuardLink parses them into a live threat model for your codebase.

@verb subject [preposition object] [-- "description"]

Inline examples below use comment prefixes; raw .gal files use the same lines without // or #. In .gal files, use @source file:<path> line:<n> [symbol:<name>] to anchor following annotations.

@asset <path> [-- "description"]

Declare a named asset (component, service, data store). Path uses dot notation for hierarchy.

// @asset api.auth.token_store -- "Stores JWT refresh tokens"
// @asset db.users
@threat <name> (#id) [critical|high|medium|low] [ext-refs] [-- "description"]

Declare a named threat. Severity in brackets: [P0]=[critical] [P1]=[high] [P2]=[medium] [P3]=[low].

// @threat SQL Injection (#sql-inj) [high] cwe:CWE-89 -- "Unsanitized input reaches DB"
// @threat Token Theft [P0]
@control <name> (#id) [-- "description"]

Declare a security control (mitigation mechanism).

// @control Input Validation (#input-val) -- "Sanitize all user-supplied strings"
// @control Rate Limiting
@actor <name> (#id) [-- "description"]

Declare a principal in the authorization model — a role, not a person. Declared once per project, alongside @asset / @threat / @control.

// @actor Namespace_Admin (#ns-admin) -- "Administers one namespace's configuration"
// @actor Namespace_Writer (#ns-writer) -- "Starts and signals workflows"
@exposes <asset> to <threat> [severity] [ext-refs] [-- "description"]

Mark an asset as exposed to a threat at this code location. This is the primary annotation — every exposure creates a finding.

// @exposes api.auth to SQL Injection [high] cwe:CWE-89
// @exposes db.users to Token Theft [critical] -- "No token rotation"
@mitigates <asset> against <threat> [using <control>] [-- "description"]

Mark that a control mitigates a threat on an asset. Closes the exposure — removes it from open findings. “using” is the primary keyword; “with” also accepted.

// @mitigates api.auth against SQL Injection using Input Validation
// @mitigates db.users against Token Theft -- "Rotation implemented in v2"
@confirmed <threat> on <asset> [severity] [ext-refs] [-- "evidence"]

Mark a threat as verified exploitable (pentest, scan, or manual repro). Not a false positive — use observed severity. Distinct from @exposes (hypothesis).

// @confirmed SQL Injection on api.auth [critical] cwe:CWE-89 -- "Pen test: blind SQLi on /login"
// @confirmed #secret-exposure on App.Config [critical] -- "Live key in repo; verified with provider"
@accepts <threat> on <asset> [-- "reason"]

Explicitly accept a risk. Removes it from open findings. Use when the risk is known and intentionally not mitigated.

// @accepts Timing Attack on api.auth -- "Acceptable for current threat model"
@entitles <actor> to <capability> [on <asset>] [against <threat>] [-- "description"]

State that an actor is legitimately entitled to a capability by design — the answer to “is the caller already allowed to do this?”. <capability> is one identifier, never prose. The JOIN is (actor, asset, threat): a claim missing on or against joins nothing and cannot demote. Never suppresses a finding and never gates testing — it only informs the recommendation downstream. Absent from the SARIF export entirely. Must cite the authz code (file:line) in the description, or it is inert. Not written by hand and never by an agent: an over-grant closes a real escalation as by-design, so entitlements are proposed and then accepted. An @entitles with no accepted proposal behind it is a validation error.

// @entitles #ns-admin to configure-archival-destination on #archival-fs against #path-traversal
// -- "By design: the archival URI is namespace config. Authz: common/api/metadata.go:189"
guardlink entitle --propose --actor "#ns-admin" --capability configure-archival-destination \
--asset "#archival-fs" --threat "#path-traversal" --file common/api/metadata.go --line 189 \
--rationale "By design: namespace config. Authz: common/api/metadata.go:189"
guardlink entitle # review proposals: accept / reject / defer
guardlink entitle --list # see the ledger, .guardlink/entitlement-proposals.json
@transfers <threat> from <source> to <target> [-- "description"]

Transfer responsibility for a threat to another asset/team.

// @transfers DDoS from api.gateway to cdn.cloudflare -- "Handled by CDN layer"
@flows <source> -> <target> [via <mechanism>] [-- "description"]

Document data movement between components. Appears in the Data Flow Diagram.

// @flows api.auth -> db.users via TLS 1.3
// @flows mobile.app -> api.gateway via HTTPS -- "User credentials"
@boundary <asset_a> and <asset_b> (#id) [-- "description"]

Declare a trust boundary between two assets. Groups assets in the Data Flow Diagram. Alternate: @boundary between A and B or @boundary A | B

// @boundary internet and api.gateway (#edge) -- "Public-facing edge"
// @boundary api.gateway | db.users -- "Internal network boundary"
@handles <classification> on <asset> [-- "description"]

Declare data classification handled by an asset. Classifications: pii phi financial secrets internal public

// @handles pii on db.users -- "Stores name, email, phone"
// @handles secrets on api.auth.token_store
@owns <owner> for <asset> [-- "description"]

Assign ownership of an asset to a team or person.

// @owns platform-team for api.auth
@validates <control> for <asset> [-- "description"]

Assert that a control has been validated/tested on an asset.

// @validates Input Validation for api.auth -- "Pen-tested 2024-Q3"
@audit <asset> [-- "description"]

Mark that this code path is an audit trail point.

// @audit db.users -- "All writes logged to audit_log table"
@assumes <asset> [-- "description"]

Document a security assumption about an asset.

// @assumes api.gateway -- "Upstream WAF filters malformed requests"
@feature "Feature Name" [-- "description"]

Tag code with a feature name for filtering reports and dashboards. A file can have multiple @feature tags. All annotations in that file are associated with the tagged features. Filter commands by feature:

// @feature "SSO Login" -- "Single sign-on authentication flow"
// @feature "Payment Processing"
guardlink feature list
guardlink report . --feature "SSO Login"
guardlink dashboard . --feature "SSO Login,Payment Processing"
@comment [-- "description"]

Free-form developer security note (no structural effect).

// @comment -- "TODO — add rate limiting before v2 launch"
@shield [-- "reason"]

Single-line marker for a security-sensitive code point.

// @shield -- "Crypto key derivation — do not refactor without review"
@shield:begin / @shield:end

Wrap a code block to mark it as security-sensitive. GuardLink will flag unannotated symbols inside the block.

// @shield:begin -- "Auth verification block"
function verifyToken(token: string) { ... }
// @shield:end

Append space-separated refs after severity on @threat, @exposes, and @confirmed:

cwe:CWE-89 owasp:A03:2021 capec:CAPEC-66 attack:T1190

Example:

// @exposes api.auth to SQL Injection [high] cwe:CWE-89 owasp:A03:2021
  • Descriptions use – “quoted text” format (not : colon)
  • Severity uses brackets: [critical] [high] [medium] [low] or [P0]-[P3]
  • Annotations work in any comment style: // /* # – <!– –>
  • Place annotations on the line ABOVE the code they describe
  • Asset names are case-insensitive and normalized (spaces→underscores)
  • Threat/control names can reference IDs with #id syntax
  • @flows uses -> arrow syntax (not “to”)
  • Run guardlink parse after adding annotations to update the threat model
  • Run guardlink validate to check for syntax errors and dangling references
  • Run guardlink annotate to have an AI agent add annotations automatically
  • Run guardlink entitle to decide proposed @entitles claims — an agent drafts, a human accepts