guardlink 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/README.md +14 -0
- package/dist/agents/config.d.ts +2 -0
- package/dist/agents/config.d.ts.map +1 -1
- package/dist/agents/config.js +1 -1
- package/dist/agents/config.js.map +1 -1
- package/dist/agents/prompts.d.ts +2 -2
- package/dist/agents/prompts.d.ts.map +1 -1
- package/dist/agents/prompts.js +223 -31
- package/dist/agents/prompts.js.map +1 -1
- package/dist/analyzer/sarif.js +1 -1
- package/dist/cli/index.js +2 -56
- package/dist/cli/index.js.map +1 -1
- package/dist/dashboard/data.d.ts.map +1 -1
- package/dist/dashboard/data.js +19 -12
- package/dist/dashboard/data.js.map +1 -1
- package/dist/dashboard/diagrams.d.ts.map +1 -1
- package/dist/dashboard/diagrams.js +310 -37
- package/dist/dashboard/diagrams.js.map +1 -1
- package/dist/dashboard/generate.d.ts.map +1 -1
- package/dist/dashboard/generate.js +21 -5
- package/dist/dashboard/generate.js.map +1 -1
- package/dist/init/picker.d.ts.map +1 -1
- package/dist/init/picker.js +2 -2
- package/dist/init/picker.js.map +1 -1
- package/dist/init/templates.js +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +8 -26
- package/dist/mcp/server.js.map +1 -1
- package/dist/parser/index.d.ts +1 -0
- package/dist/parser/index.d.ts.map +1 -1
- package/dist/parser/index.js +1 -0
- package/dist/parser/index.js.map +1 -1
- package/dist/parser/parse-line.js +3 -3
- package/dist/parser/parse-line.js.map +1 -1
- package/dist/parser/parse-project.js +1 -1
- package/dist/parser/validate.d.ts +19 -0
- package/dist/parser/validate.d.ts.map +1 -0
- package/dist/parser/validate.js +105 -0
- package/dist/parser/validate.js.map +1 -0
- package/dist/tui/commands.d.ts +1 -6
- package/dist/tui/commands.d.ts.map +1 -1
- package/dist/tui/commands.js +96 -221
- package/dist/tui/commands.js.map +1 -1
- package/dist/tui/config.d.ts +2 -0
- package/dist/tui/config.d.ts.map +1 -1
- package/dist/tui/config.js.map +1 -1
- package/dist/tui/index.d.ts.map +1 -1
- package/dist/tui/index.js +20 -24
- package/dist/tui/index.js.map +1 -1
- package/dist/tui/input.d.ts +2 -2
- package/dist/tui/input.js +2 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,34 @@ All notable changes to GuardLink CLI will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.1.0] — 2026-02-21
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Validation**: Shared `findDanglingRefs` and `findUnmitigatedExposures` with consistent `#id`/bare-name normalization across CLI, TUI, and MCP
|
|
13
|
+
- **Validation**: Expanded dangling ref checks to cover `@flows`, `@boundary`, `@audit`, `@owns`, `@handles`, `@assumes` annotations
|
|
14
|
+
- **Diagrams**: Threat graph now renders `@transfers`, `@validates`, trust boundaries, data classifications, ownership, and CWE references
|
|
15
|
+
- **Diagrams**: Heuristic icons for assets (👤 user, 🖥️ service, 🗄️ database) and flow mechanisms (🔐 TLS, 🌐 HTTP, 📨 queue)
|
|
16
|
+
- **Prompts**: Flow-first threat modeling methodology with architecture mapping, trust boundary identification, and coupled annotation style guide
|
|
17
|
+
- **Prompts**: Agent context now includes existing data flows and unmitigated exposures for smarter annotation
|
|
18
|
+
- **Model**: Two-step `/model` configuration — CLI Agents (Claude Code, Codex, Gemini) or API providers
|
|
19
|
+
- **Tests**: Dashboard diagram generation tests (label sanitization, severity resolution, transfers, validations)
|
|
20
|
+
- **Tests**: Parser regression tests (`@flows` via + description, `@shield` vs `@shield:begin` disambiguation)
|
|
21
|
+
- **Tests**: Validation unit tests (dangling refs, unmitigated exposure matching with ref normalization)
|
|
22
|
+
- **README**: Manual installation instructions (build from source + npm link)
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- **Parser**: `@flows` regex no longer swallows description when `via` mechanism is present
|
|
27
|
+
- **Parser**: `@shield` no longer incorrectly matches `@shield:begin` and `@shield:end`
|
|
28
|
+
- **Validation**: `#id` and bare-name refs now compare correctly (e.g., `#sqli` matches `sqli` in mitigations)
|
|
29
|
+
|
|
30
|
+
### Removed
|
|
31
|
+
|
|
32
|
+
- **TUI**: `/scan` command — redundant with `/status` coverage display; AI-driven annotation replaces manual symbol discovery
|
|
33
|
+
- **TUI**: `/exposures` and `/show` commands — exposure data remains accessible via `/validate`, MCP `guardlink_status`, and `guardlink://unmitigated` resource
|
|
34
|
+
- **Dependencies**: Removed accidental `build` package (unused)
|
|
35
|
+
|
|
8
36
|
## [1.0.0] — 2026-02-21
|
|
9
37
|
|
|
10
38
|
Initial public release of GuardLink.
|
package/README.md
CHANGED
|
@@ -35,6 +35,20 @@ npm install -g guardlink
|
|
|
35
35
|
|
|
36
36
|
Requires Node.js 18+.
|
|
37
37
|
|
|
38
|
+
### Manual Installation
|
|
39
|
+
|
|
40
|
+
To install from source:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# 1. Build the project
|
|
44
|
+
npm run build
|
|
45
|
+
|
|
46
|
+
# 2. Link globally
|
|
47
|
+
npm link
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
To uninstall: `npm unlink -g guardlink`
|
|
51
|
+
|
|
38
52
|
## Quick Start
|
|
39
53
|
|
|
40
54
|
```bash
|
package/dist/agents/config.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/agents/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIhE,UAAU,WAAW;IACnB,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/agents/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIhE,UAAU,WAAW;IACnB,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAgDD;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7D,SAAS,GAAG,IAAI,CAmDlB;AAiCD,0DAA0D;AAC1D,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,IAAI,CAEtE;AAED,4DAA4D;AAC5D,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAEvD;AAED,+CAA+C;AAC/C,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAGlE;AAED,yBAAyB;AACzB,wBAAgB,gBAAgB,IAAI,WAAW,GAAG,IAAI,CAErD;AAID,uDAAuD;AACvD,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG3C;AAED,iDAAiD;AACjD,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7C,MAAM,CAcR"}
|
package/dist/agents/config.js
CHANGED
|
@@ -176,7 +176,7 @@ export function describeConfigSource(root, flags) {
|
|
|
176
176
|
if (process.env.DEEPSEEK_API_KEY)
|
|
177
177
|
return 'DEEPSEEK_API_KEY env var';
|
|
178
178
|
const pc = readJsonFile(projectConfigPath(root));
|
|
179
|
-
if (pc && Object.keys(pc).length > 0 && pc.provider)
|
|
179
|
+
if (pc && Object.keys(pc).length > 0 && (pc.provider || pc.aiMode))
|
|
180
180
|
return `.guardlink/${CONFIG_FILE}`;
|
|
181
181
|
const lc = readJsonFile(legacyConfigPath(root));
|
|
182
182
|
if (lc && Object.keys(lc).length > 0 && lc.provider)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/agents/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/agents/config.ts"],"names":[],"mappings":"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"}
|
package/dist/agents/prompts.d.ts
CHANGED
|
@@ -7,8 +7,8 @@ import type { ThreatModel } from '../types/index.js';
|
|
|
7
7
|
/**
|
|
8
8
|
* Build a prompt for annotation agents.
|
|
9
9
|
*
|
|
10
|
-
* Includes the GuardLink reference doc
|
|
11
|
-
*
|
|
10
|
+
* Includes the GuardLink reference doc, current model summary with flows and exposures,
|
|
11
|
+
* flow-first threat modeling methodology, and precise GAL syntax rules.
|
|
12
12
|
*/
|
|
13
13
|
export declare function buildAnnotatePrompt(userPrompt: string, root: string, model: ThreatModel | null): string;
|
|
14
14
|
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/agents/prompts.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,WAAW,GAAG,IAAI,GACxB,MAAM,
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/agents/prompts.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,WAAW,GAAG,IAAI,GACxB,MAAM,CA6SR"}
|
package/dist/agents/prompts.js
CHANGED
|
@@ -8,8 +8,8 @@ import { resolve } from 'node:path';
|
|
|
8
8
|
/**
|
|
9
9
|
* Build a prompt for annotation agents.
|
|
10
10
|
*
|
|
11
|
-
* Includes the GuardLink reference doc
|
|
12
|
-
*
|
|
11
|
+
* Includes the GuardLink reference doc, current model summary with flows and exposures,
|
|
12
|
+
* flow-first threat modeling methodology, and precise GAL syntax rules.
|
|
13
13
|
*/
|
|
14
14
|
export function buildAnnotatePrompt(userPrompt, root, model) {
|
|
15
15
|
// Read the reference doc if available
|
|
@@ -18,8 +18,17 @@ export function buildAnnotatePrompt(userPrompt, root, model) {
|
|
|
18
18
|
if (existsSync(refPath)) {
|
|
19
19
|
refDoc = readFileSync(refPath, 'utf-8');
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
// Fall back to docs/GUARDLINK_REFERENCE.md
|
|
22
|
+
if (!refDoc) {
|
|
23
|
+
const docsRefPath = resolve(root, 'docs', 'GUARDLINK_REFERENCE.md');
|
|
24
|
+
if (existsSync(docsRefPath)) {
|
|
25
|
+
refDoc = readFileSync(docsRefPath, 'utf-8');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
let modelSummary = 'No threat model parsed yet. This may be a fresh project — define assets, threats, and controls first.';
|
|
22
29
|
let existingIds = '';
|
|
30
|
+
let existingFlows = '';
|
|
31
|
+
let existingExposures = '';
|
|
23
32
|
if (model) {
|
|
24
33
|
const parts = [
|
|
25
34
|
`${model.annotations_parsed} annotations`,
|
|
@@ -28,6 +37,8 @@ export function buildAnnotatePrompt(userPrompt, root, model) {
|
|
|
28
37
|
`${model.threats.length} threats`,
|
|
29
38
|
`${model.controls.length} controls`,
|
|
30
39
|
`${model.mitigations.length} mitigations`,
|
|
40
|
+
`${model.flows.length} flows`,
|
|
41
|
+
`${model.boundaries.length} boundaries`,
|
|
31
42
|
];
|
|
32
43
|
modelSummary = `Current model: ${parts.join(', ')}.`;
|
|
33
44
|
// Include existing IDs so the agent doesn't create duplicates or dangling refs
|
|
@@ -36,45 +47,208 @@ export function buildAnnotatePrompt(userPrompt, root, model) {
|
|
|
36
47
|
const controlIds = model.controls.filter(c => c.id).map(c => `#${c.id}`);
|
|
37
48
|
if (threatIds.length + assetIds.length + controlIds.length > 0) {
|
|
38
49
|
const sections = [];
|
|
39
|
-
if (threatIds.length)
|
|
40
|
-
sections.push(`Threats: ${threatIds.join(', ')}`);
|
|
41
50
|
if (assetIds.length)
|
|
42
51
|
sections.push(`Assets: ${assetIds.join(', ')}`);
|
|
52
|
+
if (threatIds.length)
|
|
53
|
+
sections.push(`Threats: ${threatIds.join(', ')}`);
|
|
43
54
|
if (controlIds.length)
|
|
44
55
|
sections.push(`Controls: ${controlIds.join(', ')}`);
|
|
45
|
-
existingIds = `\n\nExisting defined IDs (
|
|
56
|
+
existingIds = `\n\nExisting defined IDs (REUSE these — do NOT redefine):\n${sections.join('\n')}`;
|
|
57
|
+
}
|
|
58
|
+
// Include existing flows so agent understands the current flow graph
|
|
59
|
+
if (model.flows.length > 0) {
|
|
60
|
+
const flowLines = model.flows.slice(0, 30).map(f => ` ${f.source} -> ${f.target}${f.mechanism ? ` via ${f.mechanism}` : ''} (${f.location.file}:${f.location.line})`);
|
|
61
|
+
existingFlows = `\n\nExisting data flows (extend these, don't duplicate):\n${flowLines.join('\n')}`;
|
|
62
|
+
if (model.flows.length > 30)
|
|
63
|
+
existingFlows += `\n ... and ${model.flows.length - 30} more`;
|
|
64
|
+
}
|
|
65
|
+
// Include unmitigated exposures so agent knows what still needs attention
|
|
66
|
+
const unmitigatedExposures = model.exposures.filter(e => {
|
|
67
|
+
return !model.mitigations.some(m => m.asset === e.asset && m.threat === e.threat)
|
|
68
|
+
&& !model.acceptances.some(a => a.asset === e.asset && a.threat === e.threat);
|
|
69
|
+
});
|
|
70
|
+
if (unmitigatedExposures.length > 0) {
|
|
71
|
+
const expLines = unmitigatedExposures.slice(0, 20).map(e => ` ${e.asset} exposed to ${e.threat} [${e.severity || 'unrated'}] (${e.location.file}:${e.location.line})`);
|
|
72
|
+
existingExposures = `\n\nOpen exposures (unmitigated — add @mitigates or @accepts for these):\n${expLines.join('\n')}`;
|
|
73
|
+
if (unmitigatedExposures.length > 20)
|
|
74
|
+
existingExposures += `\n ... and ${unmitigatedExposures.length - 20} more`;
|
|
46
75
|
}
|
|
47
76
|
}
|
|
48
|
-
return `You are
|
|
77
|
+
return `You are an expert security engineer performing threat modeling as code.
|
|
78
|
+
Your job is to read this codebase deeply, understand how code flows between components, and annotate it with GuardLink (GAL) security annotations that accurately represent the security posture.
|
|
79
|
+
|
|
80
|
+
This is NOT a vulnerability scanner. You are building a living threat model embedded in the code itself.
|
|
81
|
+
Annotations capture what COULD go wrong, what controls exist, and how data moves — not just confirmed bugs.
|
|
49
82
|
|
|
50
|
-
${refDoc ? '## GuardLink Reference\n\n' + refDoc.slice(0, 4000) + '\n\n' : ''}## Current State
|
|
51
|
-
${modelSummary}${existingIds}
|
|
83
|
+
${refDoc ? '## GuardLink Annotation Language Reference\n\n' + refDoc.slice(0, 4000) + '\n\n' : ''}## Current State
|
|
84
|
+
${modelSummary}${existingIds}${existingFlows}${existingExposures}
|
|
52
85
|
|
|
53
|
-
## Task
|
|
86
|
+
## Your Task
|
|
54
87
|
${userPrompt}
|
|
55
88
|
|
|
56
|
-
##
|
|
89
|
+
## HOW TO THINK — Flow-First Threat Modeling
|
|
90
|
+
|
|
91
|
+
Before writing ANY annotation, you MUST understand the code deeply:
|
|
92
|
+
|
|
93
|
+
### Step 1: Map the Architecture
|
|
94
|
+
Read ALL source files related to the area you're annotating. Trace:
|
|
95
|
+
- Entry points (HTTP handlers, CLI commands, message consumers, event listeners)
|
|
96
|
+
- Data paths (how user input flows through functions, classes, middleware, to storage or output)
|
|
97
|
+
- Exit points (database writes, API calls, file I/O, rendered templates, responses)
|
|
98
|
+
- Class hierarchies, inherited methods, shared utilities, middleware chains
|
|
99
|
+
- Configuration and environment variable usage
|
|
100
|
+
|
|
101
|
+
### Step 2: Identify Trust Boundaries
|
|
102
|
+
Look for where trust changes:
|
|
103
|
+
- External user → application code (HTTP boundary)
|
|
104
|
+
- Application → database (data layer boundary)
|
|
105
|
+
- Service → service (network boundary)
|
|
106
|
+
- Frontend → backend (client/server boundary)
|
|
107
|
+
- Application → third-party API (vendor boundary)
|
|
108
|
+
- Internal code → spawned process (process boundary)
|
|
109
|
+
|
|
110
|
+
### Step 3: Identify What Could Go Wrong
|
|
111
|
+
At each boundary crossing and data transformation, ask:
|
|
112
|
+
- What if this input is malicious? (@exposes)
|
|
113
|
+
- What validation/sanitization exists? (@mitigates)
|
|
114
|
+
- What sensitive data passes through here? (@handles)
|
|
115
|
+
- Is there an assumption that could be violated? (@assumes)
|
|
116
|
+
- Has the team accepted this risk intentionally? (@accepts)
|
|
117
|
+
- Is this risk handled by someone else? (@transfers)
|
|
118
|
+
|
|
119
|
+
### Step 4: Write Coupled Annotation Blocks
|
|
120
|
+
NEVER write a single annotation in isolation. Every annotated location should tell a complete story.
|
|
121
|
+
|
|
122
|
+
## ANNOTATION STYLE GUIDE — Write Like a Developer
|
|
123
|
+
|
|
124
|
+
### Always Couple Annotations Together
|
|
125
|
+
A file's doc-block should paint the full security picture of that module. Group annotations logically:
|
|
126
|
+
|
|
127
|
+
\`\`\`
|
|
128
|
+
// @shield:begin -- "Example annotation block for reference, excluded from parsing"
|
|
129
|
+
//
|
|
130
|
+
// GOOD — Complete story at a single code location:
|
|
131
|
+
// @exposes #auth-api to #sqli [P1] cwe:CWE-89 -- "User-supplied email passed to findUser() query builder"
|
|
132
|
+
// @mitigates #auth-api against #sqli using #input-validation -- "Zod schema validates email format before query"
|
|
133
|
+
// @flows User_Input -> #auth-api via POST./login -- "Login form submits credentials"
|
|
134
|
+
// @flows #auth-api -> #user-db via TypeORM.findOne -- "Authenticated user lookup"
|
|
135
|
+
// @handles pii on #auth-api -- "Processes email, password, session tokens"
|
|
136
|
+
// @comment -- "Password comparison uses bcrypt.compare with timing-safe equality"
|
|
137
|
+
//
|
|
138
|
+
// BAD — Isolated annotation with no context:
|
|
139
|
+
// @exposes #auth-api to #sqli -- "SQL injection possible"
|
|
140
|
+
//
|
|
141
|
+
// @shield:end
|
|
142
|
+
\`\`\`
|
|
143
|
+
|
|
144
|
+
### Description Style — Reference Actual Code
|
|
145
|
+
Descriptions must reference the real code: function names, variable names, libraries, mechanisms.
|
|
146
|
+
|
|
147
|
+
\`\`\`
|
|
148
|
+
// @shield:begin -- "Description examples, excluded from parsing"
|
|
149
|
+
//
|
|
150
|
+
// GOOD: -- "req.body.token passed to jwt.verify() without audience check"
|
|
151
|
+
// GOOD: -- "bcrypt rounds set to 12 via BCRYPT_COST env var"
|
|
152
|
+
// GOOD: -- "Rate limiter uses express-rate-limit at 100req/15min on /api/*"
|
|
153
|
+
//
|
|
154
|
+
// BAD: -- "Input not validated" (too vague — WHICH input? WHERE?)
|
|
155
|
+
// BAD: -- "Uses encryption" (WHAT encryption? On WHAT data?)
|
|
156
|
+
// BAD: -- "Security vulnerability exists" (meaningless — be specific)
|
|
157
|
+
//
|
|
158
|
+
// @shield:end
|
|
159
|
+
\`\`\`
|
|
160
|
+
|
|
161
|
+
### @flows — Stitch the Complete Data Path
|
|
162
|
+
@flows is the backbone of the threat model. Trace data movement accurately:
|
|
163
|
+
|
|
164
|
+
\`\`\`
|
|
165
|
+
// @shield:begin -- "Flow examples, excluded from parsing"
|
|
166
|
+
//
|
|
167
|
+
// Trace a request through the full stack:
|
|
168
|
+
// @flows User_Browser -> #api-gateway via HTTPS -- "Client sends auth request"
|
|
169
|
+
// @flows #api-gateway -> #auth-service via internal.gRPC -- "Gateway forwards to auth microservice"
|
|
170
|
+
// @flows #auth-service -> #user-db via pg.query -- "Looks up user record by email"
|
|
171
|
+
// @flows #auth-service -> #session-store via redis.set -- "Stores session token with TTL"
|
|
172
|
+
// @flows #auth-service -> User_Browser via Set-Cookie -- "Returns session cookie to client"
|
|
173
|
+
//
|
|
174
|
+
// @shield:end
|
|
175
|
+
\`\`\`
|
|
176
|
+
|
|
177
|
+
### @boundary — Mark Every Trust Zone Crossing
|
|
178
|
+
Place @boundary annotations where trust level changes between two components:
|
|
179
|
+
|
|
180
|
+
\`\`\`
|
|
181
|
+
// @shield:begin -- "Boundary examples, excluded from parsing"
|
|
182
|
+
//
|
|
183
|
+
// @boundary between #api-gateway and External_Internet (#public-boundary) -- "TLS termination, rate limiting at edge"
|
|
184
|
+
// @boundary between #backend and #database (#data-boundary) -- "Application to persistence layer, connection pooling via pgBouncer"
|
|
185
|
+
// @boundary between #app and #payment-provider (#vendor-boundary) -- "PCI-DSS scope boundary, tokenized card data only"
|
|
186
|
+
//
|
|
187
|
+
// @shield:end
|
|
188
|
+
\`\`\`
|
|
57
189
|
|
|
58
|
-
|
|
190
|
+
### Where to Place Annotations
|
|
191
|
+
Annotations go in the file's top doc-block comment OR directly above the security-relevant code:
|
|
59
192
|
|
|
60
|
-
### Definitions
|
|
61
193
|
\`\`\`
|
|
62
|
-
// @shield:begin -- "
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
// @
|
|
194
|
+
// @shield:begin -- "Placement examples, excluded from parsing"
|
|
195
|
+
//
|
|
196
|
+
// FILE-LEVEL (top doc-block) — for module-wide security properties:
|
|
197
|
+
// Place @exposes, @mitigates, @flows, @handles, @boundary that describe the module as a whole
|
|
198
|
+
//
|
|
199
|
+
// INLINE (above specific functions/methods) — for function-specific concerns:
|
|
200
|
+
// Place @exposes, @mitigates above the exact function where the risk or control lives
|
|
201
|
+
// Place @comment above tricky security-relevant code to explain intent
|
|
202
|
+
//
|
|
66
203
|
// @shield:end
|
|
67
204
|
\`\`\`
|
|
68
205
|
|
|
69
|
-
###
|
|
206
|
+
### Severity — Be Honest, Not Alarmist
|
|
207
|
+
Annotations capture what COULD go wrong, calibrated to realistic risk:
|
|
208
|
+
- **[P0] / [critical]**: Directly exploitable by external attacker, severe impact (RCE, auth bypass, data breach)
|
|
209
|
+
- **[P1] / [high]**: Exploitable with some conditions, significant impact (privilege escalation, data leak)
|
|
210
|
+
- **[P2] / [medium]**: Requires specific conditions or insider access (SSRF, info disclosure)
|
|
211
|
+
- **[P3] / [low]**: Minor impact or very difficult to exploit (timing side-channels, verbose errors)
|
|
212
|
+
|
|
213
|
+
Don't rate everything P0. A SQL injection in an admin-only internal tool is different from one in a public API.
|
|
214
|
+
|
|
215
|
+
### @comment — Always Add Context
|
|
216
|
+
Every annotation block should include at least one @comment explaining non-obvious security decisions, assumptions, or context that helps future developers (and AI tools) understand the "why".
|
|
217
|
+
|
|
218
|
+
### @shield — DO NOT USE Unless Explicitly Asked
|
|
219
|
+
@shield and @shield:begin/@shield:end block AI coding assistants from reading the annotated code.
|
|
220
|
+
This means any shielded code becomes invisible to AI tools — they cannot analyze, refactor, or annotate it.
|
|
221
|
+
Do NOT add @shield annotations unless the user has EXPLICITLY requested it (e.g., "shield the crypto module").
|
|
222
|
+
Adding @shield on your own initiative would actively harm the threat model by creating blind spots where AI cannot help.
|
|
223
|
+
|
|
224
|
+
## PRECISE GAL Syntax
|
|
225
|
+
|
|
226
|
+
Definitions go in .guardlink/definitions.{ts,js,py,rs}. Source files use only relationship verbs.
|
|
227
|
+
|
|
228
|
+
### Definitions (in .guardlink/definitions file)
|
|
70
229
|
\`\`\`
|
|
71
|
-
// @shield:begin -- "
|
|
230
|
+
// @shield:begin -- "Definition syntax examples, excluded from parsing"
|
|
231
|
+
// @asset Server.Auth (#auth) -- "Authentication service handling login and session management"
|
|
232
|
+
// @threat SQL_Injection (#sqli) [P0] cwe:CWE-89 -- "Unsanitized input reaches SQL query builder"
|
|
233
|
+
// @control Prepared_Statements (#prepared-stmts) -- "Parameterized queries via ORM or driver placeholders"
|
|
234
|
+
// @shield:end
|
|
235
|
+
\`\`\`
|
|
236
|
+
|
|
237
|
+
### Relationships (in source files)
|
|
238
|
+
\`\`\`
|
|
239
|
+
// @shield:begin -- "Relationship syntax examples, excluded from parsing"
|
|
72
240
|
// @exposes #auth to #sqli [P0] cwe:CWE-89 owasp:A03:2021 -- "User input concatenated into query"
|
|
73
|
-
// @mitigates #auth against #sqli using #prepared-stmts -- "Uses parameterized queries"
|
|
241
|
+
// @mitigates #auth against #sqli using #prepared-stmts -- "Uses parameterized queries via sqlx"
|
|
242
|
+
// @accepts #timing-attack on #auth -- "Acceptable given bcrypt constant-time comparison"
|
|
243
|
+
// @transfers #ddos from #api to #cdn -- "Cloudflare handles L7 DDoS mitigation"
|
|
74
244
|
// @flows req.body.username -> db.query via string-concat -- "User input flows to SQL"
|
|
75
|
-
// @boundary between #frontend and #api (#
|
|
76
|
-
// @handles pii on #auth -- "Processes
|
|
77
|
-
// @
|
|
245
|
+
// @boundary between #frontend and #api (#web-boundary) -- "TLS-terminated public/private boundary"
|
|
246
|
+
// @handles pii on #auth -- "Processes email, password, session tokens"
|
|
247
|
+
// @validates #prepared-stmts for #auth -- "Integration test sqlInjectionTest.ts confirms parameterized queries block SQLi payloads"
|
|
248
|
+
// @audit #auth -- "Session token rotation logic needs cryptographic review"
|
|
249
|
+
// @assumes #auth -- "Upstream API gateway has already validated TLS and rate-limited requests"
|
|
250
|
+
// @owns security-team for #auth -- "Security team reviews all auth PRs"
|
|
251
|
+
// @comment -- "Password hashing uses bcrypt with cost factor 12, migration from SHA256 completed in v2.1"
|
|
78
252
|
// @shield:end
|
|
79
253
|
\`\`\`
|
|
80
254
|
|
|
@@ -84,13 +258,13 @@ Definitions go in .guardlink/definitions.js (or .py/.rs). Source files use only
|
|
|
84
258
|
WRONG: \`@boundary api -- "desc"\` (only one argument — will NOT parse)
|
|
85
259
|
RIGHT: \`@boundary between #api and #client (#api-boundary) -- "Trust boundary"\`
|
|
86
260
|
|
|
87
|
-
2. **@flows is ONE source
|
|
261
|
+
2. **@flows is ONE source -> ONE target per line**: \`@flows <source> -> <target> via <mechanism>\`.
|
|
88
262
|
WRONG: \`@flows A -> B, C -> D -- "desc"\` (commas not supported)
|
|
89
263
|
RIGHT: \`@flows A -> B via mechanism -- "desc"\` (one per line, repeat for multiple)
|
|
90
264
|
|
|
91
265
|
3. **@exposes / @mitigates require DEFINED #id refs**: Every \`#id\` you reference must exist as a definition.
|
|
92
266
|
Before using \`@exposes #app to #sqli\`, ensure \`@threat SQL_Injection (#sqli)\` exists in definitions.
|
|
93
|
-
Add new definitions to .guardlink/definitions
|
|
267
|
+
Add new definitions to the .guardlink/definitions file FIRST, then reference them in source files.
|
|
94
268
|
|
|
95
269
|
4. **Severity in square brackets**: \`[P0]\` \`[P1]\` \`[P2]\` \`[P3]\` or \`[critical]\` \`[high]\` \`[medium]\` \`[low]\`.
|
|
96
270
|
Goes AFTER the threat ref in @exposes: \`@exposes #app to #sqli [P0] cwe:CWE-89\`
|
|
@@ -108,13 +282,31 @@ Definitions go in .guardlink/definitions.js (or .py/.rs). Source files use only
|
|
|
108
282
|
|
|
109
283
|
8. **External refs are space-separated after severity**: \`cwe:CWE-89 owasp:A03:2021 capec:CAPEC-66\`
|
|
110
284
|
|
|
285
|
+
9. **@comment always needs -- and quotes**: \`@comment -- "your note here"\`.
|
|
286
|
+
A bare \`@comment\` without description is valid but useless. Always include context.
|
|
287
|
+
|
|
288
|
+
10. **One annotation per comment line.** Do NOT put two @verbs on the same line.
|
|
289
|
+
|
|
111
290
|
## Workflow
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
291
|
+
|
|
292
|
+
1. **Read first, annotate second.** Read ALL related source files before writing any annotation.
|
|
293
|
+
Trace the full call chain: entry point → middleware → handler → service → repository → database.
|
|
294
|
+
Understand class hierarchies, shared utilities, and configuration.
|
|
295
|
+
|
|
296
|
+
2. **Read existing definitions** in the .guardlink/definitions file — reuse existing IDs, never duplicate.
|
|
297
|
+
|
|
298
|
+
3. **Add NEW definitions FIRST** if you need new assets, threats, or controls.
|
|
299
|
+
Group related definitions together with section comments.
|
|
300
|
+
|
|
301
|
+
4. **Annotate in coupled blocks.** For each security-relevant location, write the complete story:
|
|
302
|
+
@exposes + @mitigates (or @accepts) + @flows + @comment at minimum.
|
|
303
|
+
Think: "what's the risk, what's the defense, how does data flow here, and what should the next developer know?"
|
|
304
|
+
|
|
305
|
+
5. **Use the project's comment style** (// for JS/TS/Go/Rust, # for Python/Ruby/Shell, etc.)
|
|
306
|
+
|
|
307
|
+
6. **Run validation** via guardlink_validate (MCP) or \`guardlink validate\` to check for errors.
|
|
308
|
+
|
|
309
|
+
7. **Fix any validation errors** before finishing — especially dangling refs and malformed syntax.
|
|
118
310
|
`;
|
|
119
311
|
}
|
|
120
312
|
//# sourceMappingURL=prompts.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/agents/prompts.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CACjC,UAAkB,EAClB,IAAY,EACZ,KAAyB;IAEzB,sCAAsC;IACtC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,wBAAwB,CAAC,CAAC;IACtE,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,MAAM,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IAED,IAAI,YAAY,GAAG,
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/agents/prompts.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CACjC,UAAkB,EAClB,IAAY,EACZ,KAAyB;IAEzB,sCAAsC;IACtC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,wBAAwB,CAAC,CAAC;IACtE,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,MAAM,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IACD,2CAA2C;IAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,wBAAwB,CAAC,CAAC;QACpE,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC5B,MAAM,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,IAAI,YAAY,GAAG,uGAAuG,CAAC;IAC3H,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,IAAI,aAAa,GAAG,EAAE,CAAC;IACvB,IAAI,iBAAiB,GAAG,EAAE,CAAC;IAC3B,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,KAAK,GAAG;YACZ,GAAG,KAAK,CAAC,kBAAkB,cAAc;YACzC,GAAG,KAAK,CAAC,SAAS,CAAC,MAAM,YAAY;YACrC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,SAAS;YAC/B,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,UAAU;YACjC,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,WAAW;YACnC,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,cAAc;YACzC,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,QAAQ;YAC7B,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,aAAa;SACxC,CAAC;QACF,YAAY,GAAG,kBAAkB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;QAErD,+EAA+E;QAC/E,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACvE,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACrE,MAAM,UAAU,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACzE,IAAI,SAAS,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/D,MAAM,QAAQ,GAAa,EAAE,CAAC;YAC9B,IAAI,QAAQ,CAAC,MAAM;gBAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACrE,IAAI,SAAS,CAAC,MAAM;gBAAE,QAAQ,CAAC,IAAI,CAAC,YAAY,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACxE,IAAI,UAAU,CAAC,MAAM;gBAAE,QAAQ,CAAC,IAAI,CAAC,aAAa,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC3E,WAAW,GAAG,8DAA8D,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACpG,CAAC;QAED,qEAAqE;QACrE,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CACjD,KAAK,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,GAAG,CAClH,CAAC;YACF,aAAa,GAAG,6DAA6D,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACpG,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,EAAE;gBAAE,aAAa,IAAI,eAAe,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,EAAE,OAAO,CAAC;QAC9F,CAAC;QAED,0EAA0E;QAC1E,MAAM,oBAAoB,GAAG,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;YACtD,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,CAAC;mBAC5E,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC;QAClF,CAAC,CAAC,CAAC;QACH,IAAI,oBAAoB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpC,MAAM,QAAQ,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CACzD,KAAK,CAAC,CAAC,KAAK,eAAe,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,QAAQ,IAAI,SAAS,MAAM,CAAC,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,GAAG,CAC3G,CAAC;YACF,iBAAiB,GAAG,6EAA6E,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACvH,IAAI,oBAAoB,CAAC,MAAM,GAAG,EAAE;gBAAE,iBAAiB,IAAI,eAAe,oBAAoB,CAAC,MAAM,GAAG,EAAE,OAAO,CAAC;QACpH,CAAC;IACH,CAAC;IAED,OAAO;;;;;;EAMP,MAAM,CAAC,CAAC,CAAC,gDAAgD,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE;EAC/F,YAAY,GAAG,WAAW,GAAG,aAAa,GAAG,iBAAiB;;;EAG9D,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+NX,CAAC;AACF,CAAC"}
|
package/dist/analyzer/sarif.js
CHANGED
package/dist/cli/index.js
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
import { Command } from 'commander';
|
|
25
25
|
import { resolve, basename } from 'node:path';
|
|
26
26
|
import { readFileSync, existsSync } from 'node:fs';
|
|
27
|
-
import { parseProject } from '../parser/index.js';
|
|
27
|
+
import { parseProject, findDanglingRefs, findUnmitigatedExposures } from '../parser/index.js';
|
|
28
28
|
import { initProject, detectProject, promptAgentSelection } from '../init/index.js';
|
|
29
29
|
import { generateReport, generateMermaid } from '../report/index.js';
|
|
30
30
|
import { diffModels, formatDiff, formatDiffMarkdown, parseAtRef } from '../diff/index.js';
|
|
@@ -80,7 +80,7 @@ function detectProjectName(root, explicit) {
|
|
|
80
80
|
program
|
|
81
81
|
.name('guardlink')
|
|
82
82
|
.description('GuardLink — Security annotations for code. Threat modeling that lives in your codebase.')
|
|
83
|
-
.version('1.
|
|
83
|
+
.version('1.1.0')
|
|
84
84
|
.addHelpText('before', gradient(['#00ff41', '#00d4ff'])(ASCII_LOGO));
|
|
85
85
|
// ─── init ────────────────────────────────────────────────────────────
|
|
86
86
|
program
|
|
@@ -764,58 +764,4 @@ function printStatus(model) {
|
|
|
764
764
|
console.log(`Comments: ${model.comments.length}`);
|
|
765
765
|
console.log(`Shields: ${model.shields.length}`);
|
|
766
766
|
}
|
|
767
|
-
function findDanglingRefs(model) {
|
|
768
|
-
const diagnostics = [];
|
|
769
|
-
// Collect all defined IDs
|
|
770
|
-
const definedIds = new Set();
|
|
771
|
-
for (const a of model.assets)
|
|
772
|
-
if (a.id)
|
|
773
|
-
definedIds.add(a.id);
|
|
774
|
-
for (const t of model.threats)
|
|
775
|
-
if (t.id)
|
|
776
|
-
definedIds.add(t.id);
|
|
777
|
-
for (const c of model.controls)
|
|
778
|
-
if (c.id)
|
|
779
|
-
definedIds.add(c.id);
|
|
780
|
-
for (const b of model.boundaries)
|
|
781
|
-
if (b.id)
|
|
782
|
-
definedIds.add(b.id);
|
|
783
|
-
// Check all references
|
|
784
|
-
const checkRef = (ref, loc) => {
|
|
785
|
-
if (ref.startsWith('#')) {
|
|
786
|
-
const id = ref.slice(1);
|
|
787
|
-
if (!definedIds.has(id)) {
|
|
788
|
-
diagnostics.push({
|
|
789
|
-
level: 'warning',
|
|
790
|
-
message: `Dangling reference: #${id} is never defined`,
|
|
791
|
-
file: loc.file,
|
|
792
|
-
line: loc.line,
|
|
793
|
-
});
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
};
|
|
797
|
-
for (const m of model.mitigations) {
|
|
798
|
-
checkRef(m.threat, m.location);
|
|
799
|
-
if (m.control)
|
|
800
|
-
checkRef(m.control, m.location);
|
|
801
|
-
}
|
|
802
|
-
for (const e of model.exposures)
|
|
803
|
-
checkRef(e.threat, e.location);
|
|
804
|
-
for (const a of model.acceptances)
|
|
805
|
-
checkRef(a.threat, a.location);
|
|
806
|
-
for (const t of model.transfers)
|
|
807
|
-
checkRef(t.threat, t.location);
|
|
808
|
-
for (const v of model.validations)
|
|
809
|
-
checkRef(v.control, v.location);
|
|
810
|
-
return diagnostics;
|
|
811
|
-
}
|
|
812
|
-
function findUnmitigatedExposures(model) {
|
|
813
|
-
// Build set of (asset, threat) pairs that are mitigated or accepted
|
|
814
|
-
const mitigated = new Set();
|
|
815
|
-
for (const m of model.mitigations)
|
|
816
|
-
mitigated.add(`${m.asset}::${m.threat}`);
|
|
817
|
-
for (const a of model.acceptances)
|
|
818
|
-
mitigated.add(`${a.asset}::${a.threat}`);
|
|
819
|
-
return model.exposures.filter(e => !mitigated.has(`${e.asset}::${e.threat}`));
|
|
820
|
-
}
|
|
821
767
|
//# sourceMappingURL=index.js.map
|