guardlink 1.0.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.
Files changed (172) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/LICENSE +21 -0
  3. package/README.md +344 -0
  4. package/dist/agents/config.d.ts +46 -0
  5. package/dist/agents/config.d.ts.map +1 -0
  6. package/dist/agents/config.js +189 -0
  7. package/dist/agents/config.js.map +1 -0
  8. package/dist/agents/index.d.ts +24 -0
  9. package/dist/agents/index.d.ts.map +1 -0
  10. package/dist/agents/index.js +42 -0
  11. package/dist/agents/index.js.map +1 -0
  12. package/dist/agents/launcher.d.ts +54 -0
  13. package/dist/agents/launcher.d.ts.map +1 -0
  14. package/dist/agents/launcher.js +152 -0
  15. package/dist/agents/launcher.js.map +1 -0
  16. package/dist/agents/prompts.d.ts +14 -0
  17. package/dist/agents/prompts.d.ts.map +1 -0
  18. package/dist/agents/prompts.js +120 -0
  19. package/dist/agents/prompts.js.map +1 -0
  20. package/dist/analyze/index.d.ts +80 -0
  21. package/dist/analyze/index.d.ts.map +1 -0
  22. package/dist/analyze/index.js +306 -0
  23. package/dist/analyze/index.js.map +1 -0
  24. package/dist/analyze/llm.d.ts +52 -0
  25. package/dist/analyze/llm.d.ts.map +1 -0
  26. package/dist/analyze/llm.js +295 -0
  27. package/dist/analyze/llm.js.map +1 -0
  28. package/dist/analyze/prompts.d.ts +14 -0
  29. package/dist/analyze/prompts.d.ts.map +1 -0
  30. package/dist/analyze/prompts.js +205 -0
  31. package/dist/analyze/prompts.js.map +1 -0
  32. package/dist/analyzer/index.d.ts +5 -0
  33. package/dist/analyzer/index.d.ts.map +1 -0
  34. package/dist/analyzer/index.js +5 -0
  35. package/dist/analyzer/index.js.map +1 -0
  36. package/dist/analyzer/sarif.d.ts +84 -0
  37. package/dist/analyzer/sarif.d.ts.map +1 -0
  38. package/dist/analyzer/sarif.js +149 -0
  39. package/dist/analyzer/sarif.js.map +1 -0
  40. package/dist/cli/index.d.ts +25 -0
  41. package/dist/cli/index.d.ts.map +1 -0
  42. package/dist/cli/index.js +821 -0
  43. package/dist/cli/index.js.map +1 -0
  44. package/dist/dashboard/data.d.ts +52 -0
  45. package/dist/dashboard/data.d.ts.map +1 -0
  46. package/dist/dashboard/data.js +93 -0
  47. package/dist/dashboard/data.js.map +1 -0
  48. package/dist/dashboard/diagrams.d.ts +25 -0
  49. package/dist/dashboard/diagrams.d.ts.map +1 -0
  50. package/dist/dashboard/diagrams.js +243 -0
  51. package/dist/dashboard/diagrams.js.map +1 -0
  52. package/dist/dashboard/generate.d.ts +17 -0
  53. package/dist/dashboard/generate.d.ts.map +1 -0
  54. package/dist/dashboard/generate.js +1258 -0
  55. package/dist/dashboard/generate.js.map +1 -0
  56. package/dist/dashboard/index.d.ts +7 -0
  57. package/dist/dashboard/index.d.ts.map +1 -0
  58. package/dist/dashboard/index.js +7 -0
  59. package/dist/dashboard/index.js.map +1 -0
  60. package/dist/diff/engine.d.ts +51 -0
  61. package/dist/diff/engine.d.ts.map +1 -0
  62. package/dist/diff/engine.js +153 -0
  63. package/dist/diff/engine.js.map +1 -0
  64. package/dist/diff/format.d.ts +10 -0
  65. package/dist/diff/format.d.ts.map +1 -0
  66. package/dist/diff/format.js +111 -0
  67. package/dist/diff/format.js.map +1 -0
  68. package/dist/diff/git.d.ts +24 -0
  69. package/dist/diff/git.d.ts.map +1 -0
  70. package/dist/diff/git.js +85 -0
  71. package/dist/diff/git.js.map +1 -0
  72. package/dist/diff/index.d.ts +7 -0
  73. package/dist/diff/index.d.ts.map +1 -0
  74. package/dist/diff/index.js +7 -0
  75. package/dist/diff/index.js.map +1 -0
  76. package/dist/index.d.ts +20 -0
  77. package/dist/index.d.ts.map +1 -0
  78. package/dist/index.js +17 -0
  79. package/dist/index.js.map +1 -0
  80. package/dist/init/detect.d.ts +42 -0
  81. package/dist/init/detect.d.ts.map +1 -0
  82. package/dist/init/detect.js +185 -0
  83. package/dist/init/detect.js.map +1 -0
  84. package/dist/init/index.d.ts +39 -0
  85. package/dist/init/index.d.ts.map +1 -0
  86. package/dist/init/index.js +228 -0
  87. package/dist/init/index.js.map +1 -0
  88. package/dist/init/picker.d.ts +32 -0
  89. package/dist/init/picker.d.ts.map +1 -0
  90. package/dist/init/picker.js +105 -0
  91. package/dist/init/picker.js.map +1 -0
  92. package/dist/init/templates.d.ts +25 -0
  93. package/dist/init/templates.d.ts.map +1 -0
  94. package/dist/init/templates.js +263 -0
  95. package/dist/init/templates.js.map +1 -0
  96. package/dist/mcp/index.d.ts +12 -0
  97. package/dist/mcp/index.d.ts.map +1 -0
  98. package/dist/mcp/index.js +18 -0
  99. package/dist/mcp/index.js.map +1 -0
  100. package/dist/mcp/lookup.d.ts +27 -0
  101. package/dist/mcp/lookup.d.ts.map +1 -0
  102. package/dist/mcp/lookup.js +282 -0
  103. package/dist/mcp/lookup.js.map +1 -0
  104. package/dist/mcp/server.d.ts +41 -0
  105. package/dist/mcp/server.d.ts.map +1 -0
  106. package/dist/mcp/server.js +388 -0
  107. package/dist/mcp/server.js.map +1 -0
  108. package/dist/mcp/suggest.d.ts +35 -0
  109. package/dist/mcp/suggest.d.ts.map +1 -0
  110. package/dist/mcp/suggest.js +268 -0
  111. package/dist/mcp/suggest.js.map +1 -0
  112. package/dist/parser/comment-strip.d.ts +15 -0
  113. package/dist/parser/comment-strip.d.ts.map +1 -0
  114. package/dist/parser/comment-strip.js +76 -0
  115. package/dist/parser/comment-strip.js.map +1 -0
  116. package/dist/parser/index.d.ts +10 -0
  117. package/dist/parser/index.d.ts.map +1 -0
  118. package/dist/parser/index.js +9 -0
  119. package/dist/parser/index.js.map +1 -0
  120. package/dist/parser/normalize.d.ts +22 -0
  121. package/dist/parser/normalize.d.ts.map +1 -0
  122. package/dist/parser/normalize.js +42 -0
  123. package/dist/parser/normalize.js.map +1 -0
  124. package/dist/parser/parse-file.d.ts +18 -0
  125. package/dist/parser/parse-file.d.ts.map +1 -0
  126. package/dist/parser/parse-file.js +68 -0
  127. package/dist/parser/parse-file.js.map +1 -0
  128. package/dist/parser/parse-line.d.ts +21 -0
  129. package/dist/parser/parse-line.d.ts.map +1 -0
  130. package/dist/parser/parse-line.js +230 -0
  131. package/dist/parser/parse-line.js.map +1 -0
  132. package/dist/parser/parse-project.d.ts +31 -0
  133. package/dist/parser/parse-project.d.ts.map +1 -0
  134. package/dist/parser/parse-project.js +281 -0
  135. package/dist/parser/parse-project.js.map +1 -0
  136. package/dist/report/index.d.ts +6 -0
  137. package/dist/report/index.d.ts.map +1 -0
  138. package/dist/report/index.js +6 -0
  139. package/dist/report/index.js.map +1 -0
  140. package/dist/report/mermaid.d.ts +15 -0
  141. package/dist/report/mermaid.d.ts.map +1 -0
  142. package/dist/report/mermaid.js +260 -0
  143. package/dist/report/mermaid.js.map +1 -0
  144. package/dist/report/report.d.ts +16 -0
  145. package/dist/report/report.d.ts.map +1 -0
  146. package/dist/report/report.js +211 -0
  147. package/dist/report/report.js.map +1 -0
  148. package/dist/tui/commands.d.ts +42 -0
  149. package/dist/tui/commands.d.ts.map +1 -0
  150. package/dist/tui/commands.js +1216 -0
  151. package/dist/tui/commands.js.map +1 -0
  152. package/dist/tui/config.d.ts +27 -0
  153. package/dist/tui/config.d.ts.map +1 -0
  154. package/dist/tui/config.js +27 -0
  155. package/dist/tui/config.js.map +1 -0
  156. package/dist/tui/format.d.ts +63 -0
  157. package/dist/tui/format.d.ts.map +1 -0
  158. package/dist/tui/format.js +253 -0
  159. package/dist/tui/format.js.map +1 -0
  160. package/dist/tui/index.d.ts +18 -0
  161. package/dist/tui/index.d.ts.map +1 -0
  162. package/dist/tui/index.js +470 -0
  163. package/dist/tui/index.js.map +1 -0
  164. package/dist/tui/input.d.ts +63 -0
  165. package/dist/tui/input.d.ts.map +1 -0
  166. package/dist/tui/input.js +454 -0
  167. package/dist/tui/input.js.map +1 -0
  168. package/dist/types/index.d.ts +254 -0
  169. package/dist/types/index.d.ts.map +1 -0
  170. package/dist/types/index.js +6 -0
  171. package/dist/types/index.js.map +1 -0
  172. package/package.json +97 -0
