guardlink 1.4.0 → 1.4.2
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 +48 -0
- package/README.md +17 -3
- package/dist/agents/index.d.ts +8 -0
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +35 -0
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/launcher.d.ts +1 -1
- package/dist/agents/launcher.d.ts.map +1 -1
- package/dist/agents/launcher.js +6 -1
- package/dist/agents/launcher.js.map +1 -1
- package/dist/agents/prompts.d.ts +2 -1
- package/dist/agents/prompts.d.ts.map +1 -1
- package/dist/agents/prompts.js +66 -14
- package/dist/agents/prompts.js.map +1 -1
- package/dist/analyze/prompts.js +1 -1
- package/dist/cli/index.js +86 -49
- package/dist/cli/index.js.map +1 -1
- package/dist/diff/git.js +3 -3
- package/dist/diff/git.js.map +1 -1
- package/dist/init/index.d.ts +7 -0
- package/dist/init/index.d.ts.map +1 -1
- package/dist/init/index.js +60 -24
- package/dist/init/index.js.map +1 -1
- package/dist/init/templates.js +5 -5
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +13 -8
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/suggest.d.ts +1 -0
- package/dist/mcp/suggest.d.ts.map +1 -1
- package/dist/mcp/suggest.js +1 -0
- package/dist/mcp/suggest.js.map +1 -1
- package/dist/parser/clear.d.ts +2 -1
- package/dist/parser/clear.d.ts.map +1 -1
- package/dist/parser/clear.js +18 -28
- package/dist/parser/clear.js.map +1 -1
- package/dist/parser/comment-strip.d.ts +5 -0
- package/dist/parser/comment-strip.d.ts.map +1 -1
- package/dist/parser/comment-strip.js +8 -0
- package/dist/parser/comment-strip.js.map +1 -1
- package/dist/parser/parse-file.d.ts +1 -0
- package/dist/parser/parse-file.d.ts.map +1 -1
- package/dist/parser/parse-file.js +31 -8
- package/dist/parser/parse-file.js.map +1 -1
- package/dist/parser/parse-line.d.ts +6 -0
- package/dist/parser/parse-line.d.ts.map +1 -1
- package/dist/parser/parse-line.js +23 -5
- package/dist/parser/parse-line.js.map +1 -1
- package/dist/parser/parse-project.d.ts +1 -0
- package/dist/parser/parse-project.d.ts.map +1 -1
- package/dist/parser/parse-project.js +17 -2
- package/dist/parser/parse-project.js.map +1 -1
- package/dist/review/index.d.ts +3 -1
- package/dist/review/index.d.ts.map +1 -1
- package/dist/review/index.js +77 -35
- package/dist/review/index.js.map +1 -1
- package/dist/tui/commands.d.ts.map +1 -1
- package/dist/tui/commands.js +72 -46
- package/dist/tui/commands.js.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/review/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/review/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAIpF,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,WAAW,GAAG,MAAM,CAAC;AAE7D,MAAM,WAAW,kBAAkB;IACjC,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,wBAAwB;IACxB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,cAAc,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,MAAM,EAAE,YAAY,CAAC;IACrB,oDAAoD;IACpD,aAAa,EAAE,MAAM,CAAC;IACtB,wDAAwD;IACxD,UAAU,EAAE,MAAM,CAAC;CACpB;AAWD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,WAAW,GAAG,kBAAkB,EAAE,CAsB/E;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,CAAC,EAAE,QAAQ,GAAG,MAAM,CAGlD;AAuKD;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,kBAAkB,EAC9B,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,YAAY,CAAC,CAwBvB;AAqBD;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CASpF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAY/D"}
|
package/dist/review/index.js
CHANGED
|
@@ -15,8 +15,9 @@
|
|
|
15
15
|
* @handles internal on #cli -- "Processes exposure metadata and user justification text"
|
|
16
16
|
*/
|
|
17
17
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
18
|
-
import { resolve } from 'node:path';
|
|
19
|
-
import { stripCommentPrefix } from '../parser/comment-strip.js';
|
|
18
|
+
import { extname, resolve } from 'node:path';
|
|
19
|
+
import { commentStyleForExt, stripCommentPrefix } from '../parser/comment-strip.js';
|
|
20
|
+
import { parseLine } from '../parser/parse-line.js';
|
|
20
21
|
import { findUnmitigatedExposures } from '../parser/validate.js';
|
|
21
22
|
// ─── Severity ordering ──────────────────────────────────────────────
|
|
22
23
|
const SEVERITY_ORDER = {
|
|
@@ -45,7 +46,7 @@ export function getReviewableExposures(model) {
|
|
|
45
46
|
return filtered.map((exposure, i) => ({
|
|
46
47
|
index: i + 1,
|
|
47
48
|
exposure,
|
|
48
|
-
id:
|
|
49
|
+
id: reviewExposureId(exposure),
|
|
49
50
|
}));
|
|
50
51
|
}
|
|
51
52
|
/**
|
|
@@ -60,39 +61,57 @@ export function severityLabel(s) {
|
|
|
60
61
|
* Detect the comment style and indentation from the @exposes source line.
|
|
61
62
|
* Supports JSDoc ( * @...), single-line (// @...), and hash (# @...) styles.
|
|
62
63
|
*/
|
|
63
|
-
function detectCommentStyle(rawLine) {
|
|
64
|
+
function detectCommentStyle(rawLine, filePath) {
|
|
64
65
|
const indent = rawLine.match(/^(\s*)/)?.[1] || '';
|
|
65
66
|
const trimmed = rawLine.trimStart();
|
|
67
|
+
if (trimmed.startsWith('@')) {
|
|
68
|
+
return { prefix: '', suffix: '', indent };
|
|
69
|
+
}
|
|
66
70
|
if (trimmed.startsWith('* @') || trimmed.startsWith('* @')) {
|
|
67
|
-
return { prefix: '* ', indent };
|
|
71
|
+
return { prefix: '* ', suffix: '', indent };
|
|
68
72
|
}
|
|
69
73
|
if (trimmed.startsWith('// @')) {
|
|
70
|
-
return { prefix: '// ', indent };
|
|
74
|
+
return { prefix: '// ', suffix: '', indent };
|
|
71
75
|
}
|
|
72
76
|
if (trimmed.startsWith('# @')) {
|
|
73
|
-
return { prefix: '# ', indent };
|
|
77
|
+
return { prefix: '# ', suffix: '', indent };
|
|
74
78
|
}
|
|
75
79
|
if (trimmed.startsWith('-- @')) {
|
|
76
|
-
return { prefix: '-- ', indent };
|
|
80
|
+
return { prefix: '-- ', suffix: '', indent };
|
|
81
|
+
}
|
|
82
|
+
if (trimmed.startsWith('<!--')) {
|
|
83
|
+
return { prefix: '<!-- ', suffix: ' -->', indent };
|
|
84
|
+
}
|
|
85
|
+
if (trimmed.startsWith('/*')) {
|
|
86
|
+
return { prefix: '/* ', suffix: ' */', indent };
|
|
87
|
+
}
|
|
88
|
+
return fallbackCommentStyle(filePath, indent);
|
|
89
|
+
}
|
|
90
|
+
function fallbackCommentStyle(filePath, indent) {
|
|
91
|
+
switch (commentStyleForExt(extname(filePath))) {
|
|
92
|
+
case '#': return { prefix: '# ', suffix: '', indent };
|
|
93
|
+
case '--': return { prefix: '-- ', suffix: '', indent };
|
|
94
|
+
case '<!--': return { prefix: '<!-- ', suffix: ' -->', indent };
|
|
95
|
+
case '/*': return { prefix: '/* ', suffix: ' */', indent };
|
|
96
|
+
case '%': return { prefix: '% ', suffix: '', indent };
|
|
97
|
+
case ';': return { prefix: '; ', suffix: '', indent };
|
|
98
|
+
case 'REM': return { prefix: 'REM ', suffix: '', indent };
|
|
99
|
+
case "'": return { prefix: "' ", suffix: '', indent };
|
|
100
|
+
case '//':
|
|
101
|
+
default:
|
|
102
|
+
return { prefix: '// ', suffix: '', indent };
|
|
77
103
|
}
|
|
78
|
-
// Fallback: single-line JS style
|
|
79
|
-
return { prefix: '// ', indent };
|
|
80
104
|
}
|
|
81
105
|
/**
|
|
82
106
|
* Check if a source line is a GuardLink annotation (used to walk past coupled blocks).
|
|
83
107
|
*/
|
|
84
108
|
function isAnnotationLine(line) {
|
|
85
|
-
const
|
|
86
|
-
if (
|
|
87
|
-
return false;
|
|
88
|
-
const trimmed = inner.trim();
|
|
89
|
-
// Annotation line: starts with @verb
|
|
90
|
-
if (trimmed.startsWith('@'))
|
|
109
|
+
const rawTrimmed = line.trimStart();
|
|
110
|
+
if (/^--\s*"/.test(rawTrimmed))
|
|
91
111
|
return true;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
return false;
|
|
112
|
+
const inner = stripCommentPrefix(line) ?? rawTrimmed;
|
|
113
|
+
const parsed = parseLine(inner, { file: '<review>', line: 1 });
|
|
114
|
+
return Boolean(parsed.annotation || parsed.sourceDirective || parsed.isContinuation);
|
|
96
115
|
}
|
|
97
116
|
/**
|
|
98
117
|
* Find the insertion point after the coupled annotation block that contains
|
|
@@ -101,11 +120,14 @@ function isAnnotationLine(line) {
|
|
|
101
120
|
* Walks forward from the exposure line past consecutive annotation lines
|
|
102
121
|
* to find the end of the block, then returns the 0-indexed line to insert after.
|
|
103
122
|
*/
|
|
104
|
-
function findInsertionIndex(lines, exposureLine) {
|
|
123
|
+
function findInsertionIndex(lines, exposureLine, stopAtSourceBoundary = false) {
|
|
105
124
|
// exposureLine is 1-indexed, convert to 0-indexed
|
|
106
125
|
let idx = exposureLine - 1;
|
|
107
126
|
// Walk forward past consecutive annotation lines
|
|
108
127
|
while (idx + 1 < lines.length && isAnnotationLine(lines[idx + 1])) {
|
|
128
|
+
if (stopAtSourceBoundary && lines[idx + 1].trimStart().startsWith('@source')) {
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
109
131
|
idx++;
|
|
110
132
|
}
|
|
111
133
|
// Insert after the last annotation line in the block
|
|
@@ -120,21 +142,21 @@ function todayISO() {
|
|
|
120
142
|
* Returns lines WITHOUT trailing newline.
|
|
121
143
|
*/
|
|
122
144
|
function buildAcceptLines(style, exposure, justification) {
|
|
123
|
-
const { prefix, indent } = style;
|
|
145
|
+
const { prefix, suffix, indent } = style;
|
|
124
146
|
const date = todayISO();
|
|
125
147
|
return [
|
|
126
|
-
`${indent}${prefix}@accepts ${exposure.threat} on ${exposure.asset} -- "${escapeDesc(justification)}"`,
|
|
127
|
-
`${indent}${prefix}@audit ${exposure.asset} -- "Accepted via guardlink review on ${date}"`,
|
|
148
|
+
`${indent}${prefix}@accepts ${exposure.threat} on ${exposure.asset} -- "${escapeDesc(justification)}"${suffix}`,
|
|
149
|
+
`${indent}${prefix}@audit ${exposure.asset} -- "Accepted via guardlink review on ${date}"${suffix}`,
|
|
128
150
|
];
|
|
129
151
|
}
|
|
130
152
|
/**
|
|
131
153
|
* Build the annotation line to insert for a "remediate" decision.
|
|
132
154
|
*/
|
|
133
155
|
function buildRemediateLines(style, exposure, note) {
|
|
134
|
-
const { prefix, indent } = style;
|
|
156
|
+
const { prefix, suffix, indent } = style;
|
|
135
157
|
const date = todayISO();
|
|
136
158
|
return [
|
|
137
|
-
`${indent}${prefix}@audit ${exposure.asset} -- "Planned remediation: ${escapeDesc(note)} — flagged via guardlink review on ${date}"`,
|
|
159
|
+
`${indent}${prefix}@audit ${exposure.asset} -- "Planned remediation: ${escapeDesc(note)} — flagged via guardlink review on ${date}"${suffix}`,
|
|
138
160
|
];
|
|
139
161
|
}
|
|
140
162
|
/** Escape double quotes in description strings */
|
|
@@ -149,15 +171,17 @@ function escapeDesc(s) {
|
|
|
149
171
|
* Returns the number of lines inserted.
|
|
150
172
|
*/
|
|
151
173
|
async function insertAnnotations(root, exposure, newLines) {
|
|
152
|
-
const filePath = resolve(root, exposure.
|
|
174
|
+
const filePath = resolve(root, getWriteLocation(exposure).file);
|
|
153
175
|
const content = await readFile(filePath, 'utf-8');
|
|
154
176
|
const lines = content.split('\n');
|
|
155
177
|
// Validate that the exposure line exists and looks right
|
|
156
|
-
const
|
|
178
|
+
const targetLocation = getWriteLocation(exposure);
|
|
179
|
+
const exposureIdx = targetLocation.line - 1; // 0-indexed
|
|
157
180
|
if (exposureIdx < 0 || exposureIdx >= lines.length) {
|
|
158
|
-
throw new Error(`Line ${
|
|
181
|
+
throw new Error(`Line ${targetLocation.line} out of range in ${targetLocation.file}`);
|
|
159
182
|
}
|
|
160
|
-
const
|
|
183
|
+
const style = detectCommentStyle(lines[exposureIdx], targetLocation.file);
|
|
184
|
+
const insertIdx = findInsertionIndex(lines, targetLocation.line, style.prefix === '');
|
|
161
185
|
// Splice in the new lines
|
|
162
186
|
lines.splice(insertIdx, 0, ...newLines);
|
|
163
187
|
await writeFile(filePath, lines.join('\n'));
|
|
@@ -174,15 +198,16 @@ async function insertAnnotations(root, exposure, newLines) {
|
|
|
174
198
|
*/
|
|
175
199
|
export async function applyReviewAction(root, reviewable, action) {
|
|
176
200
|
if (action.decision === 'skip') {
|
|
177
|
-
return { exposure: reviewable, action, linesInserted: 0 };
|
|
201
|
+
return { exposure: reviewable, action, linesInserted: 0, targetFile: getWriteLocation(reviewable.exposure).file };
|
|
178
202
|
}
|
|
179
203
|
const { exposure } = reviewable;
|
|
180
|
-
const
|
|
204
|
+
const targetLocation = getWriteLocation(exposure);
|
|
205
|
+
const filePath = resolve(root, targetLocation.file);
|
|
181
206
|
const content = await readFile(filePath, 'utf-8');
|
|
182
207
|
const lines = content.split('\n');
|
|
183
208
|
// Detect comment style from the @exposes line
|
|
184
|
-
const exposureIdx =
|
|
185
|
-
const style = detectCommentStyle(lines[exposureIdx]);
|
|
209
|
+
const exposureIdx = targetLocation.line - 1;
|
|
210
|
+
const style = detectCommentStyle(lines[exposureIdx], targetLocation.file);
|
|
186
211
|
let newLines;
|
|
187
212
|
if (action.decision === 'accept') {
|
|
188
213
|
newLines = buildAcceptLines(style, exposure, action.justification);
|
|
@@ -191,7 +216,24 @@ export async function applyReviewAction(root, reviewable, action) {
|
|
|
191
216
|
newLines = buildRemediateLines(style, exposure, action.justification);
|
|
192
217
|
}
|
|
193
218
|
const linesInserted = await insertAnnotations(root, exposure, newLines);
|
|
194
|
-
return { exposure: reviewable, action, linesInserted };
|
|
219
|
+
return { exposure: reviewable, action, linesInserted, targetFile: targetLocation.file };
|
|
220
|
+
}
|
|
221
|
+
function getWriteLocation(exposure) {
|
|
222
|
+
return {
|
|
223
|
+
file: exposure.location.origin_file || exposure.location.file,
|
|
224
|
+
line: exposure.location.origin_line || exposure.location.line,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
function reviewExposureId(exposure) {
|
|
228
|
+
const writeLocation = getWriteLocation(exposure);
|
|
229
|
+
return [
|
|
230
|
+
writeLocation.file,
|
|
231
|
+
String(writeLocation.line),
|
|
232
|
+
exposure.location.file,
|
|
233
|
+
String(exposure.location.line),
|
|
234
|
+
exposure.asset,
|
|
235
|
+
exposure.threat,
|
|
236
|
+
].join(':');
|
|
195
237
|
}
|
|
196
238
|
/**
|
|
197
239
|
* Format an exposure for display in CLI/TUI review UI.
|
package/dist/review/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/review/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/review/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/tui/commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAYH,OAAO,KAAK,EAAE,WAAW,EAAmB,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AA0B3F,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,EAAE,EAAE,OAAO,eAAe,EAAE,SAAS,CAAC;IACtC,8DAA8D;IAC9D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,qEAAqE;IACrE,aAAa,EAAE,mBAAmB,EAAE,CAAC;CACtC;AAED,8CAA8C;AAC9C,wBAAsB,YAAY,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAGjE;AAoBD,wBAAgB,OAAO,IAAI,IAAI,
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/tui/commands.ts"],"names":[],"mappings":"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"}
|
package/dist/tui/commands.js
CHANGED
|
@@ -32,7 +32,7 @@ import { diffModels, formatDiff, parseAtRef } from '../diff/index.js';
|
|
|
32
32
|
import { generateSarif } from '../analyzer/index.js';
|
|
33
33
|
import { C, severityBadge, severityText, severityTextPad, severityOrder, computeGrade, gradeColored, readCodeContext, trunc, bar, fileLink, fileLinkTrunc, cleanCliArtifacts } from './format.js';
|
|
34
34
|
import { resolveLLMConfig, saveTuiConfig, loadTuiConfig } from './config.js';
|
|
35
|
-
import { AGENTS, parseAgentFlag, launchAgent, launchAgentInline, copyToClipboard, buildAnnotatePrompt } from '../agents/index.js';
|
|
35
|
+
import { AGENTS, parseAgentFlag, parseAnnotationModeFlag, launchAgent, launchAgentInline, copyToClipboard, buildAnnotatePrompt } from '../agents/index.js';
|
|
36
36
|
import { describeConfigSource } from '../agents/config.js';
|
|
37
37
|
import { getReviewableExposures, applyReviewAction, summarizeReview } from '../review/index.js';
|
|
38
38
|
import { loadWorkspaceConfig, linkProject, addToWorkspace, removeFromWorkspace, mergeReports, formatMergeSummary, diffMergedReports } from '../workspace/index.js';
|
|
@@ -87,6 +87,7 @@ export function cmdHelp() {
|
|
|
87
87
|
['/assets', 'Asset tree with threat/control counts'],
|
|
88
88
|
['/files', 'Annotated file tree with exposure counts'],
|
|
89
89
|
['/view <file>', 'Show all annotations in a file with code context'],
|
|
90
|
+
['/unannotated', 'List source files with no annotations'],
|
|
90
91
|
['', ''],
|
|
91
92
|
['/threat-report <fw>', 'AI threat report (stride|dread|pasta|attacker|rapid|general|custom)'],
|
|
92
93
|
['/threat-reports', 'List saved AI threat reports'],
|
|
@@ -133,115 +134,135 @@ export function cmdGal() {
|
|
|
133
134
|
console.log(H(' GAL — GuardLink Annotation Language'));
|
|
134
135
|
console.log(H(' ══════════════════════════════════════════════════════════'));
|
|
135
136
|
console.log('');
|
|
136
|
-
console.log(D(' Annotations live in source
|
|
137
|
-
console.log(D(' them
|
|
137
|
+
console.log(D(' Annotations live in source comments or standalone .gal files.'));
|
|
138
|
+
console.log(D(' GuardLink parses them into a live threat model for your codebase.'));
|
|
138
139
|
console.log('');
|
|
139
|
-
console.log(D(' Syntax: @verb subject [preposition object] [
|
|
140
|
+
console.log(D(' Syntax: @verb subject [preposition object] [-- "description"]'));
|
|
141
|
+
console.log(D(' Inline examples below use comment prefixes; raw .gal files use the same lines without // or #.'));
|
|
142
|
+
console.log(D(' In .gal files, use @source file:<path> line:<n> [symbol:<name>] to anchor following annotations.'));
|
|
140
143
|
console.log('');
|
|
141
144
|
// ── DEFINITIONS ──────────────────────────────────────────────────
|
|
142
145
|
console.log(H(' ── Definitions ─────────────────────────────────────────────'));
|
|
143
146
|
console.log('');
|
|
144
|
-
console.log(` ${V('@asset')} ${K('<path>')} ${D('[
|
|
147
|
+
console.log(` ${V('@asset')} ${K('<path>')} ${D('[-- "description"]')}`);
|
|
145
148
|
console.log(D(' Declare a named asset (component, service, data store).'));
|
|
146
149
|
console.log(D(' Path uses dot notation for hierarchy.'));
|
|
147
|
-
console.log(EX(' // @asset api.auth.token_store
|
|
150
|
+
console.log(EX(' // @asset api.auth.token_store -- "Stores JWT refresh tokens"'));
|
|
148
151
|
console.log(EX(' // @asset db.users'));
|
|
149
152
|
console.log('');
|
|
150
|
-
console.log(` ${V('@threat')} ${K('<name>')} ${D('[
|
|
151
|
-
console.log(D(' Declare a named threat. Severity
|
|
152
|
-
console.log(EX(' // @threat SQL Injection
|
|
153
|
-
console.log(EX(' // @threat Token Theft
|
|
153
|
+
console.log(` ${V('@threat')} ${K('<name>')} ${D('(#id)')} ${D('[critical|high|medium|low]')} ${D('[ext-refs]')} ${D('[-- "description"]')}`);
|
|
154
|
+
console.log(D(' Declare a named threat. Severity in brackets: [P0]=[critical] [P1]=[high] [P2]=[medium] [P3]=[low].'));
|
|
155
|
+
console.log(EX(' // @threat SQL Injection (#sql-inj) [high] cwe:CWE-89 -- "Unsanitized input reaches DB"'));
|
|
156
|
+
console.log(EX(' // @threat Token Theft [P0]'));
|
|
154
157
|
console.log('');
|
|
155
|
-
console.log(` ${V('@control')} ${K('<name>')} ${D('[
|
|
158
|
+
console.log(` ${V('@control')} ${K('<name>')} ${D('(#id)')} ${D('[-- "description"]')}`);
|
|
156
159
|
console.log(D(' Declare a security control (mitigation mechanism).'));
|
|
157
|
-
console.log(EX(' // @control Input Validation
|
|
160
|
+
console.log(EX(' // @control Input Validation (#input-val) -- "Sanitize all user-supplied strings"'));
|
|
158
161
|
console.log(EX(' // @control Rate Limiting'));
|
|
159
162
|
console.log('');
|
|
160
163
|
// ── RELATIONSHIPS ─────────────────────────────────────────────────
|
|
161
164
|
console.log(H(' ── Relationships ───────────────────────────────────────────'));
|
|
162
165
|
console.log('');
|
|
163
|
-
console.log(` ${V('@exposes')} ${K('<asset>')} ${D('to')} ${K('<threat>')} ${D('[severity
|
|
166
|
+
console.log(` ${V('@exposes')} ${K('<asset>')} ${D('to')} ${K('<threat>')} ${D('[severity]')} ${D('[ext-refs]')} ${D('[-- "description"]')}`);
|
|
164
167
|
console.log(D(' Mark an asset as exposed to a threat at this code location.'));
|
|
165
168
|
console.log(D(' This is the primary annotation — every exposure creates a finding.'));
|
|
166
|
-
console.log(EX(' // @exposes api.auth to SQL Injection
|
|
167
|
-
console.log(EX(' // @exposes db.users to Token Theft
|
|
169
|
+
console.log(EX(' // @exposes api.auth to SQL Injection [high] cwe:CWE-89'));
|
|
170
|
+
console.log(EX(' // @exposes db.users to Token Theft [critical] -- "No token rotation"'));
|
|
168
171
|
console.log('');
|
|
169
|
-
console.log(` ${V('@mitigates')} ${K('<asset>')} ${D('against')} ${K('<threat>')} ${D('[
|
|
172
|
+
console.log(` ${V('@mitigates')} ${K('<asset>')} ${D('against')} ${K('<threat>')} ${D('[using')} ${K('<control>')}${D(']')} ${D('[-- "description"]')}`);
|
|
170
173
|
console.log(D(' Mark that a control mitigates a threat on an asset.'));
|
|
171
174
|
console.log(D(' Closes the exposure — removes it from open findings.'));
|
|
172
|
-
console.log(
|
|
173
|
-
console.log(EX(' // @mitigates
|
|
175
|
+
console.log(D(' "using" is the primary keyword; "with" also accepted.'));
|
|
176
|
+
console.log(EX(' // @mitigates api.auth against SQL Injection using Input Validation'));
|
|
177
|
+
console.log(EX(' // @mitigates db.users against Token Theft -- "Rotation implemented in v2"'));
|
|
174
178
|
console.log('');
|
|
175
|
-
console.log(` ${V('@accepts')} ${K('<threat>')} ${D('on')} ${K('<asset>')} ${D('[
|
|
179
|
+
console.log(` ${V('@accepts')} ${K('<threat>')} ${D('on')} ${K('<asset>')} ${D('[-- "reason"]')}`);
|
|
176
180
|
console.log(D(' Explicitly accept a risk. Removes it from open findings.'));
|
|
177
181
|
console.log(D(' Use when the risk is known and intentionally not mitigated.'));
|
|
178
|
-
console.log(EX(' // @accepts Timing Attack on api.auth
|
|
182
|
+
console.log(EX(' // @accepts Timing Attack on api.auth -- "Acceptable for current threat model"'));
|
|
179
183
|
console.log('');
|
|
180
|
-
console.log(` ${V('@transfers')} ${K('<threat>')} ${D('from')} ${K('<source>')} ${D('to')} ${K('<target>')} ${D('[
|
|
184
|
+
console.log(` ${V('@transfers')} ${K('<threat>')} ${D('from')} ${K('<source>')} ${D('to')} ${K('<target>')} ${D('[-- "description"]')}`);
|
|
181
185
|
console.log(D(' Transfer responsibility for a threat to another asset/team.'));
|
|
182
|
-
console.log(EX(' // @transfers DDoS from api.gateway to cdn.cloudflare
|
|
186
|
+
console.log(EX(' // @transfers DDoS from api.gateway to cdn.cloudflare -- "Handled by CDN layer"'));
|
|
183
187
|
console.log('');
|
|
184
188
|
// ── DATA FLOWS ────────────────────────────────────────────────────
|
|
185
189
|
console.log(H(' ── Data Flows & Boundaries ─────────────────────────────────'));
|
|
186
190
|
console.log('');
|
|
187
|
-
console.log(` ${V('@flows')} ${K('<source>')} ${D('
|
|
191
|
+
console.log(` ${V('@flows')} ${K('<source>')} ${D('->')} ${K('<target>')} ${D('[via')} ${K('<mechanism>')}${D(']')} ${D('[-- "description"]')}`);
|
|
188
192
|
console.log(D(' Document data movement between components.'));
|
|
189
193
|
console.log(D(' Appears in the Data Flow Diagram.'));
|
|
190
|
-
console.log(EX(' // @flows api.auth
|
|
191
|
-
console.log(EX(' // @flows mobile.app
|
|
194
|
+
console.log(EX(' // @flows api.auth -> db.users via TLS 1.3'));
|
|
195
|
+
console.log(EX(' // @flows mobile.app -> api.gateway via HTTPS -- "User credentials"'));
|
|
192
196
|
console.log('');
|
|
193
|
-
console.log(` ${V('@boundary')} ${K('<asset_a>')} ${D('and')} ${K('<asset_b>')} ${D('[
|
|
197
|
+
console.log(` ${V('@boundary')} ${K('<asset_a>')} ${D('and')} ${K('<asset_b>')} ${D('(#id)')} ${D('[-- "description"]')}`);
|
|
194
198
|
console.log(D(' Declare a trust boundary between two assets.'));
|
|
195
199
|
console.log(D(' Groups assets in the Data Flow Diagram.'));
|
|
196
|
-
console.log(
|
|
197
|
-
console.log(EX(' // @boundary api.gateway
|
|
200
|
+
console.log(D(' Alternate: @boundary between A and B or @boundary A | B'));
|
|
201
|
+
console.log(EX(' // @boundary internet and api.gateway (#edge) -- "Public-facing edge"'));
|
|
202
|
+
console.log(EX(' // @boundary api.gateway | db.users -- "Internal network boundary"'));
|
|
198
203
|
console.log('');
|
|
199
204
|
// ── LIFECYCLE ─────────────────────────────────────────────────────
|
|
200
205
|
console.log(H(' ── Lifecycle & Governance ──────────────────────────────────'));
|
|
201
206
|
console.log('');
|
|
202
|
-
console.log(` ${V('@handles')} ${K('<classification>')} ${D('on')} ${K('<asset>')} ${D('[
|
|
207
|
+
console.log(` ${V('@handles')} ${K('<classification>')} ${D('on')} ${K('<asset>')} ${D('[-- "description"]')}`);
|
|
203
208
|
console.log(D(' Declare data classification handled by an asset.'));
|
|
204
209
|
console.log(D(' Classifications: pii phi financial secrets internal public'));
|
|
205
|
-
console.log(EX(' // @handles pii on db.users
|
|
210
|
+
console.log(EX(' // @handles pii on db.users -- "Stores name, email, phone"'));
|
|
206
211
|
console.log(EX(' // @handles secrets on api.auth.token_store'));
|
|
207
212
|
console.log('');
|
|
208
|
-
console.log(` ${V('@owns')} ${K('<owner>')} ${K('<asset>')} ${D('[
|
|
213
|
+
console.log(` ${V('@owns')} ${K('<owner>')} ${D('for')} ${K('<asset>')} ${D('[-- "description"]')}`);
|
|
209
214
|
console.log(D(' Assign ownership of an asset to a team or person.'));
|
|
210
|
-
console.log(EX(' // @owns platform-team api.auth'));
|
|
215
|
+
console.log(EX(' // @owns platform-team for api.auth'));
|
|
211
216
|
console.log('');
|
|
212
|
-
console.log(` ${V('@validates')} ${K('<control>')} ${D('
|
|
217
|
+
console.log(` ${V('@validates')} ${K('<control>')} ${D('for')} ${K('<asset>')} ${D('[-- "description"]')}`);
|
|
213
218
|
console.log(D(' Assert that a control has been validated/tested on an asset.'));
|
|
214
|
-
console.log(EX(' // @validates Input Validation
|
|
219
|
+
console.log(EX(' // @validates Input Validation for api.auth -- "Pen-tested 2024-Q3"'));
|
|
215
220
|
console.log('');
|
|
216
|
-
console.log(` ${V('@audit')} ${K('<asset>')} ${D('[
|
|
221
|
+
console.log(` ${V('@audit')} ${K('<asset>')} ${D('[-- "description"]')}`);
|
|
217
222
|
console.log(D(' Mark that this code path is an audit trail point.'));
|
|
218
|
-
console.log(EX(' // @audit db.users
|
|
223
|
+
console.log(EX(' // @audit db.users -- "All writes logged to audit_log table"'));
|
|
219
224
|
console.log('');
|
|
220
|
-
console.log(` ${V('@assumes')} ${K('<asset>')} ${D('[
|
|
225
|
+
console.log(` ${V('@assumes')} ${K('<asset>')} ${D('[-- "description"]')}`);
|
|
221
226
|
console.log(D(' Document a security assumption about an asset.'));
|
|
222
|
-
console.log(EX(' // @assumes api.gateway
|
|
227
|
+
console.log(EX(' // @assumes api.gateway -- "Upstream WAF filters malformed requests"'));
|
|
223
228
|
console.log('');
|
|
224
|
-
console.log(` ${V('@comment')} ${D('[
|
|
229
|
+
console.log(` ${V('@comment')} ${D('[-- "description"]')}`);
|
|
225
230
|
console.log(D(' Free-form developer security note (no structural effect).'));
|
|
226
|
-
console.log(EX(' // @comment
|
|
231
|
+
console.log(EX(' // @comment -- "TODO — add rate limiting before v2 launch"'));
|
|
227
232
|
console.log('');
|
|
228
233
|
// ── SHIELD BLOCKS ─────────────────────────────────────────────────
|
|
229
234
|
console.log(H(' ── Shield Blocks ───────────────────────────────────────────'));
|
|
230
235
|
console.log('');
|
|
236
|
+
console.log(` ${V('@shield')} ${D('[-- "reason"]')}`);
|
|
237
|
+
console.log(D(' Single-line marker for a security-sensitive code point.'));
|
|
238
|
+
console.log(EX(' // @shield -- "Crypto key derivation — do not refactor without review"'));
|
|
239
|
+
console.log('');
|
|
231
240
|
console.log(` ${V('@shield:begin')} ${D('/')} ${V('@shield:end')}`);
|
|
232
241
|
console.log(D(' Wrap a code block to mark it as security-sensitive.'));
|
|
233
242
|
console.log(D(' GuardLink will flag unannotated symbols inside the block.'));
|
|
234
|
-
console.log(EX(' // @shield:begin'));
|
|
243
|
+
console.log(EX(' // @shield:begin -- "Auth verification block"'));
|
|
235
244
|
console.log(EX(' function verifyToken(token: string) { ... }'));
|
|
236
245
|
console.log(EX(' // @shield:end'));
|
|
237
246
|
console.log('');
|
|
247
|
+
// ── EXTERNAL REFERENCES ─────────────────────────────────────────
|
|
248
|
+
console.log(H(' ── External References ─────────────────────────────────────'));
|
|
249
|
+
console.log('');
|
|
250
|
+
console.log(D(' Append space-separated refs after severity on @threat and @exposes:'));
|
|
251
|
+
console.log(EX(' cwe:CWE-89 owasp:A03:2021 capec:CAPEC-66 attack:T1190'));
|
|
252
|
+
console.log('');
|
|
253
|
+
console.log(D(' Example:'));
|
|
254
|
+
console.log(EX(' // @exposes api.auth to SQL Injection [high] cwe:CWE-89 owasp:A03:2021'));
|
|
255
|
+
console.log('');
|
|
238
256
|
// ── TIPS ──────────────────────────────────────────────────────────
|
|
239
257
|
console.log(H(' ── Tips ────────────────────────────────────────────────────'));
|
|
240
258
|
console.log('');
|
|
259
|
+
console.log(D(' • Descriptions use -- "quoted text" format (not : colon)'));
|
|
260
|
+
console.log(D(' • Severity uses brackets: [critical] [high] [medium] [low] or [P0]-[P3]'));
|
|
241
261
|
console.log(D(' • Annotations work in any comment style: // /* # -- <!-- -->'));
|
|
242
262
|
console.log(D(' • Place annotations on the line ABOVE the code they describe'));
|
|
243
263
|
console.log(D(' • Asset names are case-insensitive and normalized (spaces→underscores)'));
|
|
244
264
|
console.log(D(' • Threat/control names can reference IDs with #id syntax'));
|
|
265
|
+
console.log(D(' • @flows uses -> arrow syntax (not "to")'));
|
|
245
266
|
console.log(D(' • Run /parse after adding annotations to update the threat model'));
|
|
246
267
|
console.log(D(' • Run /validate to check for syntax errors and dangling references'));
|
|
247
268
|
console.log(D(' • Run /annotate to have an AI agent add annotations automatically'));
|
|
@@ -1273,10 +1294,15 @@ export function cmdThreatReports(ctx) {
|
|
|
1273
1294
|
}
|
|
1274
1295
|
// ─── /annotate ───────────────────────────────────────────────────────
|
|
1275
1296
|
export async function cmdAnnotate(args, ctx) {
|
|
1276
|
-
const {
|
|
1297
|
+
const { mode: annotationMode, cleanArgs: argsWithoutMode, error: modeError } = parseAnnotationModeFlag(args);
|
|
1298
|
+
if (modeError) {
|
|
1299
|
+
console.log(C.warn(` ${modeError}`));
|
|
1300
|
+
return;
|
|
1301
|
+
}
|
|
1302
|
+
const { agent: flagAgent, cleanArgs } = parseAgentFlag(argsWithoutMode);
|
|
1277
1303
|
if (!cleanArgs.trim()) {
|
|
1278
|
-
console.log(C.warn(' Usage: /annotate <prompt> [--claude-code|--codex|--gemini|--cursor|--windsurf|--clipboard]'));
|
|
1279
|
-
console.log(C.dim(' Example: /annotate "annotate auth endpoints for OWASP Top 10" --claude-code'));
|
|
1304
|
+
console.log(C.warn(' Usage: /annotate <prompt> [--mode inline|external] [--claude-code|--codex|--gemini|--cursor|--windsurf|--clipboard]'));
|
|
1305
|
+
console.log(C.dim(' Example: /annotate "annotate auth endpoints for OWASP Top 10" --mode external --claude-code'));
|
|
1280
1306
|
return;
|
|
1281
1307
|
}
|
|
1282
1308
|
console.log('');
|
|
@@ -1285,7 +1311,7 @@ export async function cmdAnnotate(args, ctx) {
|
|
|
1285
1311
|
if (!agent)
|
|
1286
1312
|
return;
|
|
1287
1313
|
// Build context prompt using shared builder
|
|
1288
|
-
const prompt = buildAnnotatePrompt(cleanArgs.trim(), ctx.root, ctx.model);
|
|
1314
|
+
const prompt = buildAnnotatePrompt(cleanArgs.trim(), ctx.root, ctx.model, annotationMode);
|
|
1289
1315
|
// For terminal agents: foreground spawn (agent takes over terminal)
|
|
1290
1316
|
if (agent.cmd) {
|
|
1291
1317
|
const copied = copyToClipboard(prompt);
|
|
@@ -1540,7 +1566,7 @@ export async function cmdReview(args, ctx) {
|
|
|
1540
1566
|
console.log(` ${C.success('✓')} Marked for remediation — ${result.linesInserted} line(s) written\n`);
|
|
1541
1567
|
}
|
|
1542
1568
|
else {
|
|
1543
|
-
results.push({ exposure: reviewable, action: { decision: 'skip', justification: '' }, linesInserted: 0 });
|
|
1569
|
+
results.push({ exposure: reviewable, action: { decision: 'skip', justification: '' }, linesInserted: 0, targetFile: reviewable.exposure.location.file });
|
|
1544
1570
|
console.log(` ${C.dim('— Skipped')}\n`);
|
|
1545
1571
|
}
|
|
1546
1572
|
}
|