@opensip-cli/tool-trivy 0.1.15

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.
@@ -0,0 +1,339 @@
1
+ /**
2
+ * Tier-2 worker E2E (ADR-0090 D6 Tier 2) — install / discover / dispatch the trivy
3
+ * adapter over a REAL forked worker, end-to-end against the BUILT CLI.
4
+ *
5
+ * Trivy is the SARIF adapter, so this also proves the shared `ingestSarif` read
6
+ * path through the FULL installed-tool dispatch:
7
+ * - the trivy package is presented as a genuinely INSTALLED npm tool in a
8
+ * throwaway project (symlinked into its `node_modules` so the worker resolves
9
+ * the adapter's workspace deps from the monorepo via realpath);
10
+ * - `OPENSIP_CLI_ALLOW_INSTALLED_TOOLS` trusts it (installed tools are
11
+ * deny-by-default);
12
+ * - a FAKE `trivy` binary on PATH makes the run deterministic: it copies the
13
+ * committed golden SARIF to `--output` and exits 0 — Trivy exits 0 EVEN WITH
14
+ * findings, so the CLI's nonzero exit comes from the findings DERIVED FROM THE
15
+ * PARSED SARIF, not from the process exit (the Trivy exit-model proof). The
16
+ * worker fork curates its env to an allow-list, so the golden path is forwarded
17
+ * via the documented `OPENSIP_CLI_TOOL_ENV_PASSTHROUGH`.
18
+ *
19
+ * `opensip trivy` forks a worker that re-discovers + imports the real runtime and
20
+ * runs the scan loop; this suite asserts the worker→host result + host-side
21
+ * effects: normalized signals match the golden (with the RECOVERED severities —
22
+ * `critical` from CVSS 9.8, not `high` from `level:"error"`), the raw SARIF
23
+ * artifact lands at `.runtime/artifacts/trivy/<runId>/trivy.sarif` with mode 0600,
24
+ * the `--json` envelope is well-formed, the session row persists with provenance,
25
+ * and the full gate ratchet (gate-save → clean compare → net-new vuln surfaces)
26
+ * works.
27
+ *
28
+ * Requires `pnpm build` first (the CLI dist + the trivy dist). Missing builds FAIL
29
+ * loudly (no silent skip).
30
+ */
31
+ import { execFileSync } from 'node:child_process';
32
+ import { cpSync, existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, statSync, symlinkSync, writeFileSync, } from 'node:fs';
33
+ import { tmpdir } from 'node:os';
34
+ import { dirname, join } from 'node:path';
35
+ import { fileURLToPath } from 'node:url';
36
+ import { afterAll, beforeAll, describe, expect, it } from 'vitest';
37
+ const HERE = dirname(fileURLToPath(import.meta.url));
38
+ // .../packages/tool-trivy/src/__tests__ → repo root is four levels up.
39
+ const REPO_ROOT = join(HERE, '..', '..', '..', '..');
40
+ const CLI_DIST = join(REPO_ROOT, 'packages', 'cli', 'dist', 'index.js');
41
+ const TRIVY_PKG_DIR = join(REPO_ROOT, 'packages', 'tool-trivy');
42
+ const FIXTURES = join(TRIVY_PKG_DIR, '__fixtures__');
43
+ const GOLDEN_PATH = join(FIXTURES, 'trivy-golden.sarif');
44
+ const TRIVY_STABLE_ID = 'a26ea0eb-ee3b-4e22-a3f3-7e1f93e16000';
45
+ const EXPECTED = JSON.parse(readFileSync(join(FIXTURES, 'expected-signals.json'), 'utf8'));
46
+ let projectDir;
47
+ let binDir;
48
+ let baseEnv;
49
+ /** Run the built CLI as a child process, capturing stdout/stderr + exit code. */
50
+ function runCli(args, extraEnv = {}, cwd = projectDir) {
51
+ try {
52
+ const stdout = execFileSync('node', [CLI_DIST, ...args], {
53
+ cwd,
54
+ env: { ...process.env, ...baseEnv, ...extraEnv },
55
+ encoding: 'utf8',
56
+ maxBuffer: 32 * 1024 * 1024,
57
+ });
58
+ return { stdout, stderr: '', status: 0 };
59
+ }
60
+ catch (error) {
61
+ const e = error;
62
+ return { stdout: e.stdout ?? '', stderr: e.stderr ?? '', status: e.status ?? 1 };
63
+ }
64
+ }
65
+ /** Scaffold a throwaway opensip-cli project that resolves the installed trivy tool. */
66
+ function makeTrivyProject() {
67
+ const dir = mkdtempSync(join(tmpdir(), 'opensip-trivy-gate-'));
68
+ writeFileSync(join(dir, 'opensip-cli.config.yml'), 'schemaVersion: 1\ntargets: {}\n', 'utf8');
69
+ const scopeDir = join(dir, 'node_modules', '@opensip-cli');
70
+ mkdirSync(scopeDir, { recursive: true });
71
+ symlinkSync(TRIVY_PKG_DIR, join(scopeDir, 'tool-trivy'), 'dir');
72
+ return dir;
73
+ }
74
+ /** Read the `--json` outcome wrapper (`{ kind, status, exitCode, envelope?, data? }`) from a run. */
75
+ function outcomeJson(run) {
76
+ return JSON.parse(run.stdout);
77
+ }
78
+ beforeAll(() => {
79
+ if (!existsSync(CLI_DIST)) {
80
+ throw new Error(`built CLI not found at ${CLI_DIST} — run \`pnpm build\` first`);
81
+ }
82
+ if (!existsSync(join(TRIVY_PKG_DIR, 'dist', 'index.js'))) {
83
+ throw new Error('built tool-trivy dist not found — run `pnpm build` first');
84
+ }
85
+ projectDir = mkdtempSync(join(tmpdir(), 'opensip-trivy-e2e-'));
86
+ // Project marker so the worker's `scope: 'project'` bootstrap resolves a project.
87
+ writeFileSync(join(projectDir, 'opensip-cli.config.yml'), 'schemaVersion: 1\ntargets: {}\n', 'utf8');
88
+ // Present the REAL trivy package as an installed npm tool. A SYMLINK (not a copy)
89
+ // so the worker resolves the adapter's `@opensip-cli/*` workspace deps from the
90
+ // monorepo via realpath — a copy would orphan them.
91
+ const scopeDir = join(projectDir, 'node_modules', '@opensip-cli');
92
+ mkdirSync(scopeDir, { recursive: true });
93
+ symlinkSync(TRIVY_PKG_DIR, join(scopeDir, 'tool-trivy'), 'dir');
94
+ // A FAKE trivy on PATH for determinism (copies the golden SARIF to --output,
95
+ // exits 0). PATH is auto-forwarded into the worker fork's curated env.
96
+ binDir = mkdtempSync(join(tmpdir(), 'opensip-trivy-bin-'));
97
+ cpSync(join(FIXTURES, 'fake-trivy'), join(binDir, 'trivy'));
98
+ execFileSync('chmod', ['+x', join(binDir, 'trivy')]);
99
+ baseEnv = {
100
+ PATH: `${binDir}:${process.env.PATH ?? ''}`,
101
+ // The committed fake binary reads the golden path from here; forward it through
102
+ // the worker fork's env allow-list via the documented passthrough.
103
+ FAKE_TRIVY_GOLDEN: GOLDEN_PATH,
104
+ OPENSIP_CLI_TOOL_ENV_PASSTHROUGH: 'FAKE_TRIVY_GOLDEN',
105
+ // Installed tools are deny-by-default — trust the trivy id (the admission check
106
+ // keys on `opensipTools.id`; the UUID is included to match the ADR-0048 stable
107
+ // id convention).
108
+ OPENSIP_CLI_ALLOW_INSTALLED_TOOLS: `${TRIVY_STABLE_ID} trivy`,
109
+ };
110
+ });
111
+ afterAll(() => {
112
+ if (projectDir !== undefined)
113
+ rmSync(projectDir, { recursive: true, force: true });
114
+ if (binDir !== undefined)
115
+ rmSync(binDir, { recursive: true, force: true });
116
+ });
117
+ describe('trivy worker E2E — opensip trivy (real forked worker)', () => {
118
+ let scan;
119
+ let envelope;
120
+ beforeAll(() => {
121
+ scan = runCli(['trivy', '--json']);
122
+ const outcome = outcomeJson(scan);
123
+ envelope = outcome.envelope;
124
+ });
125
+ it('forks a worker and emits a well-formed signal envelope for trivy', () => {
126
+ expect(envelope.tool).toBe('trivy');
127
+ expect(envelope.runId).toMatch(/^RUN_/);
128
+ // The fake binary exits 0, but the parsed SARIF has critical/high findings ⇒ the
129
+ // verdict FAILS and the CLI exits 1 (findings derived from SARIF, not exit code).
130
+ expect(envelope.verdict.passed).toBe(false);
131
+ expect(scan.status).toBe(1);
132
+ });
133
+ it('normalizes the worker SARIF output to the golden signal shapes (recovered severities)', () => {
134
+ const shapes = envelope.signals.map((s) => ({
135
+ ruleId: s.ruleId,
136
+ severity: s.severity,
137
+ message: s.message,
138
+ file: s.filePath,
139
+ line: s.line,
140
+ column: s.column,
141
+ }));
142
+ expect(shapes).toEqual(EXPECTED);
143
+ // The headline recovery: a level:"error" + security-severity:"9.8" finding is
144
+ // `critical`, NOT `high` (which level alone would give).
145
+ const certifi = envelope.signals.find((s) => s.ruleId === 'CVE-2023-37920');
146
+ expect(certifi?.severity).toBe('critical');
147
+ });
148
+ it('stamps message-hash fingerprints + provenance + recovered native severity worker-side', () => {
149
+ for (const s of envelope.signals) {
150
+ expect(s.fingerprint).toMatch(/^[0-9a-f]{64}$/);
151
+ const provenance = s.metadata.provenance;
152
+ expect(provenance.tool).toBe('trivy');
153
+ expect(provenance.adapterPackage).toBe('@opensip-cli/tool-trivy');
154
+ }
155
+ const certifi = envelope.signals.find((s) => s.ruleId === 'CVE-2023-37920');
156
+ expect(certifi?.metadata.securitySeverity).toBe('9.8');
157
+ expect(certifi?.metadata.nativeLevel).toBe('error');
158
+ const misconfig = envelope.signals.find((s) => s.ruleId === 'DS002');
159
+ expect(misconfig?.metadata.nativeLevel).toBe('warning');
160
+ });
161
+ it('lands the raw SARIF artifact under .runtime/artifacts/trivy/<runId>/trivy.sarif with mode 0600', () => {
162
+ const runDir = join(projectDir, 'opensip-cli', '.runtime', 'artifacts', 'trivy');
163
+ expect(existsSync(runDir)).toBe(true);
164
+ const runs = readdirSync(runDir);
165
+ expect(runs.length).toBeGreaterThan(0);
166
+ const artifact = join(runDir, runs[0], 'trivy.sarif');
167
+ expect(existsSync(artifact)).toBe(true);
168
+ // Owner-only read/write (0600) — the artifact carries the raw scanner output.
169
+ expect(statSync(artifact).mode & 0o777).toBe(0o600);
170
+ // The persisted artifact is the byte-preserved golden (three SARIF results).
171
+ const doc = JSON.parse(readFileSync(artifact, 'utf8'));
172
+ expect(doc.runs[0].results).toHaveLength(3);
173
+ });
174
+ it('persists a session row with the trivy tool + provenance payload', () => {
175
+ const list = runCli(['sessions', 'list', '--json']);
176
+ expect(list.status).toBe(0);
177
+ const outcome = outcomeJson(list);
178
+ const data = outcome.data;
179
+ const sessions = data?.sessions ?? [];
180
+ const trivyRow = sessions.find((s) => s.tool === 'trivy');
181
+ expect(trivyRow).toBeDefined();
182
+ expect(trivyRow?.passed).toBe(false);
183
+ const payload = trivyRow?.payload;
184
+ expect(payload?.binary?.path).toContain('trivy');
185
+ expect(payload?.findings).toBe(3);
186
+ });
187
+ });
188
+ describe('trivy worker E2E — doctor / version diagnostics', () => {
189
+ it('doctor --json reports a ready, resolved binary (exit 0)', () => {
190
+ const run = runCli(['trivy', 'doctor', '--json']);
191
+ expect(run.status).toBe(0);
192
+ const report = outcomeJson(run).data;
193
+ expect(report.tool).toBe('trivy');
194
+ expect(report.ready).toBe(true);
195
+ expect(report.binary.found).toBe(true);
196
+ expect(report.version.detected).toBe('0.50.1');
197
+ expect(report.version.status).toBe('ok');
198
+ });
199
+ it('doctor reports NOT ready (exit 2) when the resolved binary is missing', () => {
200
+ // Pin the binary to a non-existent absolute path via the env layer (which beats
201
+ // PATH and hard-misses) so resolution fails WITHOUT breaking the toolchain/worker
202
+ // fork. Forward the pin into the worker (doctor probes worker-side) via the
203
+ // documented passthrough.
204
+ const run = runCli(['trivy', 'doctor', '--json'], {
205
+ OPENSIP_TRIVY_BIN: '/nonexistent/path/to/trivy',
206
+ OPENSIP_CLI_TOOL_ENV_PASSTHROUGH: 'FAKE_TRIVY_GOLDEN OPENSIP_TRIVY_BIN',
207
+ });
208
+ expect(run.status).toBe(2);
209
+ const report = outcomeJson(run).data;
210
+ expect(report.ready).toBe(false);
211
+ expect(report.binary.found).toBe(false);
212
+ });
213
+ it('version --json prints the resolved trivy binary version', () => {
214
+ const run = runCli(['trivy', 'version', '--json']);
215
+ expect(run.status).toBe(0);
216
+ const report = outcomeJson(run).data;
217
+ expect(report.found).toBe(true);
218
+ expect(report.version).toBe('0.50.1');
219
+ });
220
+ });
221
+ describe('trivy worker E2E — installed tools are deny-by-default', () => {
222
+ it('without the trust allowlist, `opensip trivy` is not admitted', () => {
223
+ const run = runCli(['trivy', '--json'], { OPENSIP_CLI_ALLOW_INSTALLED_TOOLS: '' });
224
+ // Deny-by-default: the command never mounts (unknown command / not found), so
225
+ // the scan does NOT run.
226
+ expect(run.status).not.toBe(0);
227
+ expect(`${run.stdout}${run.stderr}`.toLowerCase()).toMatch(/unknown command|not found|trivy/);
228
+ });
229
+ });
230
+ /**
231
+ * §4.12 ratchet acceptance — the FULL baseline/gate loop over a REAL forked worker.
232
+ * The substrate wires `--gate-save` / `--gate-compare` once (ADR-0036), so the trivy
233
+ * adapter inherits it. This proves: capture a baseline → an unchanged re-scan is
234
+ * clean (exit 0) → a NET-NEW vulnerability surfaces and fails (exit ≠ 0).
235
+ *
236
+ * Runs in its OWN throwaway project so the baseline + sessions are isolated from the
237
+ * scan suites above. The fake binary copies `FAKE_TRIVY_GOLDEN` to `--output`;
238
+ * pointing it at an AUGMENTED golden (the three originals + one new SARIF result +
239
+ * rule) is how the "regression" run injects a net-new finding.
240
+ */
241
+ describe('trivy worker E2E — full gate ratchet (§4.12)', () => {
242
+ let gateProject;
243
+ let augmentedGolden;
244
+ let save;
245
+ let compareClean;
246
+ let compareRegressed;
247
+ beforeAll(() => {
248
+ gateProject = makeTrivyProject();
249
+ // The augmented golden = the committed three findings + one NET-NEW SARIF result
250
+ // (a distinct ruleId/message ⇒ a distinct message-hash fingerprint ⇒ the ratchet
251
+ // sees it as net-new, not unchanged). A matching rule descriptor carries its CVSS.
252
+ const original = JSON.parse(readFileSync(GOLDEN_PATH, 'utf8'));
253
+ const run0 = original.runs[0];
254
+ run0.tool.driver.rules.push({
255
+ id: 'CVE-2024-99999',
256
+ name: 'LanguageSpecificPackageVulnerability',
257
+ shortDescription: { text: 'axios: Server-Side Request Forgery' },
258
+ helpUri: 'https://avd.aquasec.com/nvd/cve-2024-99999',
259
+ defaultConfiguration: { level: 'error' },
260
+ properties: { 'security-severity': '8.6', tags: ['vulnerability', 'security', 'HIGH'] },
261
+ });
262
+ run0.results.push({
263
+ ruleId: 'CVE-2024-99999',
264
+ ruleIndex: 3,
265
+ level: 'error',
266
+ message: { text: 'axios: Server-Side Request Forgery' },
267
+ locations: [
268
+ {
269
+ physicalLocation: {
270
+ artifactLocation: { uri: 'requirements.txt', uriBaseId: 'ROOTPATH' },
271
+ region: { startLine: 1, startColumn: 1 },
272
+ },
273
+ },
274
+ ],
275
+ });
276
+ augmentedGolden = join(gateProject, 'augmented-golden.sarif');
277
+ writeFileSync(augmentedGolden, JSON.stringify(original), 'utf8');
278
+ // 1) Capture the baseline (three findings). The findings gate (ADR-0020) makes
279
+ // gate-save itself exit 1 — it records the baseline AND honours the verdict.
280
+ save = runCli(['trivy', '--gate-save'], {}, gateProject);
281
+ // 2) Re-scan the SAME golden and compare → no net-new ⇒ clean (exit 0).
282
+ compareClean = runCli(['trivy', '--gate-compare'], {}, gateProject);
283
+ // 3) Compare against the augmented golden → one net-new finding ⇒ degraded.
284
+ compareRegressed = runCli(['trivy', '--gate-compare'], { FAKE_TRIVY_GOLDEN: augmentedGolden }, gateProject);
285
+ });
286
+ afterAll(() => {
287
+ if (gateProject !== undefined)
288
+ rmSync(gateProject, { recursive: true, force: true });
289
+ });
290
+ it('--gate-save records the baseline and persists a session', () => {
291
+ // The findings gate makes gate-save exit 1 (critical/high findings present), but
292
+ // the baseline IS written — proven by the clean compare below.
293
+ expect(save.status).toBe(1);
294
+ const list = runCli(['sessions', 'list', '--json'], {}, gateProject);
295
+ const data = outcomeJson(list).data;
296
+ const trivyRows = (data.sessions ?? []).filter((s) => s.tool === 'trivy');
297
+ expect(trivyRows.length).toBeGreaterThanOrEqual(1);
298
+ });
299
+ it('--gate-compare on the SAME scan is a clean no-op (exit 0, no regression)', () => {
300
+ // Pre-existing findings recorded in the baseline are NOT a regression — only
301
+ // net-new findings fail the ratchet. The clean exit also proves gate-save wrote
302
+ // the baseline (the missing-baseline → exit 2 contract is asserted directly in
303
+ // the "typed exit-class survives the worker boundary" suite below).
304
+ expect(compareRegressed).toBeDefined();
305
+ expect(compareClean.status).toBe(0);
306
+ expect(`${compareClean.stdout}${compareClean.stderr}`).toMatch(/STABLE|no change/i);
307
+ });
308
+ it('--gate-compare surfaces a NET-NEW vulnerability and exits non-zero (degraded)', () => {
309
+ expect(compareRegressed.status).not.toBe(0);
310
+ const out = `${compareRegressed.stdout}${compareRegressed.stderr}`;
311
+ // The net-new advisory is named in the diff; the verdict footer says DEGRADED.
312
+ expect(out).toContain('CVE-2024-99999');
313
+ expect(out).toMatch(/DEGRADED|Added/i);
314
+ });
315
+ });
316
+ /**
317
+ * A5/A6 — the typed exit-class must survive the worker boundary on the host-RPC
318
+ * REJECT path too. `--gate-compare` with NO saved baseline makes the host
319
+ * `compareBaseline` seam reject with a ConfigurationError (BASELINE_MISSING). That
320
+ * rejection crosses the worker IPC as a structured reply; before the fix the worker
321
+ * shim rebuilt a PLAIN Error → SystemError → exit 1, silently losing the frozen
322
+ * exit-2 config contract. This asserts the contract end-to-end over a REAL fork.
323
+ */
324
+ describe('trivy worker E2E — gate-compare with no baseline exits 2 (A5/A6)', () => {
325
+ it('`opensip trivy --gate-compare` before any --gate-save exits 2 (not 1)', () => {
326
+ // A fresh project with NO baseline captured: the compareBaseline host seam
327
+ // rejects ConfigurationError(BASELINE_MISSING) over the host-RPC channel.
328
+ const freshProject = makeTrivyProject();
329
+ try {
330
+ const run = runCli(['trivy', '--gate-compare'], {}, freshProject);
331
+ expect(run.status).toBe(2);
332
+ expect(`${run.stdout}${run.stderr}`).toMatch(/baseline|gate-save/i);
333
+ }
334
+ finally {
335
+ rmSync(freshProject, { recursive: true, force: true });
336
+ }
337
+ });
338
+ });
339
+ //# sourceMappingURL=worker-e2e.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-e2e.test.js","sourceRoot":"","sources":["../../src/__tests__/worker-e2e.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * `@opensip-cli/tool-trivy` public barrel.
3
+ *
4
+ * Re-exports the `tool` descriptor the host loads by name through the installed
5
+ * external-tool worker-dispatch path (`mod.tool`), plus a `default` alias and the
6
+ * identity/stable-id constants. There is NO per-adapter SARIF parser: Trivy routes
7
+ * its SARIF output through the substrate's shared `ingestSarif` (the single SARIF
8
+ * read path, ADR-0091). The adapter internals are otherwise not public API.
9
+ */
10
+ export { tool, tool as default, TRIVY_IDENTITY, TRIVY_STABLE_ID } from './tool.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,IAAI,EAAE,IAAI,IAAI,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * `@opensip-cli/tool-trivy` public barrel.
3
+ *
4
+ * Re-exports the `tool` descriptor the host loads by name through the installed
5
+ * external-tool worker-dispatch path (`mod.tool`), plus a `default` alias and the
6
+ * identity/stable-id constants. There is NO per-adapter SARIF parser: Trivy routes
7
+ * its SARIF output through the substrate's shared `ingestSarif` (the single SARIF
8
+ * read path, ADR-0091). The adapter internals are otherwise not public API.
9
+ */
10
+ export { tool, tool as default, TRIVY_IDENTITY, TRIVY_STABLE_ID } from './tool.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,IAAI,EAAE,IAAI,IAAI,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC"}
package/dist/tool.d.ts ADDED
@@ -0,0 +1,87 @@
1
+ /**
2
+ * `@opensip-cli/tool-trivy` Tool descriptor (ADR-0090 / ADR-0091 / ADR-0092).
3
+ *
4
+ * The third External Tool Adapter — and the FIRST real consumer of the substrate's
5
+ * shared `ingestSarif`. It wraps the user-installed `trivy` vulnerability +
6
+ * misconfiguration scanner as an ordinary opensip-cli `Tool` via {@link
7
+ * defineExternalToolAdapter}. The substrate owns binary resolution, the run loop
8
+ * (resolve → execFile → ingest → normalize → persist via the host artifact seam),
9
+ * provenance, and the auto-added `doctor`/`version` commands; this module declares
10
+ * only the trivy identity, the wrapped binary, and the `scan` command (args only).
11
+ *
12
+ * Unlike gitleaks/osv-scanner (JSON adapters with a per-adapter `parse`), Trivy is
13
+ * the SARIF adapter: its `scan` command declares `output: { kind: 'sarif' }` and
14
+ * OMITS `parse`. The substrate's shared `ingestSarif` reads the SARIF 2.1.0 log,
15
+ * recovering each finding's four-bucket severity from the rule descriptor's
16
+ * `properties["security-severity"]` (a CVSS number) BEFORE the lossy `level`
17
+ * fallback (the OpenSIP SARIF writer collapses critical AND high → `error`, so a
18
+ * `9.8` result with `level:"error"` must normalize to `critical`, not `high`).
19
+ *
20
+ * Layer 4: imports the substrate + `@opensip-cli/core` ONLY — never the CLI,
21
+ * output, or any other adapter (dependency-cruiser enforced). The
22
+ * `single-sarif-ingest` rule means this adapter MUST NOT parse SARIF itself; it
23
+ * relies on the one substrate reader.
24
+ *
25
+ * This is an OPT-IN, installed tool (NOT in `bundled-tools.manifest.json`): the
26
+ * host never imports this runtime; an `opensip trivy` invocation forks a worker
27
+ * that re-discovers + imports it and runs the handler. Installed tools are
28
+ * deny-by-default — a run needs `OPENSIP_CLI_ALLOW_INSTALLED_TOOLS` to include the
29
+ * trivy id.
30
+ */
31
+ import type { Tool, ToolIdentity } from '@opensip-cli/core';
32
+ import type { AdapterRunContext } from '@opensip-cli/external-tool-adapter';
33
+ /** Human identity (`opensip trivy`). No aliases. */
34
+ export declare const TRIVY_IDENTITY: ToolIdentity;
35
+ /** Stable UUID identity (ADR-0048); mirrors `opensipTools.stableId` in package.json. */
36
+ export declare const TRIVY_STABLE_ID = "a26ea0eb-ee3b-4e22-a3f3-7e1f93e16000";
37
+ /**
38
+ * Normalize the `trivy --version` stdout to a bare semver. Trivy prints a
39
+ * multi-line banner whose first line is e.g. `Version: 0.50.1` (followed by the
40
+ * vulnerability/Java DB metadata); take the first semver-shaped token and strip a
41
+ * leading `v`.
42
+ *
43
+ * VERIFY-against-installed-binary: exact `trivy --version` output format.
44
+ */
45
+ export declare function parseTrivyVersion(stdout: string): string;
46
+ /**
47
+ * Build the trivy scan argv (no shell — args are passed to `execFile`). Scans the
48
+ * project filesystem (`fs <root>`) for vulnerabilities + secrets + misconfigurations
49
+ * and writes a SARIF 2.1.0 report to the host-owned artifact path the substrate
50
+ * composes for this run.
51
+ *
52
+ * Scanner selection (A8): `trivy fs` defaults to `vuln,secret` ONLY — misconfig is
53
+ * OFF unless requested. The adapter advertises misconfig (metadata, docs, the DS002
54
+ * golden), so it MUST pass `--scanners vuln,secret,misconfig` or a real run would
55
+ * silently emit zero misconfig findings while the fixtures assert them. VERIFY-
56
+ * against-installed-trivy: the `--scanners` value set + name across versions.
57
+ *
58
+ * Local-only posture (ADR-0092): Trivy fetches its vulnerability DB from GHCR on
59
+ * first run, so the scan is pinned offline with `--skip-db-update`,
60
+ * `--skip-java-db-update`, `--offline-scan`, and — because the misconfig scanner
61
+ * pulls a separate "checks" bundle from GHCR — `--skip-check-update`. This REQUIRES
62
+ * a pre-populated cache (the vuln DB AND, for misconfig, the checks bundle); the
63
+ * adapter's `doctor`/`installHint` notes the cache caveat.
64
+ *
65
+ * VERIFY-against-installed-binary: the local-only flag set across versions.
66
+ * Trivy is NOT passed `--exit-code` — it exits 0 even with findings, and the
67
+ * substrate derives findings from the parsed SARIF (any nonzero is a fault).
68
+ */
69
+ export declare function buildScanArgs(ctx: AdapterRunContext): readonly string[];
70
+ /**
71
+ * A3: build trivy's exclusion of opensip's own `.runtime` artifact store. Trivy
72
+ * takes a directory skip via `--skip-dirs`; the substrate supplies the path and
73
+ * the run loop appends the flag (no user-facing flag, so the command manifest is
74
+ * unchanged). VERIFY-against-installed-binary: `--skip-dirs` accepts an absolute
75
+ * path / glob and may be passed after the positional scan root.
76
+ */
77
+ export declare function buildTrivyExclude(input: {
78
+ readonly excludePath: string;
79
+ }): {
80
+ readonly args: readonly string[];
81
+ };
82
+ /**
83
+ * The trivy external-tool adapter `Tool`. The host loads it by name through the
84
+ * installed-tool worker-dispatch path (the barrel re-exports it as `tool`).
85
+ */
86
+ export declare const tool: Tool;
87
+ //# sourceMappingURL=tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../src/tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAKH,OAAO,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAE5E,oDAAoD;AACpD,eAAO,MAAM,cAAc,EAAE,YAE5B,CAAC;AAEF,wFAAwF;AACxF,eAAO,MAAM,eAAe,yCAAyC,CAAC;AAEtE;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKxD;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,iBAAiB,GAAG,SAAS,MAAM,EAAE,CAevE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IAAE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG;IAC1E,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC,CAEA;AAED;;;GAGG;AACH,eAAO,MAAM,IAAI,EAAE,IA8CjB,CAAC"}
package/dist/tool.js ADDED
@@ -0,0 +1,152 @@
1
+ /**
2
+ * `@opensip-cli/tool-trivy` Tool descriptor (ADR-0090 / ADR-0091 / ADR-0092).
3
+ *
4
+ * The third External Tool Adapter — and the FIRST real consumer of the substrate's
5
+ * shared `ingestSarif`. It wraps the user-installed `trivy` vulnerability +
6
+ * misconfiguration scanner as an ordinary opensip-cli `Tool` via {@link
7
+ * defineExternalToolAdapter}. The substrate owns binary resolution, the run loop
8
+ * (resolve → execFile → ingest → normalize → persist via the host artifact seam),
9
+ * provenance, and the auto-added `doctor`/`version` commands; this module declares
10
+ * only the trivy identity, the wrapped binary, and the `scan` command (args only).
11
+ *
12
+ * Unlike gitleaks/osv-scanner (JSON adapters with a per-adapter `parse`), Trivy is
13
+ * the SARIF adapter: its `scan` command declares `output: { kind: 'sarif' }` and
14
+ * OMITS `parse`. The substrate's shared `ingestSarif` reads the SARIF 2.1.0 log,
15
+ * recovering each finding's four-bucket severity from the rule descriptor's
16
+ * `properties["security-severity"]` (a CVSS number) BEFORE the lossy `level`
17
+ * fallback (the OpenSIP SARIF writer collapses critical AND high → `error`, so a
18
+ * `9.8` result with `level:"error"` must normalize to `critical`, not `high`).
19
+ *
20
+ * Layer 4: imports the substrate + `@opensip-cli/core` ONLY — never the CLI,
21
+ * output, or any other adapter (dependency-cruiser enforced). The
22
+ * `single-sarif-ingest` rule means this adapter MUST NOT parse SARIF itself; it
23
+ * relies on the one substrate reader.
24
+ *
25
+ * This is an OPT-IN, installed tool (NOT in `bundled-tools.manifest.json`): the
26
+ * host never imports this runtime; an `opensip trivy` invocation forks a worker
27
+ * that re-discovers + imports it and runs the handler. Installed tools are
28
+ * deny-by-default — a run needs `OPENSIP_CLI_ALLOW_INSTALLED_TOOLS` to include the
29
+ * trivy id.
30
+ */
31
+ import { readPackageVersion } from '@opensip-cli/core';
32
+ import { defineExternalToolAdapter } from '@opensip-cli/external-tool-adapter';
33
+ /** Human identity (`opensip trivy`). No aliases. */
34
+ export const TRIVY_IDENTITY = {
35
+ name: 'trivy',
36
+ };
37
+ /** Stable UUID identity (ADR-0048); mirrors `opensipTools.stableId` in package.json. */
38
+ export const TRIVY_STABLE_ID = 'a26ea0eb-ee3b-4e22-a3f3-7e1f93e16000';
39
+ /**
40
+ * Normalize the `trivy --version` stdout to a bare semver. Trivy prints a
41
+ * multi-line banner whose first line is e.g. `Version: 0.50.1` (followed by the
42
+ * vulnerability/Java DB metadata); take the first semver-shaped token and strip a
43
+ * leading `v`.
44
+ *
45
+ * VERIFY-against-installed-binary: exact `trivy --version` output format.
46
+ */
47
+ export function parseTrivyVersion(stdout) {
48
+ // Fully bounded ({1,5} digit runs, {1,2} dotted segments) so the matcher is
49
+ // linear — major.minor[.patch], optional leading `v`.
50
+ const match = /v?(\d{1,5}(?:\.\d{1,5}){1,2})/.exec(stdout);
51
+ return match?.[1] ?? stdout.trim();
52
+ }
53
+ /**
54
+ * Build the trivy scan argv (no shell — args are passed to `execFile`). Scans the
55
+ * project filesystem (`fs <root>`) for vulnerabilities + secrets + misconfigurations
56
+ * and writes a SARIF 2.1.0 report to the host-owned artifact path the substrate
57
+ * composes for this run.
58
+ *
59
+ * Scanner selection (A8): `trivy fs` defaults to `vuln,secret` ONLY — misconfig is
60
+ * OFF unless requested. The adapter advertises misconfig (metadata, docs, the DS002
61
+ * golden), so it MUST pass `--scanners vuln,secret,misconfig` or a real run would
62
+ * silently emit zero misconfig findings while the fixtures assert them. VERIFY-
63
+ * against-installed-trivy: the `--scanners` value set + name across versions.
64
+ *
65
+ * Local-only posture (ADR-0092): Trivy fetches its vulnerability DB from GHCR on
66
+ * first run, so the scan is pinned offline with `--skip-db-update`,
67
+ * `--skip-java-db-update`, `--offline-scan`, and — because the misconfig scanner
68
+ * pulls a separate "checks" bundle from GHCR — `--skip-check-update`. This REQUIRES
69
+ * a pre-populated cache (the vuln DB AND, for misconfig, the checks bundle); the
70
+ * adapter's `doctor`/`installHint` notes the cache caveat.
71
+ *
72
+ * VERIFY-against-installed-binary: the local-only flag set across versions.
73
+ * Trivy is NOT passed `--exit-code` — it exits 0 even with findings, and the
74
+ * substrate derives findings from the parsed SARIF (any nonzero is a fault).
75
+ */
76
+ export function buildScanArgs(ctx) {
77
+ return [
78
+ 'fs',
79
+ '--scanners',
80
+ 'vuln,secret,misconfig',
81
+ '--format',
82
+ 'sarif',
83
+ '--output',
84
+ ctx.artifactPath('trivy.sarif'),
85
+ '--skip-db-update',
86
+ '--skip-java-db-update',
87
+ '--offline-scan',
88
+ '--skip-check-update',
89
+ ctx.projectRoot,
90
+ ];
91
+ }
92
+ /**
93
+ * A3: build trivy's exclusion of opensip's own `.runtime` artifact store. Trivy
94
+ * takes a directory skip via `--skip-dirs`; the substrate supplies the path and
95
+ * the run loop appends the flag (no user-facing flag, so the command manifest is
96
+ * unchanged). VERIFY-against-installed-binary: `--skip-dirs` accepts an absolute
97
+ * path / glob and may be passed after the positional scan root.
98
+ */
99
+ export function buildTrivyExclude(input) {
100
+ return { args: ['--skip-dirs', input.excludePath] };
101
+ }
102
+ /**
103
+ * The trivy external-tool adapter `Tool`. The host loads it by name through the
104
+ * installed-tool worker-dispatch path (the barrel re-exports it as `tool`).
105
+ */
106
+ export const tool = defineExternalToolAdapter({
107
+ identity: TRIVY_IDENTITY,
108
+ metadata: {
109
+ id: TRIVY_STABLE_ID,
110
+ version: readPackageVersion(import.meta.url),
111
+ description: 'Vulnerability + misconfig scanning via Trivy',
112
+ adapterPackage: '@opensip-cli/tool-trivy',
113
+ },
114
+ binary: {
115
+ command: 'trivy',
116
+ versionArgs: ['--version'],
117
+ versionParse: parseTrivyVersion,
118
+ // `trivy fs --format sarif --output` is stable from 0.40. VERIFY-against-
119
+ // installed-binary (the local-only flag names have shifted across versions).
120
+ minVersion: '0.40.0',
121
+ // Operator pin (config `binaries.trivy.path` / `OPENSIP_TRIVY_BIN`) beats
122
+ // PATH; resolution never fetches a binary.
123
+ resolution: ['config', 'path'],
124
+ installHint: 'Install trivy: https://aquasecurity.github.io/trivy/latest/getting-started/installation/ (brew install trivy). Pre-populate the offline caches: the vuln DB (e.g. `trivy image --download-db-only`) AND, for misconfiguration scanning, the checks bundle (e.g. run `trivy fs .` once online so the misconfig checks are cached).',
125
+ },
126
+ // Trivy queries its LOCAL vuln DB cache via execFile with --offline-scan — no
127
+ // network, no credentials at scan time (the DB cache must be pre-populated).
128
+ network: 'local-only',
129
+ commands: [
130
+ {
131
+ name: 'scan',
132
+ description: 'Scan the project filesystem for vulnerabilities and misconfigurations (Trivy)',
133
+ args: buildScanArgs,
134
+ // SARIF adapter: no `parse` — the substrate's shared `ingestSarif` reads it,
135
+ // recovering severity from `driver.rules[ruleIndex].properties["security-severity"]`.
136
+ output: { kind: 'sarif', path: 'trivy.sarif' },
137
+ // A3: never re-walk opensip's own persisted reports under `.runtime/` (see
138
+ // {@link buildTrivyExclude}).
139
+ excludeScan: buildTrivyExclude,
140
+ // ADR-0091 Phase-0 decision 4 (Trivy): Trivy exits `0` even WITH findings (no
141
+ // `--exit-code` passed), so findings are derived from the parsed SARIF, not the
142
+ // exit code. Only `0` is clean; there is NO findings code; any nonzero (>= 1)
143
+ // is a genuine fault. (Passing `--exit-code 1` would collide findings-1 with
144
+ // error-1 — the gitleaks sharp edge — so it is deliberately omitted.)
145
+ exitCodes: { ok: [0], findings: [], errorFrom: 1 },
146
+ },
147
+ ],
148
+ // Scanner output is line-volatile → the line-shift-tolerant message hash, not the
149
+ // host `ruleId|file|line|col` default. Stamped worker-side in the run loop.
150
+ fingerprintStrategy: 'message-hash',
151
+ });
152
+ //# sourceMappingURL=tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool.js","sourceRoot":"","sources":["../src/tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAK/E,oDAAoD;AACpD,MAAM,CAAC,MAAM,cAAc,GAAiB;IAC1C,IAAI,EAAE,OAAO;CACd,CAAC;AAEF,wFAAwF;AACxF,MAAM,CAAC,MAAM,eAAe,GAAG,sCAAsC,CAAC;AAEtE;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,4EAA4E;IAC5E,sDAAsD;IACtD,MAAM,KAAK,GAAG,+BAA+B,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3D,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;AACrC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,aAAa,CAAC,GAAsB;IAClD,OAAO;QACL,IAAI;QACJ,YAAY;QACZ,uBAAuB;QACvB,UAAU;QACV,OAAO;QACP,UAAU;QACV,GAAG,CAAC,YAAY,CAAC,aAAa,CAAC;QAC/B,kBAAkB;QAClB,uBAAuB;QACvB,gBAAgB;QAChB,qBAAqB;QACrB,GAAG,CAAC,WAAW;KAChB,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAuC;IAGvE,OAAO,EAAE,IAAI,EAAE,CAAC,aAAa,EAAE,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;AACtD,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,IAAI,GAAS,yBAAyB,CAAC;IAClD,QAAQ,EAAE,cAAc;IACxB,QAAQ,EAAE;QACR,EAAE,EAAE,eAAe;QACnB,OAAO,EAAE,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;QAC5C,WAAW,EAAE,8CAA8C;QAC3D,cAAc,EAAE,yBAAyB;KAC1C;IACD,MAAM,EAAE;QACN,OAAO,EAAE,OAAO;QAChB,WAAW,EAAE,CAAC,WAAW,CAAC;QAC1B,YAAY,EAAE,iBAAiB;QAC/B,0EAA0E;QAC1E,6EAA6E;QAC7E,UAAU,EAAE,QAAQ;QACpB,0EAA0E;QAC1E,2CAA2C;QAC3C,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC9B,WAAW,EACT,mUAAmU;KACtU;IACD,8EAA8E;IAC9E,6EAA6E;IAC7E,OAAO,EAAE,YAAY;IACrB,QAAQ,EAAE;QACR;YACE,IAAI,EAAE,MAAM;YACZ,WAAW,EAAE,+EAA+E;YAC5F,IAAI,EAAE,aAAa;YACnB,6EAA6E;YAC7E,sFAAsF;YACtF,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE;YAC9C,2EAA2E;YAC3E,8BAA8B;YAC9B,WAAW,EAAE,iBAAiB;YAC9B,8EAA8E;YAC9E,gFAAgF;YAChF,8EAA8E;YAC9E,6EAA6E;YAC7E,sEAAsE;YACtE,SAAS,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE;SACnD;KACF;IACD,kFAAkF;IAClF,4EAA4E;IAC5E,mBAAmB,EAAE,cAAc;CACpC,CAAC,CAAC"}