@owasp-aghast/aghast 0.8.4 → 0.9.0-rc.1

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 (107) hide show
  1. package/dist/build-config.d.ts.map +1 -1
  2. package/dist/build-config.js +101 -2
  3. package/dist/build-config.js.map +1 -1
  4. package/dist/check-library.d.ts +25 -0
  5. package/dist/check-library.d.ts.map +1 -1
  6. package/dist/check-library.js +165 -0
  7. package/dist/check-library.js.map +1 -1
  8. package/dist/ci-metadata.d.ts +42 -0
  9. package/dist/ci-metadata.d.ts.map +1 -0
  10. package/dist/ci-metadata.js +131 -0
  11. package/dist/ci-metadata.js.map +1 -0
  12. package/dist/cli.js +4 -1
  13. package/dist/cli.js.map +1 -1
  14. package/dist/concurrency.d.ts +18 -0
  15. package/dist/concurrency.d.ts.map +1 -0
  16. package/dist/concurrency.js +39 -0
  17. package/dist/concurrency.js.map +1 -0
  18. package/dist/cost-tracker.d.ts +45 -0
  19. package/dist/cost-tracker.d.ts.map +1 -0
  20. package/dist/cost-tracker.js +56 -0
  21. package/dist/cost-tracker.js.map +1 -0
  22. package/dist/discoveries/glob-discovery.d.ts +21 -0
  23. package/dist/discoveries/glob-discovery.d.ts.map +1 -0
  24. package/dist/discoveries/glob-discovery.js +215 -0
  25. package/dist/discoveries/glob-discovery.js.map +1 -0
  26. package/dist/discoveries/script-discovery.d.ts +117 -0
  27. package/dist/discoveries/script-discovery.d.ts.map +1 -0
  28. package/dist/discoveries/script-discovery.js +593 -0
  29. package/dist/discoveries/script-discovery.js.map +1 -0
  30. package/dist/docs-url.d.ts +14 -0
  31. package/dist/docs-url.d.ts.map +1 -0
  32. package/dist/docs-url.js +17 -0
  33. package/dist/docs-url.js.map +1 -0
  34. package/dist/error-codes.d.ts +12 -1
  35. package/dist/error-codes.d.ts.map +1 -1
  36. package/dist/error-codes.js +16 -2
  37. package/dist/error-codes.js.map +1 -1
  38. package/dist/formatters/csv-formatter.d.ts +12 -1
  39. package/dist/formatters/csv-formatter.d.ts.map +1 -1
  40. package/dist/formatters/csv-formatter.js +64 -2
  41. package/dist/formatters/csv-formatter.js.map +1 -1
  42. package/dist/formatters/html-formatter.d.ts.map +1 -1
  43. package/dist/formatters/html-formatter.js +43 -3
  44. package/dist/formatters/html-formatter.js.map +1 -1
  45. package/dist/formatters/index.d.ts.map +1 -1
  46. package/dist/formatters/index.js +2 -0
  47. package/dist/formatters/index.js.map +1 -1
  48. package/dist/formatters/markdown-formatter.d.ts +61 -0
  49. package/dist/formatters/markdown-formatter.d.ts.map +1 -0
  50. package/dist/formatters/markdown-formatter.js +557 -0
  51. package/dist/formatters/markdown-formatter.js.map +1 -0
  52. package/dist/formatters/sarif-formatter.d.ts +7 -0
  53. package/dist/formatters/sarif-formatter.d.ts.map +1 -1
  54. package/dist/formatters/sarif-formatter.js +80 -0
  55. package/dist/formatters/sarif-formatter.js.map +1 -1
  56. package/dist/formatters/types.d.ts +24 -0
  57. package/dist/formatters/types.d.ts.map +1 -1
  58. package/dist/index.d.ts +4 -0
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +342 -9
  61. package/dist/index.js.map +1 -1
  62. package/dist/issue-file-writer.d.ts +21 -0
  63. package/dist/issue-file-writer.d.ts.map +1 -0
  64. package/dist/issue-file-writer.js +307 -0
  65. package/dist/issue-file-writer.js.map +1 -0
  66. package/dist/judge.d.ts +62 -0
  67. package/dist/judge.d.ts.map +1 -0
  68. package/dist/judge.js +305 -0
  69. package/dist/judge.js.map +1 -0
  70. package/dist/mock-agent-provider.d.ts +3 -0
  71. package/dist/mock-agent-provider.d.ts.map +1 -1
  72. package/dist/mock-agent-provider.js +13 -0
  73. package/dist/mock-agent-provider.js.map +1 -1
  74. package/dist/new-check.d.ts.map +1 -1
  75. package/dist/new-check.js +322 -13
  76. package/dist/new-check.js.map +1 -1
  77. package/dist/opencode-provider.d.ts.map +1 -1
  78. package/dist/opencode-provider.js +33 -0
  79. package/dist/opencode-provider.js.map +1 -1
  80. package/dist/repo-scan.d.ts +80 -0
  81. package/dist/repo-scan.d.ts.map +1 -0
  82. package/dist/repo-scan.js +250 -0
  83. package/dist/repo-scan.js.map +1 -0
  84. package/dist/result-handlers/pr-comment-handler.d.ts +136 -0
  85. package/dist/result-handlers/pr-comment-handler.d.ts.map +1 -0
  86. package/dist/result-handlers/pr-comment-handler.js +381 -0
  87. package/dist/result-handlers/pr-comment-handler.js.map +1 -0
  88. package/dist/retry.d.ts +128 -0
  89. package/dist/retry.d.ts.map +1 -0
  90. package/dist/retry.js +261 -0
  91. package/dist/retry.js.map +1 -0
  92. package/dist/runtime-config.d.ts.map +1 -1
  93. package/dist/runtime-config.js +62 -0
  94. package/dist/runtime-config.js.map +1 -1
  95. package/dist/scan-runner.d.ts +31 -22
  96. package/dist/scan-runner.d.ts.map +1 -1
  97. package/dist/scan-runner.js +145 -100
  98. package/dist/scan-runner.js.map +1 -1
  99. package/dist/semgrep-runner.js +6 -4
  100. package/dist/semgrep-runner.js.map +1 -1
  101. package/dist/stats.d.ts.map +1 -1
  102. package/dist/stats.js +4 -1
  103. package/dist/stats.js.map +1 -1
  104. package/dist/types.d.ts +149 -2
  105. package/dist/types.d.ts.map +1 -1
  106. package/dist/types.js.map +1 -1
  107. package/package.json +1 -1
