@extenshi/cli 0.0.6 → 0.0.7
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/dist/render.d.ts +66 -0
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +172 -56
- package/dist/render.js.map +1 -1
- package/package.json +1 -1
package/dist/render.d.ts
CHANGED
|
@@ -5,6 +5,72 @@
|
|
|
5
5
|
* then by scanner, using chalk for colour.
|
|
6
6
|
*
|
|
7
7
|
* Invoked only when --json flag is NOT set.
|
|
8
|
+
*
|
|
9
|
+
* Schema tolerance
|
|
10
|
+
* ----------------
|
|
11
|
+
* The scan-worker returns the dags `ScannerResult.to_dict()` shape, NOT a
|
|
12
|
+
* normalised one (see services/extenshi-scan-worker/orchestrator + dags
|
|
13
|
+
* scanners/base_scanner.py). Concretely:
|
|
14
|
+
* - scanner objects use `scanner_name` (not `scanner`) and a lowercase
|
|
15
|
+
* `status` from the `ScanStatus` enum: `completed` / `failed` / `timeout`
|
|
16
|
+
* / `malformed_output` / `skipped` (plus the orchestrator's `error`) —
|
|
17
|
+
* never `SUCCESS`.
|
|
18
|
+
* - each scanner emits its OWN finding shape: the identifier is `rule_id`
|
|
19
|
+
* (semgrep/static_scan/yara/library_hash), `type` (jsluice/wallet_chain),
|
|
20
|
+
* `pattern` (jstap), or `id` (obfuscation); the message is `message` /
|
|
21
|
+
* `description` / `summary` / `url`; the category is `category` /
|
|
22
|
+
* `analyzer` / `kind` / `tags`; severity is mixed-case.
|
|
23
|
+
* So we read every field through a fallback chain instead of a single key —
|
|
24
|
+
* otherwise every finding renders as "(no rule)" / "[unknown]" and the
|
|
25
|
+
* success count reads 0/N (the bug this module had before).
|
|
26
|
+
*/
|
|
27
|
+
interface Finding {
|
|
28
|
+
severity?: string;
|
|
29
|
+
[key: string]: unknown;
|
|
30
|
+
}
|
|
31
|
+
interface ScannerResult {
|
|
32
|
+
/** dags shape */
|
|
33
|
+
scanner_name?: string;
|
|
34
|
+
/** legacy/normalised shape */
|
|
35
|
+
scanner?: string;
|
|
36
|
+
status?: string;
|
|
37
|
+
findings?: Finding[];
|
|
38
|
+
error?: string;
|
|
39
|
+
[key: string]: unknown;
|
|
40
|
+
}
|
|
41
|
+
export declare function isScannerOk(status: unknown): boolean;
|
|
42
|
+
/** Scanner display name: dags `scanner_name`, else legacy `scanner`, else unknown. */
|
|
43
|
+
export declare function scannerLabel(s: ScannerResult): string;
|
|
44
|
+
/** Headline = identifier, falling back to category, never empty (no more "(no rule)"). */
|
|
45
|
+
export declare function findingHeadline(f: Finding): string;
|
|
46
|
+
export interface FindingView {
|
|
47
|
+
scanner: string;
|
|
48
|
+
severity: string;
|
|
49
|
+
headline: string;
|
|
50
|
+
message: string;
|
|
51
|
+
location: string;
|
|
52
|
+
extras: string;
|
|
53
|
+
}
|
|
54
|
+
export interface ScannerIssue {
|
|
55
|
+
scanner: string;
|
|
56
|
+
status: string;
|
|
57
|
+
error?: string;
|
|
58
|
+
}
|
|
59
|
+
export interface ReportSummary {
|
|
60
|
+
total: number;
|
|
61
|
+
critHigh: number;
|
|
62
|
+
scannersRun: number;
|
|
63
|
+
scannersOk: number;
|
|
64
|
+
jobId?: string;
|
|
65
|
+
findings: FindingView[];
|
|
66
|
+
issues: ScannerIssue[];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Reduce a raw scan report to a render-ready summary. Pure — no I/O — so the
|
|
70
|
+
* schema-tolerance logic (the part that regressed) is unit-testable against a
|
|
71
|
+
* fixture without spying on console.log.
|
|
8
72
|
*/
|
|
73
|
+
export declare function summarizeReport(body: Record<string, unknown>): ReportSummary;
|
|
9
74
|
export declare function renderReport(body: Record<string, unknown>): void;
|
|
75
|
+
export {};
|
|
10
76
|
//# sourceMappingURL=render.d.ts.map
|
package/dist/render.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAMH,UAAU,OAAO;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACtB;AAED,UAAU,aAAa;IACtB,iBAAiB;IACjB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACtB;AAaD,wBAAgB,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAEpD;AAED,sFAAsF;AACtF,wBAAgB,YAAY,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,CAIrD;AAiBD,0FAA0F;AAC1F,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAElD;AAyED,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,YAAY;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,WAAW,EAAE,CAAA;IACvB,MAAM,EAAE,YAAY,EAAE,CAAA;CACtB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa,CA6C5E;AAID,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAwDhE"}
|
package/dist/render.js
CHANGED
|
@@ -5,8 +5,97 @@
|
|
|
5
5
|
* then by scanner, using chalk for colour.
|
|
6
6
|
*
|
|
7
7
|
* Invoked only when --json flag is NOT set.
|
|
8
|
+
*
|
|
9
|
+
* Schema tolerance
|
|
10
|
+
* ----------------
|
|
11
|
+
* The scan-worker returns the dags `ScannerResult.to_dict()` shape, NOT a
|
|
12
|
+
* normalised one (see services/extenshi-scan-worker/orchestrator + dags
|
|
13
|
+
* scanners/base_scanner.py). Concretely:
|
|
14
|
+
* - scanner objects use `scanner_name` (not `scanner`) and a lowercase
|
|
15
|
+
* `status` from the `ScanStatus` enum: `completed` / `failed` / `timeout`
|
|
16
|
+
* / `malformed_output` / `skipped` (plus the orchestrator's `error`) —
|
|
17
|
+
* never `SUCCESS`.
|
|
18
|
+
* - each scanner emits its OWN finding shape: the identifier is `rule_id`
|
|
19
|
+
* (semgrep/static_scan/yara/library_hash), `type` (jsluice/wallet_chain),
|
|
20
|
+
* `pattern` (jstap), or `id` (obfuscation); the message is `message` /
|
|
21
|
+
* `description` / `summary` / `url`; the category is `category` /
|
|
22
|
+
* `analyzer` / `kind` / `tags`; severity is mixed-case.
|
|
23
|
+
* So we read every field through a fallback chain instead of a single key —
|
|
24
|
+
* otherwise every finding renders as "(no rule)" / "[unknown]" and the
|
|
25
|
+
* success count reads 0/N (the bug this module had before).
|
|
8
26
|
*/
|
|
9
27
|
import chalk from 'chalk';
|
|
28
|
+
// ── Schema-tolerant field readers ───────────────────────────────────────────────
|
|
29
|
+
/** Statuses that count as a successful scanner run (case-insensitive). */
|
|
30
|
+
const OK_STATUSES = new Set(['completed', 'success', 'ok', 'passed']);
|
|
31
|
+
export function isScannerOk(status) {
|
|
32
|
+
return typeof status === 'string' && OK_STATUSES.has(status.toLowerCase());
|
|
33
|
+
}
|
|
34
|
+
/** Scanner display name: dags `scanner_name`, else legacy `scanner`, else unknown. */
|
|
35
|
+
export function scannerLabel(s) {
|
|
36
|
+
if (typeof s.scanner_name === 'string' && s.scanner_name.trim())
|
|
37
|
+
return s.scanner_name;
|
|
38
|
+
if (typeof s.scanner === 'string' && s.scanner.trim())
|
|
39
|
+
return s.scanner;
|
|
40
|
+
return 'unknown';
|
|
41
|
+
}
|
|
42
|
+
/** First key whose value is a non-empty string (or first element of a string array). */
|
|
43
|
+
function firstString(f, keys) {
|
|
44
|
+
for (const k of keys) {
|
|
45
|
+
const v = f[k];
|
|
46
|
+
if (typeof v === 'string' && v.trim())
|
|
47
|
+
return v;
|
|
48
|
+
if (Array.isArray(v) && typeof v[0] === 'string' && v[0].trim())
|
|
49
|
+
return v[0];
|
|
50
|
+
}
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
const HEADLINE_KEYS = ['rule', 'rule_id', 'ruleId', 'check_id', 'type', 'pattern', 'id'];
|
|
54
|
+
const MESSAGE_KEYS = ['message', 'description', 'desc', 'title', 'summary', 'url'];
|
|
55
|
+
const CATEGORY_KEYS = ['category', 'analyzer', 'kind', 'tags'];
|
|
56
|
+
const FILE_KEYS = ['file_path', 'file', 'files', 'path'];
|
|
57
|
+
/** Headline = identifier, falling back to category, never empty (no more "(no rule)"). */
|
|
58
|
+
export function findingHeadline(f) {
|
|
59
|
+
return firstString(f, HEADLINE_KEYS) ?? firstString(f, CATEGORY_KEYS) ?? 'finding';
|
|
60
|
+
}
|
|
61
|
+
function findingMessage(f) {
|
|
62
|
+
return firstString(f, MESSAGE_KEYS) ?? '';
|
|
63
|
+
}
|
|
64
|
+
function findingLocation(f) {
|
|
65
|
+
const file = firstString(f, FILE_KEYS);
|
|
66
|
+
if (!file)
|
|
67
|
+
return '';
|
|
68
|
+
const lineRaw = f.line_number ?? f.line;
|
|
69
|
+
const line = typeof lineRaw === 'number' || (typeof lineRaw === 'string' && lineRaw.trim()) ? String(lineRaw) : '';
|
|
70
|
+
return line ? `${file}:${line}` : file;
|
|
71
|
+
}
|
|
72
|
+
// Keys already surfaced via a dedicated channel — excluded from the "extras" dump.
|
|
73
|
+
const CONSUMED_KEYS = new Set([
|
|
74
|
+
...HEADLINE_KEYS,
|
|
75
|
+
...MESSAGE_KEYS,
|
|
76
|
+
...FILE_KEYS,
|
|
77
|
+
'severity',
|
|
78
|
+
'line',
|
|
79
|
+
'line_number',
|
|
80
|
+
'column',
|
|
81
|
+
'location',
|
|
82
|
+
]);
|
|
83
|
+
/** Remaining scalar fields worth showing (confidence, count, category, is_external, …). */
|
|
84
|
+
function findingExtras(f, max = 3) {
|
|
85
|
+
const parts = [];
|
|
86
|
+
for (const [k, v] of Object.entries(f)) {
|
|
87
|
+
if (CONSUMED_KEYS.has(k))
|
|
88
|
+
continue;
|
|
89
|
+
if (v === null || v === undefined)
|
|
90
|
+
continue;
|
|
91
|
+
if (typeof v === 'object')
|
|
92
|
+
continue; // skip nested dicts/arrays — too noisy for a one-liner
|
|
93
|
+
parts.push(`${k}: ${typeof v === 'string' ? v : JSON.stringify(v)}`);
|
|
94
|
+
if (parts.length >= max)
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
return parts.join(' ');
|
|
98
|
+
}
|
|
10
99
|
// ── Severity ordering ──────────────────────────────────────────────────────────
|
|
11
100
|
const SEVERITY_ORDER = {
|
|
12
101
|
CRITICAL: 0,
|
|
@@ -34,94 +123,121 @@ function severityColour(s) {
|
|
|
34
123
|
return chalk.dim(s ?? 'UNKNOWN');
|
|
35
124
|
}
|
|
36
125
|
}
|
|
37
|
-
|
|
38
|
-
|
|
126
|
+
/**
|
|
127
|
+
* Reduce a raw scan report to a render-ready summary. Pure — no I/O — so the
|
|
128
|
+
* schema-tolerance logic (the part that regressed) is unit-testable against a
|
|
129
|
+
* fixture without spying on console.log.
|
|
130
|
+
*/
|
|
131
|
+
export function summarizeReport(body) {
|
|
39
132
|
const report = body;
|
|
40
|
-
const scanners = report.scanners
|
|
41
|
-
const
|
|
133
|
+
const scanners = Array.isArray(report.scanners) ? report.scanners : [];
|
|
134
|
+
const findings = [];
|
|
135
|
+
const issues = [];
|
|
42
136
|
let scannersRun = 0;
|
|
43
137
|
let scannersOk = 0;
|
|
44
138
|
for (const s of scanners) {
|
|
45
139
|
scannersRun++;
|
|
46
|
-
if (s.status
|
|
140
|
+
if (isScannerOk(s.status)) {
|
|
47
141
|
scannersOk++;
|
|
48
142
|
}
|
|
143
|
+
else {
|
|
144
|
+
issues.push({
|
|
145
|
+
scanner: scannerLabel(s),
|
|
146
|
+
status: typeof s.status === 'string' ? s.status : 'unknown',
|
|
147
|
+
error: typeof s.error === 'string' && s.error.trim() ? s.error : undefined,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
const name = scannerLabel(s);
|
|
49
151
|
for (const f of s.findings ?? []) {
|
|
50
|
-
|
|
152
|
+
findings.push({
|
|
153
|
+
scanner: name,
|
|
154
|
+
severity: f.severity?.toUpperCase() ?? 'UNKNOWN',
|
|
155
|
+
headline: findingHeadline(f),
|
|
156
|
+
message: findingMessage(f),
|
|
157
|
+
location: findingLocation(f),
|
|
158
|
+
extras: findingExtras(f),
|
|
159
|
+
});
|
|
51
160
|
}
|
|
52
161
|
}
|
|
53
|
-
|
|
54
|
-
|
|
162
|
+
findings.sort((a, b) => severityRank(a.severity) - severityRank(b.severity));
|
|
163
|
+
const critHigh = findings.filter((f) => severityRank(f.severity) <= 1).length;
|
|
164
|
+
return {
|
|
165
|
+
total: findings.length,
|
|
166
|
+
critHigh,
|
|
167
|
+
scannersRun,
|
|
168
|
+
scannersOk,
|
|
169
|
+
jobId: typeof report.jobId === 'string' ? report.jobId : undefined,
|
|
170
|
+
findings,
|
|
171
|
+
issues,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
// ── Main render function ───────────────────────────────────────────────────────
|
|
175
|
+
export function renderReport(body) {
|
|
176
|
+
const { total, critHigh, scannersRun, scannersOk, jobId, findings, issues } = summarizeReport(body);
|
|
55
177
|
// Header
|
|
56
178
|
console.log();
|
|
57
|
-
if (
|
|
179
|
+
if (total === 0) {
|
|
58
180
|
console.log(chalk.green.bold('✓ No findings — extension looks clean.'));
|
|
59
181
|
}
|
|
60
182
|
else {
|
|
61
|
-
const
|
|
62
|
-
const label = critHigh > 0
|
|
63
|
-
? chalk.red.bold(`${allFindings.length} finding${allFindings.length !== 1 ? 's' : ''} (${critHigh} critical/high)`)
|
|
64
|
-
: chalk.yellow.bold(`${allFindings.length} finding${allFindings.length !== 1 ? 's' : ''}`);
|
|
183
|
+
const noun = `${total} finding${total !== 1 ? 's' : ''}`;
|
|
184
|
+
const label = critHigh > 0 ? chalk.red.bold(`${noun} (${critHigh} critical/high)`) : chalk.yellow.bold(noun);
|
|
65
185
|
console.log(`${chalk.bold('Scan report')} · ${label}`);
|
|
66
186
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
187
|
+
const scannersColour = scannersOk === scannersRun ? chalk.dim : chalk.yellow;
|
|
188
|
+
console.log(scannersColour(`Scanners: ${scannersOk}/${scannersRun} succeeded`));
|
|
189
|
+
if (jobId) {
|
|
190
|
+
console.log(chalk.dim(`Job: ${jobId}`));
|
|
70
191
|
}
|
|
71
192
|
console.log();
|
|
72
|
-
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
// Print findings grouped by severity (already sorted)
|
|
193
|
+
// Findings grouped by severity (already sorted)
|
|
76
194
|
let lastSeverity = '';
|
|
77
|
-
for (const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
console.log(chalk.bold(`── ${severityColour(sev)} ──────────────────────────`));
|
|
195
|
+
for (const f of findings) {
|
|
196
|
+
if (f.severity !== lastSeverity) {
|
|
197
|
+
lastSeverity = f.severity;
|
|
198
|
+
console.log(chalk.bold(`── ${severityColour(f.severity)} ──────────────────────────`));
|
|
82
199
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
// Wrap description at 80 chars
|
|
88
|
-
const words = desc.split(' ');
|
|
89
|
-
let line = ' ';
|
|
90
|
-
for (const word of words) {
|
|
91
|
-
if (line.length + word.length + 1 > 80) {
|
|
92
|
-
console.log(chalk.dim(line));
|
|
93
|
-
line = ` ${word}`;
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
line += (line === ' ' ? '' : ' ') + word;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
if (line.trim()) {
|
|
100
|
-
console.log(chalk.dim(line));
|
|
200
|
+
console.log(` ${chalk.bold(f.headline)} ${chalk.dim(`[${f.scanner}]`)}`);
|
|
201
|
+
if (f.message) {
|
|
202
|
+
for (const line of wrap(f.message, 80)) {
|
|
203
|
+
console.log(chalk.dim(` ${line}`));
|
|
101
204
|
}
|
|
102
205
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
.filter(([k]) => !skip.has(k))
|
|
107
|
-
.map(([k, v]) => `${k}: ${JSON.stringify(v)}`);
|
|
108
|
-
if (extras.length > 0) {
|
|
109
|
-
console.log(chalk.dim(` ${extras.slice(0, 3).join(' ')}`));
|
|
206
|
+
const meta = [f.location, f.extras].filter(Boolean).join(' ');
|
|
207
|
+
if (meta) {
|
|
208
|
+
console.log(chalk.dim(` ${meta}`));
|
|
110
209
|
}
|
|
111
210
|
console.log();
|
|
112
211
|
}
|
|
113
|
-
//
|
|
114
|
-
|
|
115
|
-
if (failedScanners.length > 0) {
|
|
212
|
+
// Scanners that did not complete OK (surface the error so a failure is visible)
|
|
213
|
+
if (issues.length > 0) {
|
|
116
214
|
console.log(chalk.dim('── Scanner issues ──────────────────────────'));
|
|
117
|
-
for (const
|
|
118
|
-
|
|
215
|
+
for (const i of issues) {
|
|
216
|
+
const why = i.error ? `: ${i.error}` : '';
|
|
217
|
+
console.log(chalk.dim(` ${i.scanner}: ${i.status}${why}`));
|
|
119
218
|
}
|
|
120
219
|
console.log();
|
|
121
220
|
}
|
|
122
221
|
// Exit hint
|
|
123
|
-
if (
|
|
222
|
+
if (critHigh > 0) {
|
|
124
223
|
console.log(chalk.red('⚠ Critical/high findings detected. Review before publishing.'));
|
|
125
224
|
}
|
|
126
225
|
}
|
|
226
|
+
/** Greedy word-wrap to `width` columns. */
|
|
227
|
+
function wrap(text, width) {
|
|
228
|
+
const out = [];
|
|
229
|
+
let line = '';
|
|
230
|
+
for (const word of text.split(/\s+/)) {
|
|
231
|
+
if (line && line.length + word.length + 1 > width) {
|
|
232
|
+
out.push(line);
|
|
233
|
+
line = word;
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
line = line ? `${line} ${word}` : word;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (line)
|
|
240
|
+
out.push(line);
|
|
241
|
+
return out;
|
|
242
|
+
}
|
|
127
243
|
//# sourceMappingURL=render.js.map
|
package/dist/render.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"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"}
|