@extenshi/cli 0.0.8 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.d.ts +2 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +92 -3
- package/dist/cli.js.map +1 -1
- package/dist/html-report.d.ts +44 -0
- package/dist/html-report.d.ts.map +1 -0
- package/dist/html-report.js +527 -0
- package/dist/html-report.js.map +1 -0
- package/dist/render.d.ts +22 -0
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +82 -2
- package/dist/render.js.map +1 -1
- package/dist/report.d.ts +30 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +130 -0
- package/dist/report.js.map +1 -0
- package/dist/review-archive.d.ts +29 -0
- package/dist/review-archive.d.ts.map +1 -0
- package/dist/review-archive.js +106 -0
- package/dist/review-archive.js.map +1 -0
- package/dist/review-catalog.d.ts +43 -0
- package/dist/review-catalog.d.ts.map +1 -0
- package/dist/review-catalog.js +82 -0
- package/dist/review-catalog.js.map +1 -0
- package/dist/review-checks.d.ts +139 -0
- package/dist/review-checks.d.ts.map +1 -0
- package/dist/review-checks.js +560 -0
- package/dist/review-checks.js.map +1 -0
- package/dist/review-render.d.ts +10 -0
- package/dist/review-render.d.ts.map +1 -0
- package/dist/review-render.js +94 -0
- package/dist/review-render.js.map +1 -0
- package/dist/review-risk.d.ts +29 -0
- package/dist/review-risk.d.ts.map +1 -0
- package/dist/review-risk.js +85 -0
- package/dist/review-risk.js.map +1 -0
- package/dist/scan.d.ts +82 -2
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +164 -17
- package/dist/scan.js.map +1 -1
- package/package.json +2 -1
package/dist/cli.d.ts
CHANGED
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
* ├─ auto-update check (registry, 24h cache, fail-soft)
|
|
14
14
|
* ├─ CI timeout pre-flight (GET /api/v1/healthz?delay=65, timeout 70s)
|
|
15
15
|
* └─ POST /api/v1/scan (multipart, timeout 240s)
|
|
16
|
-
* └─
|
|
16
|
+
* └─ emit findings per --format: html (branded report file, opened in
|
|
17
|
+
* the browser; default) · json (raw JSON to stdout) · stdout (pretty)
|
|
17
18
|
*/
|
|
18
19
|
export {};
|
|
19
20
|
//# sourceMappingURL=cli.d.ts.map
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;GAgBG"}
|
package/dist/cli.js
CHANGED
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
* ├─ auto-update check (registry, 24h cache, fail-soft)
|
|
14
14
|
* ├─ CI timeout pre-flight (GET /api/v1/healthz?delay=65, timeout 70s)
|
|
15
15
|
* └─ POST /api/v1/scan (multipart, timeout 240s)
|
|
16
|
-
* └─
|
|
16
|
+
* └─ emit findings per --format: html (branded report file, opened in
|
|
17
|
+
* the browser; default) · json (raw JSON to stdout) · stdout (pretty)
|
|
17
18
|
*/
|
|
18
19
|
import { createRequire } from 'node:module';
|
|
19
20
|
import * as readline from 'node:readline/promises';
|
|
@@ -21,6 +22,7 @@ import { program } from 'commander';
|
|
|
21
22
|
import { checkAutoUpdate } from './auto-update.js';
|
|
22
23
|
import { loadConfig, loadDotEnv, saveConfig } from './config.js';
|
|
23
24
|
import { runPublish } from './publish.js';
|
|
25
|
+
import { runReviewRisk } from './review-risk.js';
|
|
24
26
|
import { runScan } from './scan.js';
|
|
25
27
|
const MISSING_KEY_HELP = 'Error: API key not found.\n' +
|
|
26
28
|
'Provide it in any of these ways:\n' +
|
|
@@ -37,11 +39,16 @@ program
|
|
|
37
39
|
program
|
|
38
40
|
.command('scan <artifact>')
|
|
39
41
|
.description('Scan a browser extension artifact (.crx, .xpi, or .zip)')
|
|
40
|
-
.option('--json', 'Output
|
|
42
|
+
.option('--format <html|json|stdout>', 'Output format (default: html). html writes a branded, filterable report file and opens it in your browser; json prints raw JSON to stdout; stdout prints pretty findings in the terminal.')
|
|
43
|
+
.option('--output <path>', 'Path for the HTML report file (default: <artifact>-extenshi-report.html in the current directory; --format html only)')
|
|
44
|
+
.option('--no-open', 'Do not open the HTML report in the browser after generating it')
|
|
45
|
+
.option('--json', 'Shortcut for --format json (raw JSON to stdout)')
|
|
41
46
|
.option('--extension-id <id>', "Numeric catalog ID of a verified extension (required to spend free credits; see the Ownership tab in dojo). Paid credits don't need it.")
|
|
42
47
|
.option('--skip-preflight', 'Skip CI timeout pre-flight probe (use at your own risk)')
|
|
43
48
|
.option('--no-stream', 'Disable live progress streaming; wait for a single final JSON response')
|
|
44
49
|
.option('--api-url <url>', 'Override the scan API base URL (default: https://scan.extenshi.io)')
|
|
50
|
+
.option('--report <path>', 'Also write a formatted report file (Markdown by default; .json extension writes raw JSON). Composes with --format.')
|
|
51
|
+
.option('--report-format <md|json>', 'Force the --report file format instead of inferring from the path extension')
|
|
45
52
|
.action(async (artifact, opts) => {
|
|
46
53
|
try {
|
|
47
54
|
const config = await loadConfig(opts.apiUrl);
|
|
@@ -51,15 +58,51 @@ program
|
|
|
51
58
|
}
|
|
52
59
|
// Auto-update check (fail-soft — never blocks scan)
|
|
53
60
|
await checkAutoUpdate();
|
|
61
|
+
let reportFormat;
|
|
62
|
+
if (opts.reportFormat !== undefined) {
|
|
63
|
+
const fmt = opts.reportFormat.trim().toLowerCase();
|
|
64
|
+
if (fmt !== 'md' && fmt !== 'json') {
|
|
65
|
+
console.error('Error: --report-format must be "md" or "json".');
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
reportFormat = fmt;
|
|
69
|
+
}
|
|
70
|
+
// Resolve the primary output format. --format wins; --json is a
|
|
71
|
+
// back-compat alias for --format json; the default is html.
|
|
72
|
+
let format;
|
|
73
|
+
if (opts.format !== undefined) {
|
|
74
|
+
const f = opts.format.trim().toLowerCase();
|
|
75
|
+
if (f !== 'html' && f !== 'json' && f !== 'stdout') {
|
|
76
|
+
console.error('Error: --format must be one of: html, json, stdout.');
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
if (opts.json && f !== 'json') {
|
|
80
|
+
console.error(`Error: --json conflicts with --format ${f}. Use one or the other.`);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
format = f;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
format = opts.json ? 'json' : 'html';
|
|
87
|
+
}
|
|
88
|
+
// Auto-open the HTML report only when interactive: html format, not
|
|
89
|
+
// explicitly disabled (--no-open), and not in CI (no browser/display —
|
|
90
|
+
// the file is still written so CI can archive it as an artifact).
|
|
91
|
+
const openReport = format === 'html' && (opts.open ?? true) && !process.env.CI;
|
|
54
92
|
await runScan({
|
|
55
93
|
artifactPath: artifact,
|
|
56
94
|
apiKey: config.apiKey,
|
|
57
95
|
apiUrl: config.apiUrl,
|
|
58
96
|
extensionId: opts.extensionId,
|
|
59
|
-
|
|
97
|
+
format,
|
|
98
|
+
outputPath: opts.output,
|
|
99
|
+
openReport,
|
|
60
100
|
skipPreflight: opts.skipPreflight ?? false,
|
|
61
101
|
// commander maps --no-stream to opts.stream === false; default on.
|
|
62
102
|
stream: opts.stream ?? true,
|
|
103
|
+
reportPath: opts.report,
|
|
104
|
+
reportFormat,
|
|
105
|
+
cliVersion: pkg.version,
|
|
63
106
|
});
|
|
64
107
|
}
|
|
65
108
|
catch (err) {
|
|
@@ -117,6 +160,52 @@ program
|
|
|
117
160
|
process.exit(1);
|
|
118
161
|
}
|
|
119
162
|
});
|
|
163
|
+
program
|
|
164
|
+
.command('review-risk <artifact>')
|
|
165
|
+
.description('Predict Chrome Web Store review outcomes before publishing: what WILL BE REJECTED, ' +
|
|
166
|
+
'what triggers a SLOW manual review, and what causes user ATTRITION on update. ' +
|
|
167
|
+
'Runs fully offline; pass --extension-id to also diff against your last published manifest.')
|
|
168
|
+
.option('--extension-id <id>', 'Numeric catalog ID — enables the auto-disable diff against the last published manifest (Ownership tab in dojo)')
|
|
169
|
+
.option('--catalog-url <url>', 'Override the catalog BFF base URL (default: https://bff.extenshi.io)')
|
|
170
|
+
.option('--store <store>', 'Store to diff the manifest against: chrome | firefox | edge (default: chrome). Permission sets differ per store.')
|
|
171
|
+
.option('--json', 'Output raw JSON findings')
|
|
172
|
+
.action(async (artifact, opts) => {
|
|
173
|
+
try {
|
|
174
|
+
// Default to CHROME — this tool is Chrome-Web-Store-centric, and pinning
|
|
175
|
+
// the store avoids diffing against another store's snapshot.
|
|
176
|
+
const storeMap = {
|
|
177
|
+
chrome: 'CHROME',
|
|
178
|
+
firefox: 'FIREFOX',
|
|
179
|
+
edge: 'EDGE',
|
|
180
|
+
};
|
|
181
|
+
const store = storeMap[(opts.store ?? 'chrome').toLowerCase()];
|
|
182
|
+
if (!store) {
|
|
183
|
+
console.error('Error: --store must be one of: chrome, firefox, edge');
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
// The API key is OPTIONAL here — local checks need no network, and the
|
|
187
|
+
// manifest diff only uses the key if the catalog read path is gated.
|
|
188
|
+
const config = await loadConfig();
|
|
189
|
+
await checkAutoUpdate();
|
|
190
|
+
await runReviewRisk({
|
|
191
|
+
artifactPath: artifact,
|
|
192
|
+
extensionId: opts.extensionId,
|
|
193
|
+
bffUrl: (opts.catalogUrl ?? 'https://bff.extenshi.io').replace(/\/$/, ''),
|
|
194
|
+
apiKey: config.apiKey ?? undefined,
|
|
195
|
+
store,
|
|
196
|
+
outputJson: opts.json ?? false,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
catch (err) {
|
|
200
|
+
if (err instanceof Error) {
|
|
201
|
+
console.error(`Error: ${err.message}`);
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
console.error('Unexpected error:', err);
|
|
205
|
+
}
|
|
206
|
+
process.exit(1);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
120
209
|
program
|
|
121
210
|
.command('login')
|
|
122
211
|
.description('Save your Extenshi API key to ~/.extenshi/config.json')
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Branded, self-contained HTML report renderer for `extenshi scan --format html`.
|
|
3
|
+
*
|
|
4
|
+
* Pure (no I/O) so it is snapshot-testable — returns a complete single-file
|
|
5
|
+
* HTML document with inline CSS, inline JS, and the inline Extenshi logo. No
|
|
6
|
+
* network access, no external assets: the file opens straight from disk
|
|
7
|
+
* (file://) and works fully offline.
|
|
8
|
+
*
|
|
9
|
+
* Why this exists
|
|
10
|
+
* ---------------
|
|
11
|
+
* The terminal report repeats the same rule across dozens of files, producing a
|
|
12
|
+
* wall of near-identical lines. The HTML report DEDUPLICATES: security findings
|
|
13
|
+
* are grouped by (severity, scanner, rule) into one collapsible row carrying a
|
|
14
|
+
* count and the list of locations. On top of that it adds client-side filtering
|
|
15
|
+
* (by severity, by scanner, free-text), a sticky table of contents, and a
|
|
16
|
+
* light/dark theme toggle in the real extenshi.io palette.
|
|
17
|
+
*
|
|
18
|
+
* Schema tolerance is inherited wholesale from `summarizeReport` /
|
|
19
|
+
* `summarizeCompliance` in render.ts — this module never reads the raw scan
|
|
20
|
+
* shape directly, so it stays correct across scanner-output drift.
|
|
21
|
+
*/
|
|
22
|
+
import { type FindingView } from './render.js';
|
|
23
|
+
import { type ReportMeta } from './report.js';
|
|
24
|
+
interface FindingGroup {
|
|
25
|
+
severity: string;
|
|
26
|
+
scanner: string;
|
|
27
|
+
headline: string;
|
|
28
|
+
message: string;
|
|
29
|
+
count: number;
|
|
30
|
+
locations: string[];
|
|
31
|
+
extras: string[];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Collapse identical findings (same severity + scanner + rule headline) into one
|
|
35
|
+
* group with a count and the de-duplicated list of locations. Sorted by
|
|
36
|
+
* severity (critical first), then by count (loudest first), then headline.
|
|
37
|
+
*
|
|
38
|
+
* Dedup uses a `Set` (insertion-ordered) rather than `Array.includes` so a rule
|
|
39
|
+
* that fires thousands of times stays O(n) instead of O(n²).
|
|
40
|
+
*/
|
|
41
|
+
export declare function groupFindings(findings: FindingView[]): FindingGroup[];
|
|
42
|
+
export declare function renderHtmlReport(body: Record<string, unknown>, meta: ReportMeta): string;
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=html-report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-report.d.ts","sourceRoot":"","sources":["../src/html-report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAEN,KAAK,WAAW,EAMhB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA;AA6B7D,UAAU,YAAY;IACrB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,MAAM,EAAE,MAAM,EAAE,CAAA;CAChB;AAKD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,YAAY,EAAE,CAgDrE;AAsaD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CAqExF"}
|