@@ -0,0 +1,557 @@
1
+ /**
2
+ * Markdown output formatter — produces a human-readable security report.
3
+ * See SPECIFICATION.md Appendix E.3.1.
4
+ *
5
+ * Sections (in order):
6
+ * 1. Header — Title, date, AI provider/model, repository info
7
+ * 2. Executive Summary — One-paragraph overview of the scan outcome
8
+ * 3. Summary Table — All checks with PASS/FAIL/FLAG/ERROR status
9
+ * 4. Detailed Findings — Failed checks with descriptions, snippets, recs
10
+ * 5. Flagged Items — Checks needing human review (only when present)
11
+ * 6. Errors — Checks with ERROR status (only when present)
12
+ * 7. Statistics — Totals for the scan
13
+ * 8. CI Metadata — Job URL / branch / pipeline info (only when set)
14
+ */
15
+ /** File-extension to fenced-code-block language tag. Default is `text`. */
16
+ const EXTENSION_LANGUAGE_MAP = {
17
+ ts: 'ts',
18
+ tsx: 'tsx',
19
+ js: 'js',
20
+ jsx: 'jsx',
21
+ mjs: 'js',
22
+ cjs: 'js',
23
+ py: 'python',
24
+ rb: 'ruby',
25
+ go: 'go',
26
+ rs: 'rust',
27
+ java: 'java',
28
+ kt: 'kotlin',
29
+ scala: 'scala',
30
+ cs: 'csharp',
31
+ c: 'c',
32
+ h: 'c',
33
+ cpp: 'cpp',
34
+ cc: 'cpp',
35
+ hpp: 'cpp',
36
+ php: 'php',
37
+ swift: 'swift',
38
+ sh: 'bash',
39
+ bash: 'bash',
40
+ zsh: 'bash',
41
+ ps1: 'powershell',
42
+ yml: 'yaml',
43
+ yaml: 'yaml',
44
+ json: 'json',
45
+ toml: 'toml',
46
+ xml: 'xml',
47
+ html: 'html',
48
+ htm: 'html',
49
+ css: 'css',
50
+ scss: 'scss',
51
+ sql: 'sql',
52
+ md: 'markdown',
53
+ };
54
+ /** Resolves the fenced-code-block language tag from a file path. */
55
+ export function languageForFile(filePath) {
56
+ const lastDot = filePath.lastIndexOf('.');
57
+ if (lastDot < 0 || lastDot === filePath.length - 1)
58
+ return 'text';
59
+ const ext = filePath.slice(lastDot + 1).toLowerCase();
60
+ return EXTENSION_LANGUAGE_MAP[ext] ?? 'text';
61
+ }
62
+ /** Returns the longest backtick run in `code` so we can pick a longer fence. */
63
+ function chooseFence(code) {
64
+ // Fast path: no backticks in body → standard 3-backtick fence.
65
+ if (code.indexOf('`') === -1)
66
+ return '```';
67
+ let longest = 0;
68
+ const re = /`+/g;
69
+ let match;
70
+ while ((match = re.exec(code)) !== null) {
71
+ if (match[0].length > longest)
72
+ longest = match[0].length;
73
+ }
74
+ return '`'.repeat(Math.max(3, longest + 1));
75
+ }
76
+ /** Wraps code in a fenced block with a language tag, escaping nested fences safely. */
77
+ export function fencedCode(code, language) {
78
+ const fence = chooseFence(code);
79
+ // Strip a single trailing newline (LF or CRLF) so we control spacing inside
80
+ // the block. Without CRLF handling, Windows-line-ending snippets would leave
81
+ // a stray \r before the closing fence.
82
+ const body = code.replace(/\r?\n$/, '');
83
+ return `${fence}${language}\n${body}\n${fence}`;
84
+ }
85
+ /**
86
+ * Wraps `value` in a backtick fence long enough to survive any backticks
87
+ * already inside `value`. Per CommonMark, an inline-code span uses a backtick
88
+ * run of length N around a body that contains no run of length N — minimum
89
+ * length 1 (unlike fenced code blocks, which require minimum 3). Pad with a
90
+ * leading/trailing space if the body itself starts or ends with a backtick.
91
+ * Newlines are collapsed to spaces because inline-code spans must be
92
+ * single-line (and table cells must not contain raw newlines).
93
+ */
94
+ export function inlineCode(value) {
95
+ // CommonMark/GFM treat a bare CR (not just CRLF/LF) as a line ending — see
96
+ // escapeMarkdownText/escapeInlineText/escapeTableCell's identical fix — so
97
+ // collapse it here too. `value` is often AI-response-controlled (e.g.
98
+ // `issue.file`); an uncollapsed bare `\r` would split the surrounding
99
+ // Markdown into two physical lines before the backtick span can close,
100
+ // letting a leading `#` on the second line render as a real heading.
101
+ const flat = value.replace(/\r\n?|\n/g, ' ');
102
+ // Compute longest backtick run inline (don't reuse chooseFence — its
103
+ // minimum is 3 for block fences, but inline-code minimum is 1).
104
+ let longest = 0;
105
+ const re = /`+/g;
106
+ let match;
107
+ while ((match = re.exec(flat)) !== null) {
108
+ if (match[0].length > longest)
109
+ longest = match[0].length;
110
+ }
111
+ const fence = '`'.repeat(longest + 1);
112
+ const padStart = flat.startsWith('`') ? ' ' : '';
113
+ const padEnd = flat.endsWith('`') ? ' ' : '';
114
+ return `${fence}${padStart}${flat}${padEnd}${fence}`;
115
+ }
116
+ /**
117
+ * Escapes characters so a string is safe inside a Markdown table cell.
118
+ *
119
+ * Order matters:
120
+ * 1. Backslashes first, so subsequent `\|` insertions aren't mis-parsed
121
+ * (input `a\|b` would otherwise become `a\\|b`, which renders as a
122
+ * literal `\` followed by an UNESCAPED `|` — splitting the cell).
123
+ * 2. Pipes next.
124
+ * 3. Backticks (escape so they don't open inline-code spans inside the
125
+ * cell — a single backtick in a `checkName` would otherwise bleed
126
+ * across columns).
127
+ * 4. Collapse newlines to spaces — table cells must be single-line.
128
+ */
129
+ function escapeTableCell(value) {
130
+ return value
131
+ .replace(/\\/g, '\\\\')
132
+ .replace(/\|/g, '\\|')
133
+ .replace(/`/g, '\\`')
134
+ // CommonMark/GFM treat a bare CR (not just CRLF/LF) as a line ending — see
135
+ // escapeMarkdownText's identical fix — so collapse it here too, not just
136
+ // `\r?\n`, or a lone `\r` would survive uncollapsed into a multi-line cell.
137
+ .replace(/\r\n?|\n/g, ' ');
138
+ }
139
+ /**
140
+ * Escapes AI-authored free text (issue `description` / `recommendation`) for
141
+ * safe rendering as a Markdown *block*.
142
+ *
143
+ * Threat model: these fields come from the LLM's analysis of the scanned
144
+ * repository, whose source can contain attacker-crafted strings. Rendered raw
145
+ * they can inject active HTML that executes when the report is viewed on GitHub,
146
+ * a wiki, or any Markdown viewer permitting inline HTML (`<script>`,
147
+ * `<img onerror=...>`), and can break the report's own structure (table cells,
148
+ * headings, code fences, lists, blockquotes). The HTML formatter already defends
149
+ * the same fields via `escapeHtml`; this is the Markdown-side equivalent.
150
+ *
151
+ * Unlike {@link escapeInlineText}, newlines are *preserved* — these are prose
152
+ * paragraphs, not single-line bullets — so the escaping is applied per line:
153
+ * 1. Inline pass: backslash-escape every character that can open inline
154
+ * formatting or a raw HTML tag (`\` first so we don't re-escape our own
155
+ * escapes). Escaping `<` is what neutralises the inline-HTML vector — per
156
+ * CommonMark/GFM, `\<script>` renders as literal text.
157
+ * 2. Block pass: backslash-escape a leading marker (after optional
158
+ * indentation) that would open a block construct — ATX heading (`#`),
159
+ * list/thematic-break (`-`/`+`), setext underline (`=`), or an ordered-list
160
+ * marker (`1.` / `1)`). Blockquote (`>`) and fences (`` ` ``/`~`) are
161
+ * already handled by the inline pass.
162
+ */
163
+ export function escapeMarkdownText(value) {
164
+ return value
165
+ // CommonMark/GFM treat CRLF, LF, *and a bare CR* as line endings — fold
166
+ // all three to `\n` before splitting, or a lone `\r` would slip through
167
+ // unsplit and its trailing content would bypass the block-marker escapes
168
+ // below despite a compliant renderer treating it as a new line.
169
+ .replace(/\r\n?/g, '\n')
170
+ .split('\n')
171
+ .map((line) => {
172
+ const inline = line
173
+ .replace(/\\/g, '\\\\')
174
+ .replace(/[`*_[\]<>|~]/g, (m) => `\\${m}`);
175
+ return inline
176
+ .replace(/^(\s*)([#=+-])/, '$1\\$2')
177
+ .replace(/^(\s*)(\d+)([.)])/, '$1$2\\$3');
178
+ })
179
+ .join('\n');
180
+ }
181
+ /** Sentence-case label for a status (e.g. `PASS` → `Passed`). */
182
+ function statusLabel(status) {
183
+ switch (status) {
184
+ case 'PASS': return 'Passed';
185
+ case 'FAIL': return 'Failed';
186
+ case 'FLAG': return 'Flagged';
187
+ case 'ERROR': return 'Error';
188
+ }
189
+ }
190
+ function renderHeader(results) {
191
+ const lines = [];
192
+ lines.push('# Security Scan Report');
193
+ lines.push('');
194
+ lines.push(`- **Scan ID:** ${inlineCode(results.scanId)}`);
195
+ lines.push(`- **Date:** ${results.timestamp}`);
196
+ lines.push(`- **aghast version:** ${results.version}`);
197
+ const models = results.agentProvider.models.length > 0
198
+ ? results.agentProvider.models.join(', ')
199
+ : '(none)';
200
+ lines.push(`- **Agent provider:** ${results.agentProvider.name} (model: ${models})`);
201
+ lines.push('');
202
+ lines.push(...renderRepository(results.repository));
203
+ return lines.join('\n');
204
+ }
205
+ function renderRepository(repo) {
206
+ const lines = [];
207
+ lines.push('## Repository');
208
+ lines.push('');
209
+ lines.push(`- **Path:** ${inlineCode(repo.path)}`);
210
+ // Wrap the remote URL in `<...>` (CommonMark autolink syntax) so it
211
+ // remains clickable while the angle-bracket form prevents underscores or
212
+ // other markdown-special characters in the URL from being interpreted as
213
+ // formatting. If the URL itself contains `<` or `>` (illegal per RFC 3986
214
+ // but possible in pathological inputs) we fall back to inline-code so the
215
+ // angle-bracket pair stays balanced.
216
+ if (repo.remoteUrl) {
217
+ const url = repo.remoteUrl;
218
+ const safeAutoLink = !url.includes('<') && !url.includes('>') && !/\s/.test(url);
219
+ lines.push(`- **Remote URL:** ${safeAutoLink ? `<${url}>` : inlineCode(url)}`);
220
+ }
221
+ if (repo.branch)
222
+ lines.push(`- **Branch:** ${inlineCode(repo.branch)}`);
223
+ if (repo.commit)
224
+ lines.push(`- **Commit:** ${inlineCode(repo.commit)}`);
225
+ lines.push(`- **Git repository:** ${repo.isGitRepository ? 'yes' : 'no'}`);
226
+ return lines;
227
+ }
228
+ function renderExecutiveSummary(results) {
229
+ const { summary } = results;
230
+ let outcome;
231
+ if (summary.totalChecks === 0) {
232
+ outcome = 'No checks were applicable to this repository.';
233
+ }
234
+ else if (summary.failedChecks > 0 && summary.errorChecks > 0) {
235
+ outcome = `The scan found **${summary.failedChecks} failing** check(s) with a total of **${summary.totalIssues} issue(s)**, and **${summary.errorChecks}** check(s) errored before completing.`;
236
+ }
237
+ else if (summary.failedChecks > 0) {
238
+ outcome = `The scan found **${summary.failedChecks} failing** check(s) with a total of **${summary.totalIssues} issue(s)** that require attention.`;
239
+ }
240
+ else if (summary.errorChecks > 0) {
241
+ outcome = `The scan completed with **${summary.errorChecks}** check(s) in an error state and no failing checks.`;
242
+ }
243
+ else if (summary.flaggedChecks > 0) {
244
+ outcome = `The scan completed with **${summary.flaggedChecks}** check(s) flagged for human review and no failing checks.`;
245
+ }
246
+ else {
247
+ outcome = `All ${summary.totalChecks} check(s) passed with no issues detected.`;
248
+ }
249
+ return `## Executive Summary\n\n${outcome}`;
250
+ }
251
+ function renderSummaryTable(results) {
252
+ const lines = [];
253
+ lines.push('## Summary Table');
254
+ lines.push('');
255
+ if (results.checks.length === 0) {
256
+ lines.push('_No checks were executed._');
257
+ return lines.join('\n');
258
+ }
259
+ lines.push('| Check ID | Name | Status | Issues | Time (ms) |');
260
+ lines.push('| --- | --- | --- | --- | --- |');
261
+ for (const check of results.checks) {
262
+ lines.push(`| ${inlineCode(check.checkId)} `
263
+ + `| ${escapeTableCell(check.checkName)} `
264
+ + `| ${check.status} `
265
+ + `| ${check.issuesFound} `
266
+ + `| ${check.executionTime} |`);
267
+ }
268
+ return lines.join('\n');
269
+ }
270
+ function renderDetailedFindings(results) {
271
+ const failingChecks = results.checks.filter((c) => c.status === 'FAIL');
272
+ const lines = [];
273
+ lines.push('## Detailed Findings');
274
+ lines.push('');
275
+ if (failingChecks.length === 0) {
276
+ lines.push('_No failing checks._');
277
+ return lines.join('\n');
278
+ }
279
+ for (const check of failingChecks) {
280
+ lines.push(`### ${check.checkName} (${inlineCode(check.checkId)})`);
281
+ lines.push('');
282
+ lines.push(`- **Status:** ${statusLabel(check.status)}`);
283
+ lines.push(`- **Issues found:** ${check.issuesFound}`);
284
+ if (typeof check.targetsAnalyzed === 'number') {
285
+ lines.push(`- **Targets analyzed:** ${check.targetsAnalyzed}`);
286
+ }
287
+ lines.push('');
288
+ const issues = results.issues.filter((i) => i.checkId === check.checkId);
289
+ if (issues.length === 0) {
290
+ lines.push('_No issue details were attached to this check._');
291
+ lines.push('');
292
+ continue;
293
+ }
294
+ issues.forEach((issue, idx) => {
295
+ lines.push(...renderIssue(issue, idx + 1));
296
+ lines.push('');
297
+ });
298
+ }
299
+ // Trim trailing blank line so section terminates cleanly.
300
+ while (lines.length > 0 && lines[lines.length - 1] === '')
301
+ lines.pop();
302
+ return lines.join('\n');
303
+ }
304
+ function renderIssue(issue, ordinal) {
305
+ const lines = [];
306
+ // Note: issue ordinal restarts at 1 inside each failing check. The H4
307
+ // headings are scoped under their check's H3 parent so the structure is
308
+ // clear when reading top-to-bottom; consumers that flatten H4s (e.g. TOC
309
+ // generators) will see duplicate "Issue 1" anchors and should disambiguate
310
+ // by including the parent H3 in the anchor.
311
+ lines.push(`#### Issue ${ordinal}: ${inlineCode(issue.file)} lines ${issue.startLine}-${issue.endLine}`);
312
+ lines.push('');
313
+ if (issue.severity)
314
+ lines.push(`- **Severity:** ${issue.severity}`);
315
+ if (issue.confidence)
316
+ lines.push(`- **Confidence:** ${issue.confidence}`);
317
+ lines.push(`- **Location:** ${inlineCode(issue.file)}:${issue.startLine}-${issue.endLine}`);
318
+ lines.push('');
319
+ lines.push('**Description:**');
320
+ lines.push('');
321
+ // AI-authored free text — escape so crafted repo content can't inject active
322
+ // HTML or break the report's Markdown structure (see escapeMarkdownText).
323
+ lines.push(escapeMarkdownText(issue.description));
324
+ if (issue.codeSnippet) {
325
+ lines.push('');
326
+ lines.push('**Code:**');
327
+ lines.push('');
328
+ lines.push(fencedCode(issue.codeSnippet, languageForFile(issue.file)));
329
+ }
330
+ if (issue.dataFlow && issue.dataFlow.length > 0) {
331
+ lines.push('');
332
+ lines.push('**Data flow:**');
333
+ lines.push('');
334
+ issue.dataFlow.forEach((step, i) => {
335
+ lines.push(`${i + 1}. ${inlineCode(step.file)}:${step.lineNumber} - ${step.label}`);
336
+ });
337
+ }
338
+ if (issue.recommendation) {
339
+ lines.push('');
340
+ lines.push('**Recommendation:**');
341
+ lines.push('');
342
+ // Same AI-authored free text as description — escape it identically.
343
+ lines.push(escapeMarkdownText(issue.recommendation));
344
+ }
345
+ if (issue.judge) {
346
+ lines.push('');
347
+ lines.push('**Judge verdict:**');
348
+ lines.push('');
349
+ const confidence = `${Math.round(issue.judge.confidence * 100)}% confidence`;
350
+ lines.push(`- **Verdict:** ${issue.judge.verdict} (${confidence})`);
351
+ lines.push(`- **Model:** ${inlineCode(issue.judge.model)}`);
352
+ if (issue.judge.rationale) {
353
+ // Rationale is model-authored free text; escape it so a stray backtick or
354
+ // pipe cannot break out of the bullet and corrupt the rest of the report.
355
+ lines.push(`- **Rationale:** ${escapeInlineText(issue.judge.rationale)}`);
356
+ }
357
+ }
358
+ return lines;
359
+ }
360
+ function renderFlaggedItems(results) {
361
+ const flagged = results.checks.filter((c) => c.status === 'FLAG');
362
+ if (flagged.length === 0)
363
+ return null;
364
+ const lines = [];
365
+ lines.push('## Flagged Items');
366
+ lines.push('');
367
+ lines.push('The following checks completed but have been flagged for human review.');
368
+ lines.push('');
369
+ lines.push('| Check ID | Name | Issues |');
370
+ lines.push('| --- | --- | --- |');
371
+ for (const check of flagged) {
372
+ lines.push(`| ${inlineCode(check.checkId)} `
373
+ + `| ${escapeTableCell(check.checkName)} `
374
+ + `| ${check.issuesFound} |`);
375
+ }
376
+ return lines.join('\n');
377
+ }
378
+ function renderErrors(results) {
379
+ const errored = results.checks.filter((c) => c.status === 'ERROR');
380
+ if (errored.length === 0)
381
+ return null;
382
+ const lines = [];
383
+ lines.push('## Errors');
384
+ lines.push('');
385
+ lines.push('The following checks failed to execute and produced no findings.');
386
+ lines.push('');
387
+ // Use the same H3 shape as Detailed Findings (`### Name (id)`) — no leading
388
+ // ordinal — so the report's heading style is consistent across sections.
389
+ errored.forEach((check) => {
390
+ lines.push(`### ${check.checkName} (${inlineCode(check.checkId)})`);
391
+ lines.push('');
392
+ if (check.error) {
393
+ lines.push('**Error message:**');
394
+ lines.push('');
395
+ lines.push(fencedCode(check.error, 'text'));
396
+ }
397
+ else {
398
+ lines.push('_No error message was captured._');
399
+ }
400
+ if (check.rawAiResponse) {
401
+ lines.push('');
402
+ lines.push('**Raw agent response:**');
403
+ lines.push('');
404
+ lines.push(fencedCode(check.rawAiResponse, 'text'));
405
+ }
406
+ lines.push('');
407
+ });
408
+ while (lines.length > 0 && lines[lines.length - 1] === '')
409
+ lines.pop();
410
+ return lines.join('\n');
411
+ }
412
+ function renderStatistics(results) {
413
+ const { summary } = results;
414
+ const lines = [];
415
+ lines.push('## Statistics');
416
+ lines.push('');
417
+ lines.push(`- **Total checks:** ${summary.totalChecks}`);
418
+ lines.push(`- **Passed:** ${summary.passedChecks}`);
419
+ lines.push(`- **Failed:** ${summary.failedChecks}`);
420
+ lines.push(`- **Flagged:** ${summary.flaggedChecks}`);
421
+ lines.push(`- **Errors:** ${summary.errorChecks}`);
422
+ lines.push(`- **Total issues:** ${summary.totalIssues}`);
423
+ lines.push(`- **Execution time (ms):** ${results.executionTime}`);
424
+ lines.push(`- **Start:** ${results.startTime}`);
425
+ lines.push(`- **End:** ${results.endTime}`);
426
+ if (results.tokenUsage) {
427
+ lines.push(`- **Tokens:** total ${results.tokenUsage.totalTokens.toLocaleString('en-US')} `
428
+ + `(input ${results.tokenUsage.inputTokens.toLocaleString('en-US')}, `
429
+ + `output ${results.tokenUsage.outputTokens.toLocaleString('en-US')})`);
430
+ }
431
+ // Cost sits with tokens rather than under its own heading: it is the same
432
+ // question ("what did this run consume?") and the reader is already here.
433
+ const cost = results.metadata?.cost;
434
+ if (cost) {
435
+ lines.push(`- **Estimated cost:** ${formatCost(cost.totalCostUsd, cost.currency)}`);
436
+ }
437
+ return lines.join('\n');
438
+ }
439
+ /**
440
+ * Format a cost for display. Sub-cent runs are common with cheap models, and
441
+ * rounding them to "$0.00" reads as "free" rather than "very small", so those
442
+ * get four decimal places instead of two.
443
+ */
444
+ function formatCost(amount, currency) {
445
+ const decimals = amount > 0 && amount < 0.01 ? 4 : 2;
446
+ const value = amount.toFixed(decimals);
447
+ return currency === 'USD' ? `$${value}` : `${value} ${escapeInlineText(currency)}`;
448
+ }
449
+ /**
450
+ * Judge verdict counts. Rendered only when the judge stage ran — `judgedIssues`
451
+ * is the marker, since every other counter is legitimately zero on a clean scan
452
+ * and cannot distinguish "judge ran and found nothing" from "judge never ran".
453
+ */
454
+ function renderJudgeSummary(results) {
455
+ const { summary } = results;
456
+ if (summary.judgedIssues === undefined)
457
+ return null;
458
+ const lines = [];
459
+ lines.push('## Judge Verdicts');
460
+ lines.push('');
461
+ lines.push(`- **Issues judged:** ${summary.judgedIssues}`);
462
+ if (summary.falsePositives !== undefined) {
463
+ lines.push(`- **Judged false positive:** ${summary.falsePositives}`);
464
+ }
465
+ if (summary.uncertainJudgements !== undefined) {
466
+ lines.push(`- **Uncertain:** ${summary.uncertainJudgements}`);
467
+ }
468
+ if (summary.flaggedByCheck !== undefined) {
469
+ lines.push(`- **Flagged by check:** ${summary.flaggedByCheck}`);
470
+ }
471
+ if (summary.flaggedByJudge !== undefined) {
472
+ lines.push(`- **Flagged by judge:** ${summary.flaggedByJudge}`);
473
+ }
474
+ return lines.join('\n');
475
+ }
476
+ /**
477
+ * Escape characters that would otherwise be interpreted as Markdown formatting
478
+ * when interpolating arbitrary user/CI strings into bullet content. Conservative
479
+ * — only escapes the syntactic characters that change rendering: `\`, `*`, `_`,
480
+ * `` ` ``, `<`, `[`, `]`, `|`. Newlines collapsed to spaces (bullets are
481
+ * single-line). Keep this scoped to the CI-metadata path where keys/values come
482
+ * from arbitrary `Record<string, unknown>` input.
483
+ */
484
+ function escapeInlineText(value) {
485
+ return value
486
+ .replace(/\\/g, '\\\\')
487
+ .replace(/[*_`<[\]|]/g, (m) => `\\${m}`)
488
+ // Collapse CRLF, bare LF, *and* a bare CR to a space — CommonMark/GFM
489
+ // treats a lone `\r` as a line ending too (see escapeMarkdownText's
490
+ // identical fix), and an uncollapsed bare CR here would let a renderer
491
+ // split this "single-line" bullet into two lines, letting a leading
492
+ // block marker on the second line escape the bullet.
493
+ .replace(/\r\n?|\n/g, ' ');
494
+ }
495
+ /** Human-readable labels for CIMetadata fields, in display order. */
496
+ const CI_METADATA_LABELS = [
497
+ ['jobUrl', 'Job URL'],
498
+ ['branch', 'Ref'],
499
+ ['pipelineSource', 'Trigger'],
500
+ ['jobStartedAt', 'Started'],
501
+ ];
502
+ /**
503
+ * Renders `metadata.ciMetadata` as a labelled bullet list.
504
+ *
505
+ * This was originally written when `ScanResults.metadata` was an untyped
506
+ * `Record<string, unknown>` and iterated its top-level keys. #260 replaced that
507
+ * with the closed `ScanMetadata` type, whose members (`ciMetadata`, `cost`) are
508
+ * nested objects — so the generic iteration would have emitted a JSON blob per
509
+ * key, and would also have folded `cost` under a heading titled "CI Metadata".
510
+ *
511
+ * Values are still escaped: they originate from CI environment variables, which
512
+ * are attacker-influenceable on forked-PR builds.
513
+ */
514
+ function renderCIMetadata(results) {
515
+ const ci = results.metadata?.ciMetadata;
516
+ if (!ci)
517
+ return null;
518
+ const lines = [];
519
+ for (const [key, label] of CI_METADATA_LABELS) {
520
+ const value = ci[key];
521
+ if (value == null || value === '')
522
+ continue;
523
+ lines.push(`- **${label}:** ${escapeInlineText(value)}`);
524
+ }
525
+ // Every field is optional, so a present-but-empty object yields no rows —
526
+ // emit nothing rather than a bare heading.
527
+ if (lines.length === 0)
528
+ return null;
529
+ return ['## CI Metadata', '', ...lines].join('\n');
530
+ }
531
+ export class MarkdownFormatter {
532
+ id = 'markdown';
533
+ fileExtension = '.md';
534
+ format(results) {
535
+ const sections = [
536
+ renderHeader(results),
537
+ renderExecutiveSummary(results),
538
+ renderSummaryTable(results),
539
+ renderDetailedFindings(results),
540
+ ];
541
+ const flagged = renderFlaggedItems(results);
542
+ if (flagged)
543
+ sections.push(flagged);
544
+ const errors = renderErrors(results);
545
+ if (errors)
546
+ sections.push(errors);
547
+ const judge = renderJudgeSummary(results);
548
+ if (judge)
549
+ sections.push(judge);
550
+ sections.push(renderStatistics(results));
551
+ const ci = renderCIMetadata(results);
552
+ if (ci)
553
+ sections.push(ci);
554
+ return sections.join('\n\n') + '\n';
555
+ }
556
+ }
557
+ //# sourceMappingURL=markdown-formatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown-formatter.js","sourceRoot":"","sources":["../../src/formatters/markdown-formatter.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,13 @@ export declare class SarifFormatter implements OutputFormatter {
11
11
  readonly id = "sarif";
12
12
  readonly fileExtension = ".sarif";
13
13
  format(results: ScanResults): string;
14
+ /**
15
+ * Map CI/CD metadata (spec E.4) to a single SARIF invocation entry. The
16
+ * `properties` bag is the conventional location for non-standard run
17
+ * context in SARIF; we use stable, namespaced keys (`aghast.<field>`) so
18
+ * downstream consumers can rely on the shape.
19
+ */
20
+ private buildInvocations;
14
21
  private buildRules;
15
22
  private buildResults;
16
23
  private buildValidationResults;
@@ -1 +1 @@
1
- {"version":3,"file":"sarif-formatter.d.ts","sourceRoot":"","sources":["../../src/formatters/sarif-formatter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAiD,MAAM,aAAa,CAAC;AAC9F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,kDAAkD;AAClD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAY7F;AAiED,qBAAa,cAAe,YAAW,eAAe;IACpD,QAAQ,CAAC,EAAE,WAAW;IACtB,QAAQ,CAAC,aAAa,YAAY;IAElC,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM;IA8BpC,OAAO,CAAC,UAAU;IAclB,OAAO,CAAC,YAAY;IAgCpB,OAAO,CAAC,sBAAsB;IAoC9B,OAAO,CAAC,aAAa;CAiBtB"}
1
+ {"version":3,"file":"sarif-formatter.d.ts","sourceRoot":"","sources":["../../src/formatters/sarif-formatter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAA2E,MAAM,aAAa,CAAC;AACxH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,kDAAkD;AAClD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAY7F;AAqGD,qBAAa,cAAe,YAAW,eAAe;IACpD,QAAQ,CAAC,EAAE,WAAW;IACtB,QAAQ,CAAC,aAAa,YAAY;IAElC,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM;IAgCpC;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,UAAU;IAclB,OAAO,CAAC,YAAY;IAqEpB,OAAO,CAAC,sBAAsB;IAoC9B,OAAO,CAAC,aAAa;CAiBtB"}