@@ -0,0 +1,295 @@
1
+ /**
2
+ * GuardLink Threat Reports — Lightweight LLM client using raw fetch.
3
+ *
4
+ * Supports:
5
+ * - Anthropic Messages API (claude-sonnet-4-5-20250929, etc.)
6
+ * - OpenAI-compatible Chat Completions (GPT-4o, DeepSeek, OpenRouter)
7
+ *
8
+ * Zero dependencies — uses Node 20+ built-in fetch.
9
+ *
10
+ * @exposes #llm-client to #api-key-exposure [high] cwe:CWE-798 -- "Reads API keys from environment variables"
11
+ * @exposes #llm-client to #ssrf [medium] cwe:CWE-918 -- "Makes HTTP requests to configurable provider URLs"
12
+ * @exposes #llm-client to #prompt-injection [medium] cwe:CWE-77 -- "Sends threat model content as LLM prompt"
13
+ * @accepts #prompt-injection on #llm-client -- "Core feature: threat model data is sent to LLM for analysis"
14
+ * @mitigates #llm-client against #ssrf using #config-validation -- "BASE_URLS are hardcoded to known providers"
15
+ * @mitigates #llm-client against #api-key-exposure using #key-redaction -- "Keys read from env, not logged"
16
+ * @handles secrets on #llm-client -- "API keys held in memory during request lifecycle"
17
+ * @boundary between #llm-client and External_LLM_APIs (#llm-boundary) -- "HTTP requests cross network trust boundary to external AI providers"
18
+ * @flows #llm-client -> External_LLM_APIs via fetch -- "HTTP POST with auth headers and prompt payload"
19
+ * @flows External_LLM_APIs -> #llm-client via response -- "Streaming or complete response from LLM provider"
20
+ */
21
+ const DEFAULT_MODELS = {
22
+ anthropic: 'claude-sonnet-4-5-20250929',
23
+ openai: 'gpt-4o',
24
+ openrouter: 'anthropic/claude-sonnet-4-5-20250929',
25
+ deepseek: 'deepseek-chat',
26
+ };
27
+ const BASE_URLS = {
28
+ anthropic: 'https://api.anthropic.com',
29
+ openai: 'https://api.openai.com',
30
+ openrouter: 'https://openrouter.ai/api',
31
+ deepseek: 'https://api.deepseek.com',
32
+ };
33
+ /**
34
+ * Auto-detect provider from environment variables.
35
+ * Returns null if no API key found.
36
+ */
37
+ export function autoDetectConfig() {
38
+ // Priority: Anthropic > OpenAI > OpenRouter > DeepSeek
39
+ if (process.env.ANTHROPIC_API_KEY) {
40
+ return {
41
+ provider: 'anthropic',
42
+ model: DEFAULT_MODELS.anthropic,
43
+ apiKey: process.env.ANTHROPIC_API_KEY,
44
+ };
45
+ }
46
+ if (process.env.OPENAI_API_KEY) {
47
+ return {
48
+ provider: 'openai',
49
+ model: DEFAULT_MODELS.openai,
50
+ apiKey: process.env.OPENAI_API_KEY,
51
+ };
52
+ }
53
+ if (process.env.OPENROUTER_API_KEY) {
54
+ return {
55
+ provider: 'openrouter',
56
+ model: DEFAULT_MODELS.openrouter,
57
+ apiKey: process.env.OPENROUTER_API_KEY,
58
+ };
59
+ }
60
+ if (process.env.DEEPSEEK_API_KEY) {
61
+ return {
62
+ provider: 'deepseek',
63
+ model: DEFAULT_MODELS.deepseek,
64
+ apiKey: process.env.DEEPSEEK_API_KEY,
65
+ };
66
+ }
67
+ return null;
68
+ }
69
+ /**
70
+ * Build config from explicit flags + env vars.
71
+ */
72
+ export function buildConfig(opts) {
73
+ // If provider specified, use it
74
+ if (opts.provider) {
75
+ const provider = opts.provider;
76
+ const envKeyMap = {
77
+ anthropic: 'ANTHROPIC_API_KEY',
78
+ openai: 'OPENAI_API_KEY',
79
+ openrouter: 'OPENROUTER_API_KEY',
80
+ deepseek: 'DEEPSEEK_API_KEY',
81
+ };
82
+ const apiKey = opts.apiKey || process.env[envKeyMap[provider] || ''];
83
+ if (!apiKey)
84
+ return null;
85
+ return {
86
+ provider,
87
+ model: opts.model || DEFAULT_MODELS[provider] || 'gpt-4o',
88
+ apiKey,
89
+ };
90
+ }
91
+ // Auto-detect
92
+ const config = autoDetectConfig();
93
+ if (!config)
94
+ return null;
95
+ // Override model if specified
96
+ if (opts.model)
97
+ config.model = opts.model;
98
+ return config;
99
+ }
100
+ /**
101
+ * Send a message to the LLM and return the response.
102
+ */
103
+ export async function chatCompletion(config, systemPrompt, userMessage, onChunk) {
104
+ if (config.provider === 'anthropic') {
105
+ return callAnthropic(config, systemPrompt, userMessage, onChunk);
106
+ }
107
+ else {
108
+ return callOpenAICompatible(config, systemPrompt, userMessage, onChunk);
109
+ }
110
+ }
111
+ // ─── Anthropic Messages API ──────────────────────────────────────────
112
+ async function callAnthropic(config, systemPrompt, userMessage, onChunk) {
113
+ const baseUrl = config.baseUrl || BASE_URLS.anthropic;
114
+ const maxTokens = config.maxTokens || 8192;
115
+ if (onChunk) {
116
+ // Streaming
117
+ const res = await fetch(`${baseUrl}/v1/messages`, {
118
+ method: 'POST',
119
+ headers: {
120
+ 'Content-Type': 'application/json',
121
+ 'x-api-key': config.apiKey,
122
+ 'anthropic-version': '2023-06-01',
123
+ },
124
+ body: JSON.stringify({
125
+ model: config.model,
126
+ max_tokens: maxTokens,
127
+ system: systemPrompt,
128
+ stream: true,
129
+ messages: [{ role: 'user', content: userMessage }],
130
+ }),
131
+ });
132
+ if (!res.ok) {
133
+ const err = await res.text();
134
+ throw new Error(`Anthropic API error ${res.status}: ${err}`);
135
+ }
136
+ let content = '';
137
+ let inputTokens = 0;
138
+ let outputTokens = 0;
139
+ const reader = res.body?.getReader();
140
+ if (!reader)
141
+ throw new Error('No response body');
142
+ const decoder = new TextDecoder();
143
+ let buffer = '';
144
+ while (true) {
145
+ const { done, value } = await reader.read();
146
+ if (done)
147
+ break;
148
+ buffer += decoder.decode(value, { stream: true });
149
+ const lines = buffer.split('\n');
150
+ buffer = lines.pop() || '';
151
+ for (const line of lines) {
152
+ if (!line.startsWith('data: '))
153
+ continue;
154
+ const data = line.slice(6).trim();
155
+ if (data === '[DONE]')
156
+ continue;
157
+ try {
158
+ const event = JSON.parse(data);
159
+ if (event.type === 'content_block_delta' && event.delta?.text) {
160
+ content += event.delta.text;
161
+ onChunk(event.delta.text);
162
+ }
163
+ if (event.type === 'message_delta' && event.usage) {
164
+ outputTokens = event.usage.output_tokens || 0;
165
+ }
166
+ if (event.type === 'message_start' && event.message?.usage) {
167
+ inputTokens = event.message.usage.input_tokens || 0;
168
+ }
169
+ }
170
+ catch { /* skip non-JSON lines */ }
171
+ }
172
+ }
173
+ return { content, model: config.model, inputTokens, outputTokens };
174
+ }
175
+ else {
176
+ // Non-streaming
177
+ const res = await fetch(`${baseUrl}/v1/messages`, {
178
+ method: 'POST',
179
+ headers: {
180
+ 'Content-Type': 'application/json',
181
+ 'x-api-key': config.apiKey,
182
+ 'anthropic-version': '2023-06-01',
183
+ },
184
+ body: JSON.stringify({
185
+ model: config.model,
186
+ max_tokens: maxTokens,
187
+ system: systemPrompt,
188
+ messages: [{ role: 'user', content: userMessage }],
189
+ }),
190
+ });
191
+ if (!res.ok) {
192
+ const err = await res.text();
193
+ throw new Error(`Anthropic API error ${res.status}: ${err}`);
194
+ }
195
+ const data = await res.json();
196
+ return {
197
+ content: data.content?.[0]?.text || '',
198
+ model: data.model || config.model,
199
+ inputTokens: data.usage?.input_tokens,
200
+ outputTokens: data.usage?.output_tokens,
201
+ };
202
+ }
203
+ }
204
+ // ─── OpenAI-compatible Chat Completions ──────────────────────────────
205
+ async function callOpenAICompatible(config, systemPrompt, userMessage, onChunk) {
206
+ const baseUrl = config.baseUrl || BASE_URLS[config.provider] || BASE_URLS.openai;
207
+ const maxTokens = config.maxTokens || 8192;
208
+ const headers = {
209
+ 'Content-Type': 'application/json',
210
+ 'Authorization': `Bearer ${config.apiKey}`,
211
+ };
212
+ // OpenRouter requires extra headers
213
+ if (config.provider === 'openrouter') {
214
+ headers['HTTP-Referer'] = 'https://guardlink.bugb.io';
215
+ headers['X-Title'] = 'GuardLink CLI';
216
+ }
217
+ if (onChunk) {
218
+ // Streaming
219
+ const res = await fetch(`${baseUrl}/v1/chat/completions`, {
220
+ method: 'POST',
221
+ headers,
222
+ body: JSON.stringify({
223
+ model: config.model,
224
+ max_tokens: maxTokens,
225
+ stream: true,
226
+ messages: [
227
+ { role: 'system', content: systemPrompt },
228
+ { role: 'user', content: userMessage },
229
+ ],
230
+ }),
231
+ });
232
+ if (!res.ok) {
233
+ const err = await res.text();
234
+ throw new Error(`${config.provider} API error ${res.status}: ${err}`);
235
+ }
236
+ let content = '';
237
+ const reader = res.body?.getReader();
238
+ if (!reader)
239
+ throw new Error('No response body');
240
+ const decoder = new TextDecoder();
241
+ let buffer = '';
242
+ while (true) {
243
+ const { done, value } = await reader.read();
244
+ if (done)
245
+ break;
246
+ buffer += decoder.decode(value, { stream: true });
247
+ const lines = buffer.split('\n');
248
+ buffer = lines.pop() || '';
249
+ for (const line of lines) {
250
+ if (!line.startsWith('data: '))
251
+ continue;
252
+ const data = line.slice(6).trim();
253
+ if (data === '[DONE]')
254
+ continue;
255
+ try {
256
+ const event = JSON.parse(data);
257
+ const delta = event.choices?.[0]?.delta?.content;
258
+ if (delta) {
259
+ content += delta;
260
+ onChunk(delta);
261
+ }
262
+ }
263
+ catch { /* skip */ }
264
+ }
265
+ }
266
+ return { content, model: config.model };
267
+ }
268
+ else {
269
+ // Non-streaming
270
+ const res = await fetch(`${baseUrl}/v1/chat/completions`, {
271
+ method: 'POST',
272
+ headers,
273
+ body: JSON.stringify({
274
+ model: config.model,
275
+ max_tokens: maxTokens,
276
+ messages: [
277
+ { role: 'system', content: systemPrompt },
278
+ { role: 'user', content: userMessage },
279
+ ],
280
+ }),
281
+ });
282
+ if (!res.ok) {
283
+ const err = await res.text();
284
+ throw new Error(`${config.provider} API error ${res.status}: ${err}`);
285
+ }
286
+ const data = await res.json();
287
+ return {
288
+ content: data.choices?.[0]?.message?.content || '',
289
+ model: data.model || config.model,
290
+ inputTokens: data.usage?.prompt_tokens,
291
+ outputTokens: data.usage?.completion_tokens,
292
+ };
293
+ }
294
+ }
295
+ //# sourceMappingURL=llm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm.js","sourceRoot":"","sources":["../../src/analyze/llm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * GuardLink Threat Reports — Framework-specific analysis prompts.
3
+ *
4
+ * Each framework produces a structured security analysis from the
5
+ * serialized threat model. The LLM acts as a senior security architect.
6
+ */
7
+ export type AnalysisFramework = 'stride' | 'dread' | 'pasta' | 'attacker' | 'rapid' | 'general';
8
+ export declare const FRAMEWORK_LABELS: Record<AnalysisFramework, string>;
9
+ export declare const FRAMEWORK_PROMPTS: Record<AnalysisFramework, string>;
10
+ /**
11
+ * Build the user message containing the serialized threat model.
12
+ */
13
+ export declare function buildUserMessage(modelJson: string, framework: AnalysisFramework, customPrompt?: string): string;
14
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/analyze/prompts.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;AAEhG,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAO9D,CAAC;AAkBF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAsK/D,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAU/G"}
@@ -0,0 +1,205 @@
1
+ /**
2
+ * GuardLink Threat Reports — Framework-specific analysis prompts.
3
+ *
4
+ * Each framework produces a structured security analysis from the
5
+ * serialized threat model. The LLM acts as a senior security architect.
6
+ */
7
+ export const FRAMEWORK_LABELS = {
8
+ stride: 'STRIDE Threat Analysis',
9
+ dread: 'DREAD Risk Assessment',
10
+ pasta: 'PASTA Attack Simulation',
11
+ attacker: 'Attacker Persona Analysis',
12
+ rapid: 'Rapid Risk Assessment',
13
+ general: 'General Threat Analysis',
14
+ };
15
+ const SYSTEM_BASE = `You are an expert Security Architect and Threat Modeler with 15+ years of experience.
16
+ You are analyzing a codebase that uses GuardLink annotations — structured security metadata embedded in source code comments.
17
+
18
+ The threat model you receive contains:
19
+ - **Assets**: Components declared by developers
20
+ - **Threats**: Known threat vectors with severity and CWE references
21
+ - **Controls**: Security mechanisms in place
22
+ - **Mitigations**: Where controls defend assets against threats
23
+ - **Exposures**: Known vulnerabilities (asset exposed to threat)
24
+ - **Flows**: Data movement between components
25
+ - **Boundaries**: Trust boundaries between security zones
26
+ - **Comments**: Developer security notes
27
+
28
+ Your analysis must be actionable, specific to THIS codebase, and reference the actual assets/threats/controls by name.
29
+ Never give generic advice — always tie recommendations to concrete annotations in the model.`;
30
+ export const FRAMEWORK_PROMPTS = {
31
+ stride: `${SYSTEM_BASE}
32
+
33
+ Perform a **STRIDE** analysis of this threat model.
34
+
35
+ For each STRIDE category, evaluate the codebase:
36
+
37
+ ## S — Spoofing
38
+ Identify where authentication can be bypassed. Check: are all assets with @exposes to auth-related threats properly mitigated?
39
+
40
+ ## T — Tampering
41
+ Identify where data integrity is at risk. Check: @flows without integrity controls, @handles with sensitive data lacking validation.
42
+
43
+ ## R — Repudiation
44
+ Identify where actions cannot be traced. Check: are there @audit annotations? Are critical operations logged?
45
+
46
+ ## I — Information Disclosure
47
+ Identify where sensitive data leaks. Check: @exposes to info-disclosure/data-exposure threats, @handles pii/phi/secrets without encryption.
48
+
49
+ ## D — Denial of Service
50
+ Identify resource exhaustion risks. Check: @exposes to dos threats, rate limiting controls, boundary protections.
51
+
52
+ ## E — Elevation of Privilege
53
+ Identify privilege escalation paths. Check: @exposes to bac/idor threats, @boundary gaps, missing authorization controls.
54
+
55
+ For each category:
56
+ 1. List specific findings referencing actual assets and threats from the model
57
+ 2. Rate severity (Critical/High/Medium/Low)
58
+ 3. Recommend specific mitigations referencing existing controls or suggesting new ones
59
+ 4. Identify gaps — what SHOULD be annotated but isn't?
60
+
61
+ End with an Executive Summary and Priority Action Items.`,
62
+ dread: `${SYSTEM_BASE}
63
+
64
+ Perform a **DREAD** risk scoring analysis of this threat model.
65
+
66
+ For each unmitigated exposure and significant threat, calculate a DREAD score:
67
+
68
+ - **D — Damage Potential** (0-10): How bad if exploited?
69
+ - **R — Reproducibility** (0-10): How easy to reproduce?
70
+ - **E — Exploitability** (0-10): How easy to launch the attack?
71
+ - **A — Affected Users** (0-10): How many users impacted?
72
+ - **D — Discoverability** (0-10): How easy to find the vulnerability?
73
+
74
+ Present results as a ranked table:
75
+
76
+ | Threat | Asset | D | R | E | A | D | Total | Risk Level |
77
+ |--------|-------|---|---|---|---|---|-------|------------|
78
+
79
+ Then provide:
80
+ 1. Top 5 risks by DREAD score with detailed justification
81
+ 2. Quick wins — high-score items with easy mitigations
82
+ 3. Systemic risks — patterns across multiple exposures
83
+ 4. Recommended priority order for remediation`,
84
+ pasta: `${SYSTEM_BASE}
85
+
86
+ Perform a **PASTA** (Process for Attack Simulation and Threat Analysis) assessment.
87
+
88
+ Work through all 7 PASTA stages:
89
+
90
+ ### Stage 1: Define Objectives
91
+ What are the business-critical assets? Which @asset declarations represent the crown jewels?
92
+
93
+ ### Stage 2: Define Technical Scope
94
+ Map the attack surface from @flows, @boundary, and @handles annotations. What are the entry points?
95
+
96
+ ### Stage 3: Application Decomposition
97
+ Analyze component relationships from flows and boundaries. Identify trust zones and data paths.
98
+
99
+ ### Stage 4: Threat Analysis
100
+ Map declared @threat annotations to real-world attack techniques. Reference CWE/CAPEC where available.
101
+
102
+ ### Stage 5: Vulnerability Analysis
103
+ Evaluate each @exposes annotation. Which are most exploitable given the technical context?
104
+
105
+ ### Stage 6: Attack Simulation
106
+ For the top 3 most critical exposures, describe a realistic attack scenario step-by-step.
107
+
108
+ ### Stage 7: Risk & Impact Analysis
109
+ Prioritized risk matrix with business impact assessment.
110
+
111
+ End with concrete remediation recommendations tied to specific annotations.`,
112
+ attacker: `${SYSTEM_BASE}
113
+
114
+ Perform an **Attacker Persona** analysis of this threat model.
115
+
116
+ Adopt the mindset of different attacker types and evaluate the codebase:
117
+
118
+ ### 1. Script Kiddie (Low Skill)
119
+ What can be exploited with publicly available tools? Which @exposes have known CVEs (check cwe: refs)?
120
+
121
+ ### 2. Opportunistic Attacker (Medium Skill)
122
+ What attack chains are possible? Can multiple exposures be combined? Check @flows for lateral movement paths.
123
+
124
+ ### 3. Targeted Attacker (High Skill)
125
+ What are the high-value targets (@handles pii/phi/financial/secrets)? What's the path from @boundary entry points to crown jewel assets?
126
+
127
+ ### 4. Insider Threat
128
+ Which @assumes annotations represent blind spots? Where does the model trust internal components without verification?
129
+
130
+ For each persona:
131
+ 1. Most likely attack vector (reference specific annotations)
132
+ 2. Attack path (chain of assets/flows/boundaries)
133
+ 3. Impact if successful
134
+ 4. Current defenses (existing @mitigates)
135
+ 5. Gaps in defense
136
+
137
+ End with a prioritized defense improvement plan.`,
138
+ rapid: `${SYSTEM_BASE}
139
+
140
+ Perform a **Rapid Risk Assessment** — concise, actionable, focused on the highest-impact items.
141
+
142
+ ### Critical Findings (Stop Everything)
143
+ List any P0/critical @exposes without @mitigates. These are active vulnerabilities.
144
+
145
+ ### High-Priority Gaps
146
+ - Unmitigated exposures by severity
147
+ - @assumes that could be violated
148
+ - @boundary without proper controls on crossing flows
149
+
150
+ ### Coverage Assessment
151
+ - What percentage of assets have threat coverage?
152
+ - Which components have @flows but no security annotations?
153
+ - Are there @handles (sensitive data) without corresponding @mitigates?
154
+
155
+ ### Top 5 Recommendations
156
+ Numbered, actionable, with specific annotation suggestions (exact @mitigates lines to add).
157
+
158
+ ### Risk Score
159
+ Rate overall security posture: A (excellent) through F (critical risk). Justify with data from the model.
160
+
161
+ Keep the entire analysis under 500 lines. Be direct — no filler.`,
162
+ general: `${SYSTEM_BASE}
163
+
164
+ Perform a comprehensive threat analysis of this codebase.
165
+
166
+ ### Executive Summary
167
+ 2-3 sentence overall assessment.
168
+
169
+ ### Threat Landscape
170
+ What threats does this application face? Map @threat declarations to real-world attack patterns.
171
+
172
+ ### Security Posture
173
+ - Strengths: well-mitigated areas, good control coverage
174
+ - Weaknesses: unmitigated exposures, missing controls
175
+ - Blind spots: areas with no annotations at all
176
+
177
+ ### Data Flow Analysis
178
+ Trace sensitive data through @flows and @boundary annotations. Where does data cross trust boundaries without protection?
179
+
180
+ ### Missing Annotations
181
+ Based on the architecture visible in @flows and @boundary, what security annotations are likely missing?
182
+
183
+ ### Recommendations
184
+ Prioritized list with:
185
+ 1. What to fix (specific exposure)
186
+ 2. How to fix it (specific control/mitigation)
187
+ 3. What annotation to add (exact syntax)
188
+
189
+ ### Compliance Considerations
190
+ Based on @handles classifications (pii, phi, financial), note relevant compliance requirements (GDPR, HIPAA, PCI-DSS).`,
191
+ };
192
+ /**
193
+ * Build the user message containing the serialized threat model.
194
+ */
195
+ export function buildUserMessage(modelJson, framework, customPrompt) {
196
+ const header = customPrompt
197
+ ? `Analyze this threat model. ${customPrompt}`
198
+ : `Produce a ${FRAMEWORK_LABELS[framework]} for this threat model.`;
199
+ return `${header}
200
+
201
+ <threat_model>
202
+ ${modelJson}
203
+ </threat_model>`;
204
+ }
205
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/analyze/prompts.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,CAAC,MAAM,gBAAgB,GAAsC;IACjE,MAAM,EAAE,wBAAwB;IAChC,KAAK,EAAE,uBAAuB;IAC9B,KAAK,EAAE,yBAAyB;IAChC,QAAQ,EAAE,2BAA2B;IACrC,KAAK,EAAE,uBAAuB;IAC9B,OAAO,EAAE,yBAAyB;CACnC,CAAC;AAEF,MAAM,WAAW,GAAG;;;;;;;;;;;;;;6FAcyE,CAAC;AAE9F,MAAM,CAAC,MAAM,iBAAiB,GAAsC;IAClE,MAAM,EAAE,GAAG,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yDA8BiC;IAEvD,KAAK,EAAE,GAAG,WAAW;;;;;;;;;;;;;;;;;;;;;8CAqBuB;IAE5C,KAAK,EAAE,GAAG,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;4EA2BqD;IAE1E,QAAQ,EAAE,GAAG,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;iDAyBuB;IAE/C,KAAK,EAAE,GAAG,WAAW;;;;;;;;;;;;;;;;;;;;;;;iEAuB0C;IAE/D,OAAO,EAAE,GAAG,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;uHA4B8F;CACtH,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAAiB,EAAE,SAA4B,EAAE,YAAqB;IACrG,MAAM,MAAM,GAAG,YAAY;QACzB,CAAC,CAAC,8BAA8B,YAAY,EAAE;QAC9C,CAAC,CAAC,aAAa,gBAAgB,CAAC,SAAS,CAAC,yBAAyB,CAAC;IAEtE,OAAO,GAAG,MAAM;;;EAGhB,SAAS;gBACK,CAAC;AACjB,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * GuardLink Analyzer — exports.
3
+ */
4
+ export { generateSarif, type SarifOptions } from './sarif.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analyzer/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * GuardLink Analyzer — exports.
3
+ */
4
+ export { generateSarif } from './sarif.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/analyzer/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAqB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * GuardLink SARIF — Convert threat model findings to SARIF 2.1.0.
3
+ *
4
+ * SARIF (Static Analysis Results Interchange Format) is consumed by:
5
+ * - GitHub Advanced Security (code scanning alerts)
6
+ * - VS Code SARIF Viewer extension
7
+ * - Azure DevOps
8
+ * - SonarQube, Snyk, etc.
9
+ *
10
+ * We emit results for:
11
+ * 1. Unmitigated exposures (the primary security findings)
12
+ * 2. Parse errors (annotation syntax problems)
13
+ * 3. Dangling references (broken #id refs)
14
+ *
15
+ * @exposes #sarif to #info-disclosure [low] cwe:CWE-200 -- "SARIF output contains detailed threat model findings"
16
+ * @accepts #info-disclosure on #sarif -- "SARIF export for security tools is the intended feature"
17
+ * @exposes #sarif to #arbitrary-write [high] cwe:CWE-73 -- "SARIF written to user-specified output path"
18
+ * @mitigates #sarif against #arbitrary-write using #path-validation -- "CLI resolves output path before write"
19
+ * @flows #parser -> #sarif via ThreatModel -- "SARIF generator receives parsed threat model"
20
+ * @flows #sarif -> External_Security_Tools via SARIF_JSON -- "Output consumed by GitHub, VS Code, etc."
21
+ */
22
+ import type { ThreatModel, ParseDiagnostic, Severity } from '../types/index.js';
23
+ interface SarifLog {
24
+ $schema: string;
25
+ version: '2.1.0';
26
+ runs: SarifRun[];
27
+ }
28
+ interface SarifRun {
29
+ tool: {
30
+ driver: {
31
+ name: string;
32
+ version: string;
33
+ informationUri: string;
34
+ rules: SarifRule[];
35
+ };
36
+ };
37
+ results: SarifResult[];
38
+ }
39
+ interface SarifRule {
40
+ id: string;
41
+ name: string;
42
+ shortDescription: {
43
+ text: string;
44
+ };
45
+ fullDescription?: {
46
+ text: string;
47
+ };
48
+ helpUri?: string;
49
+ defaultConfiguration: {
50
+ level: 'error' | 'warning' | 'note';
51
+ };
52
+ properties?: Record<string, unknown>;
53
+ }
54
+ interface SarifResult {
55
+ ruleId: string;
56
+ level: 'error' | 'warning' | 'note';
57
+ message: {
58
+ text: string;
59
+ };
60
+ locations: SarifLocation[];
61
+ properties?: Record<string, unknown>;
62
+ }
63
+ interface SarifLocation {
64
+ physicalLocation: {
65
+ artifactLocation: {
66
+ uri: string;
67
+ };
68
+ region: {
69
+ startLine: number;
70
+ startColumn?: number;
71
+ };
72
+ };
73
+ }
74
+ export interface SarifOptions {
75
+ /** Include parse diagnostics as results */
76
+ includeDiagnostics?: boolean;
77
+ /** Include dangling reference warnings */
78
+ includeDanglingRefs?: boolean;
79
+ /** Only include unmitigated exposures at or above this severity */
80
+ minSeverity?: Severity;
81
+ }
82
+ export declare function generateSarif(model: ThreatModel, diagnostics?: ParseDiagnostic[], danglingRefs?: ParseDiagnostic[], options?: SarifOptions): SarifLog;
83
+ export {};
84
+ //# sourceMappingURL=sarif.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sarif.d.ts","sourceRoot":"","sources":["../../src/analyzer/sarif.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAuB,eAAe,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAIrG,UAAU,QAAQ;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,QAAQ,EAAE,CAAC;CAClB;AAED,UAAU,QAAQ;IAChB,IAAI,EAAE;QACJ,MAAM,EAAE;YACN,IAAI,EAAE,MAAM,CAAC;YACb,OAAO,EAAE,MAAM,CAAC;YAChB,cAAc,EAAE,MAAM,CAAC;YACvB,KAAK,EAAE,SAAS,EAAE,CAAC;SACpB,CAAC;KACH,CAAC;IACF,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAED,UAAU,SAAS;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACnC,eAAe,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE;QACpB,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;KACrC,CAAC;IACF,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACpC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,UAAU,aAAa;IACrB,gBAAgB,EAAE;QAChB,gBAAgB,EAAE;YAAE,GAAG,EAAE,MAAM,CAAA;SAAE,CAAC;QAClC,MAAM,EAAE;YACN,SAAS,EAAE,MAAM,CAAC;YAClB,WAAW,CAAC,EAAE,MAAM,CAAC;SACtB,CAAC;KACH,CAAC;CACH;AAyCD,MAAM,WAAW,YAAY;IAC3B,2CAA2C;IAC3C,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,0CAA0C;IAC1C,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,mEAAmE;IACnE,WAAW,CAAC,EAAE,QAAQ,CAAC;CACxB;AAED,wBAAgB,aAAa,CAC3B,KAAK,EAAE,WAAW,EAClB,WAAW,GAAE,eAAe,EAAO,EACnC,YAAY,GAAE,eAAe,EAAO,EACpC,OAAO,GAAE,YAAiB,GACzB,QAAQ,CA+EV"}