@xenos1996/usa 2.27.0 → 2.28.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-help.d.ts.map +1 -1
- package/dist/cli-help.js +2 -0
- package/dist/cli-help.js.map +1 -1
- package/dist/cli-intent.d.ts +4 -0
- package/dist/cli-intent.d.ts.map +1 -0
- package/dist/cli-intent.js +108 -0
- package/dist/cli-intent.js.map +1 -0
- package/dist/cli-scan.d.ts +12 -0
- package/dist/cli-scan.d.ts.map +1 -0
- package/dist/cli-scan.js +142 -0
- package/dist/cli-scan.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +4 -0
- package/dist/cli.js.map +1 -1
- package/dist/engine/evaluate.d.ts.map +1 -1
- package/dist/engine/evaluate.js +31 -8
- package/dist/engine/evaluate.js.map +1 -1
- package/dist/intent/match.d.ts +38 -0
- package/dist/intent/match.d.ts.map +1 -0
- package/dist/intent/match.js +108 -0
- package/dist/intent/match.js.map +1 -0
- package/dist/intent/otm.d.ts +16 -0
- package/dist/intent/otm.d.ts.map +1 -0
- package/dist/intent/otm.js +144 -0
- package/dist/intent/otm.js.map +1 -0
- package/dist/intent/types.d.ts +111 -0
- package/dist/intent/types.d.ts.map +1 -0
- package/dist/intent/types.js +16 -0
- package/dist/intent/types.js.map +1 -0
- package/dist/scanner/adapters/codeql.d.ts +14 -0
- package/dist/scanner/adapters/codeql.d.ts.map +1 -0
- package/dist/scanner/adapters/codeql.js +134 -0
- package/dist/scanner/adapters/codeql.js.map +1 -0
- package/dist/scanner/adapters/dependency-cruiser.d.ts +3 -0
- package/dist/scanner/adapters/dependency-cruiser.d.ts.map +1 -0
- package/dist/scanner/adapters/dependency-cruiser.js +174 -0
- package/dist/scanner/adapters/dependency-cruiser.js.map +1 -0
- package/dist/scanner/adapters/ort.d.ts +12 -0
- package/dist/scanner/adapters/ort.d.ts.map +1 -0
- package/dist/scanner/adapters/ort.js +259 -0
- package/dist/scanner/adapters/ort.js.map +1 -0
- package/dist/scanner/adapters/scorecard.d.ts +7 -0
- package/dist/scanner/adapters/scorecard.d.ts.map +1 -0
- package/dist/scanner/adapters/scorecard.js +209 -0
- package/dist/scanner/adapters/scorecard.js.map +1 -0
- package/dist/scanner/adapters/semgrep.d.ts +3 -0
- package/dist/scanner/adapters/semgrep.d.ts.map +1 -0
- package/dist/scanner/adapters/semgrep.js +163 -0
- package/dist/scanner/adapters/semgrep.js.map +1 -0
- package/dist/scanner/adapters/trivy.d.ts +3 -0
- package/dist/scanner/adapters/trivy.d.ts.map +1 -0
- package/dist/scanner/adapters/trivy.js +163 -0
- package/dist/scanner/adapters/trivy.js.map +1 -0
- package/dist/scanner/config.d.ts +4 -0
- package/dist/scanner/config.d.ts.map +1 -0
- package/dist/scanner/config.js +15 -0
- package/dist/scanner/config.js.map +1 -0
- package/dist/scanner/identity.d.ts +17 -0
- package/dist/scanner/identity.d.ts.map +1 -0
- package/dist/scanner/identity.js +50 -0
- package/dist/scanner/identity.js.map +1 -0
- package/dist/scanner/normalize.d.ts +40 -0
- package/dist/scanner/normalize.d.ts.map +1 -0
- package/dist/scanner/normalize.js +85 -0
- package/dist/scanner/normalize.js.map +1 -0
- package/dist/scanner/registry.d.ts +19 -0
- package/dist/scanner/registry.d.ts.map +1 -0
- package/dist/scanner/registry.js +43 -0
- package/dist/scanner/registry.js.map +1 -0
- package/dist/scanner/run.d.ts +70 -0
- package/dist/scanner/run.d.ts.map +1 -0
- package/dist/scanner/run.js +419 -0
- package/dist/scanner/run.js.map +1 -0
- package/dist/scanner/sarif.d.ts +21 -0
- package/dist/scanner/sarif.d.ts.map +1 -0
- package/dist/scanner/sarif.js +156 -0
- package/dist/scanner/sarif.js.map +1 -0
- package/dist/scanner/types.d.ts +236 -0
- package/dist/scanner/types.d.ts.map +1 -0
- package/dist/scanner/types.js +11 -0
- package/dist/scanner/types.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one place a scanner process is started.
|
|
3
|
+
*
|
|
4
|
+
* Every execution policy — timeout, output bound, scratch working directory,
|
|
5
|
+
* environment deny-list, network policy, refusal to run build commands — lives
|
|
6
|
+
* here and nowhere else. Adapters describe *what* to run; the runner decides
|
|
7
|
+
* whether and how it may run.
|
|
8
|
+
*/
|
|
9
|
+
import { spawnSync } from 'node:child_process';
|
|
10
|
+
import fs from 'node:fs';
|
|
11
|
+
import path from 'node:path';
|
|
12
|
+
import os from 'node:os';
|
|
13
|
+
import { randomUUID } from 'node:crypto';
|
|
14
|
+
export const DEFAULT_TIMEOUT_MS = 300_000;
|
|
15
|
+
export const OUTPUT_CAP_BYTES = 20 * 1024 * 1024;
|
|
16
|
+
/** Env vars stripped from every scanner child process (no credential leakage). */
|
|
17
|
+
const ENV_ALLOW = ['HOME', 'PATH', 'LANG', 'LC_ALL', 'TMPDIR', 'https_proxy', 'http_proxy'];
|
|
18
|
+
const ENV_DENY = [
|
|
19
|
+
'GITHUB_TOKEN',
|
|
20
|
+
'GH_TOKEN',
|
|
21
|
+
'NODE_AUTH_TOKEN',
|
|
22
|
+
'NPM_TOKEN',
|
|
23
|
+
'NPM_CONFIG_REGISTRY',
|
|
24
|
+
'NPM_CONFIG_USERCONFIG',
|
|
25
|
+
'SEMGREP_APP_TOKEN',
|
|
26
|
+
'SNYK_TOKEN',
|
|
27
|
+
'GPR_TOKEN',
|
|
28
|
+
'AWS_SECRET_ACCESS_KEY',
|
|
29
|
+
'AWS_SESSION_TOKEN',
|
|
30
|
+
];
|
|
31
|
+
/**
|
|
32
|
+
* The environment a scanner child inherits: an allow-list, then a deny-list
|
|
33
|
+
* applied over it. A scanner gets PATH and TMPDIR and nothing that carries a
|
|
34
|
+
* credential — that is the whole point of the deny list existing.
|
|
35
|
+
*/
|
|
36
|
+
export function childEnv(allow) {
|
|
37
|
+
const env = {};
|
|
38
|
+
for (const key of allow) {
|
|
39
|
+
const v = process.env[key];
|
|
40
|
+
if (v !== undefined && !ENV_DENY.includes(key))
|
|
41
|
+
env[key] = v;
|
|
42
|
+
}
|
|
43
|
+
return env;
|
|
44
|
+
}
|
|
45
|
+
export class ScannerRunner {
|
|
46
|
+
adapters;
|
|
47
|
+
constructor(adapters) {
|
|
48
|
+
this.adapters = adapters;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Run the selected adapters and return the manifest plus what they found.
|
|
52
|
+
* `options.adapters` filters the registry; an unknown id is a loud error
|
|
53
|
+
* rather than an empty run, because "0 evidence" must never be mistaken for
|
|
54
|
+
* "nothing wrong".
|
|
55
|
+
*/
|
|
56
|
+
run(options) {
|
|
57
|
+
const selected = this.select(options.adapters);
|
|
58
|
+
const started = new Date();
|
|
59
|
+
const executionId = randomUUID();
|
|
60
|
+
const resolved = path.resolve(options.target);
|
|
61
|
+
// A missing target is a loud error, not an empty scan: the CLI also guards
|
|
62
|
+
// this, but a library caller deserves the same honesty.
|
|
63
|
+
if (!fs.existsSync(resolved))
|
|
64
|
+
throw new Error(`scan target not found: ${resolved}`);
|
|
65
|
+
const workdir = fs.mkdtempSync(path.join(os.tmpdir(), 'usa-scan-'));
|
|
66
|
+
const target = {
|
|
67
|
+
path: resolved,
|
|
68
|
+
workdir,
|
|
69
|
+
revision: detectRevision(path.resolve(options.target)),
|
|
70
|
+
executionId,
|
|
71
|
+
};
|
|
72
|
+
const manifests = [];
|
|
73
|
+
const evidence = [];
|
|
74
|
+
const findings = [];
|
|
75
|
+
try {
|
|
76
|
+
copyTreeForScan(target.path, workdir);
|
|
77
|
+
for (const adapter of selected) {
|
|
78
|
+
const outcome = this.runAdapter(adapter, target, options);
|
|
79
|
+
manifests.push(outcome.manifest);
|
|
80
|
+
evidence.push(...outcome.evidence);
|
|
81
|
+
findings.push(...outcome.findings);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
fs.rmSync(workdir, { recursive: true, force: true });
|
|
86
|
+
}
|
|
87
|
+
const elapsed = (options.now ? options.now() : new Date()).getTime() - started.getTime();
|
|
88
|
+
void elapsed; // manifest timestamps carry per-adapter timing
|
|
89
|
+
return {
|
|
90
|
+
manifest: {
|
|
91
|
+
executionId,
|
|
92
|
+
target: target.path,
|
|
93
|
+
repositoryRevision: target.revision,
|
|
94
|
+
timestamp: started.toISOString(),
|
|
95
|
+
adapters: manifests,
|
|
96
|
+
environment: {
|
|
97
|
+
sandbox: 'subprocess-scratch-copy',
|
|
98
|
+
network: options.network ? 'allowed' : 'denied',
|
|
99
|
+
outputCapBytes: OUTPUT_CAP_BYTES,
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
evidence,
|
|
103
|
+
findings,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
select(only) {
|
|
107
|
+
if (!only || only.length === 0)
|
|
108
|
+
return this.adapters;
|
|
109
|
+
const known = new Set(this.adapters.map((a) => a.id));
|
|
110
|
+
for (const id of only) {
|
|
111
|
+
if (!known.has(id))
|
|
112
|
+
throw new Error(`unknown scanner: ${id} (known: ${[...known].join(', ')})`);
|
|
113
|
+
}
|
|
114
|
+
return this.adapters.filter((a) => only.includes(a.id));
|
|
115
|
+
}
|
|
116
|
+
runAdapter(adapter, target, options) {
|
|
117
|
+
const probe = adapter.probe();
|
|
118
|
+
const config = mergeConfig(adapter, options);
|
|
119
|
+
const gates = runGates(adapter, probe, target, config, options);
|
|
120
|
+
if (gates)
|
|
121
|
+
return { manifest: gates, evidence: [], findings: [] };
|
|
122
|
+
const command = adapter.buildCommand(target, config);
|
|
123
|
+
const timeoutMs = commandTimeout(command, options);
|
|
124
|
+
// Upstream stages first: a pipeline tool's evidence command reads what the
|
|
125
|
+
// earlier stages wrote. A failed stage is a blind spot, not a verdict.
|
|
126
|
+
const prep = runPrepare(adapter, target, command, probe.version, timeoutMs);
|
|
127
|
+
if ('manifest' in prep)
|
|
128
|
+
return { manifest: prep.manifest, evidence: [], findings: [] };
|
|
129
|
+
const prepared = prep.prepared;
|
|
130
|
+
const spawn = spawnScanner(adapter, target, command.argv, timeoutMs);
|
|
131
|
+
if ('failure' in spawn) {
|
|
132
|
+
return {
|
|
133
|
+
manifest: { ...spawn.failure, prepare: prepared, evidenceCount: 0 },
|
|
134
|
+
evidence: [],
|
|
135
|
+
findings: [],
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
const base = {
|
|
139
|
+
id: adapter.id,
|
|
140
|
+
available: true,
|
|
141
|
+
version: probe.version,
|
|
142
|
+
command: command.argv,
|
|
143
|
+
...(prepared.length > 0 ? { prepare: prepared } : {}),
|
|
144
|
+
status: 'ok',
|
|
145
|
+
exitCode: spawn.exitCode,
|
|
146
|
+
evidenceCount: 0,
|
|
147
|
+
elapsedMs: spawn.elapsedMs,
|
|
148
|
+
needsNetwork: Boolean(command.network),
|
|
149
|
+
};
|
|
150
|
+
const output = resolveOutput(spawn, command, target.workdir);
|
|
151
|
+
if (!output.ok) {
|
|
152
|
+
return {
|
|
153
|
+
manifest: { ...base, status: 'error', reason: output.reason },
|
|
154
|
+
evidence: [],
|
|
155
|
+
findings: [],
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
const parsed = parseSafely(adapter, output.raw, {
|
|
159
|
+
adapterId: adapter.id,
|
|
160
|
+
adapterVersion: probe.version,
|
|
161
|
+
target,
|
|
162
|
+
config,
|
|
163
|
+
});
|
|
164
|
+
if (!parsed.ok) {
|
|
165
|
+
return {
|
|
166
|
+
manifest: { ...base, status: 'error', reason: `parse failed: ${parsed.reason}` },
|
|
167
|
+
evidence: [],
|
|
168
|
+
findings: [],
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
const evidence = parsed.evidence;
|
|
172
|
+
stampProvenance(evidence, {
|
|
173
|
+
executionId: target.executionId,
|
|
174
|
+
command: command.argv,
|
|
175
|
+
...(prepared.length > 0 ? { preparedBy: prepared } : {}),
|
|
176
|
+
config,
|
|
177
|
+
repositoryRevision: target.revision,
|
|
178
|
+
timestamp: new Date(spawn.startedAt).toISOString(),
|
|
179
|
+
executable: probe.executable ?? command.argv[0],
|
|
180
|
+
timeoutMs,
|
|
181
|
+
elapsedMs: spawn.elapsedMs,
|
|
182
|
+
});
|
|
183
|
+
return {
|
|
184
|
+
manifest: {
|
|
185
|
+
...base,
|
|
186
|
+
...(output.artifact ? { artifact: output.artifact } : {}),
|
|
187
|
+
evidenceCount: evidence.length,
|
|
188
|
+
},
|
|
189
|
+
evidence,
|
|
190
|
+
findings: findingsOf(adapter, evidence),
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/** Adapters opt into path (2); the default is no findings. */
|
|
195
|
+
function findingsOf(adapter, evidence) {
|
|
196
|
+
return adapter.findings ? adapter.findings(evidence) : [];
|
|
197
|
+
}
|
|
198
|
+
/** Default config under the project's, so a config file overrides one key. */
|
|
199
|
+
function mergeConfig(adapter, options) {
|
|
200
|
+
return { ...adapter.defaultConfig(), ...(options.config?.[adapter.id] ?? {}) };
|
|
201
|
+
}
|
|
202
|
+
/** Adapter, then run, then global default. */
|
|
203
|
+
function commandTimeout(command, options) {
|
|
204
|
+
return command.timeoutMs ?? options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
205
|
+
}
|
|
206
|
+
/** A parse failure is never a verdict: everything it would have found is UNKNOWN. */
|
|
207
|
+
function parseSafely(adapter, raw, context) {
|
|
208
|
+
try {
|
|
209
|
+
return { ok: true, evidence: adapter.parse(raw, context) };
|
|
210
|
+
}
|
|
211
|
+
catch (err) {
|
|
212
|
+
return { ok: false, reason: err.message };
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Run the stages a pipeline tool needs before its evidence command.
|
|
217
|
+
*
|
|
218
|
+
* A prepare stage produces no payload to judge, so its exit status is the only
|
|
219
|
+
* signal it has. Using it to *stop* is not a verdict about the project — the
|
|
220
|
+
* adapter is reported as a blind spot, never as a finding.
|
|
221
|
+
*/
|
|
222
|
+
export function runPrepare(adapter, target, command, version, timeoutMs) {
|
|
223
|
+
const prepared = [];
|
|
224
|
+
for (const stage of command.prepare ?? []) {
|
|
225
|
+
const step = spawnScanner(adapter, target, stage.argv, stage.timeoutMs ?? timeoutMs);
|
|
226
|
+
const failure = 'failure' in step
|
|
227
|
+
? step.failure
|
|
228
|
+
: step.exitCode === 0
|
|
229
|
+
? null
|
|
230
|
+
: {
|
|
231
|
+
id: adapter.id,
|
|
232
|
+
available: true,
|
|
233
|
+
version,
|
|
234
|
+
command: stage.argv,
|
|
235
|
+
status: 'error',
|
|
236
|
+
reason: `prepare stage exited with status ${step.exitCode}`,
|
|
237
|
+
exitCode: step.exitCode,
|
|
238
|
+
evidenceCount: 0,
|
|
239
|
+
elapsedMs: step.elapsedMs,
|
|
240
|
+
needsNetwork: Boolean(command.network),
|
|
241
|
+
};
|
|
242
|
+
if (failure) {
|
|
243
|
+
return {
|
|
244
|
+
manifest: { ...failure, prepare: prepared, reason: `prepare stage: ${failure.reason}` },
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
prepared.push(stage.argv);
|
|
248
|
+
}
|
|
249
|
+
return { prepared };
|
|
250
|
+
}
|
|
251
|
+
/** The bytes to parse: the declared artifact if the tool writes one, else stdout. */
|
|
252
|
+
export function resolveOutput(spawn, command, workdir) {
|
|
253
|
+
if (!command.artifacts || command.artifacts.length === 0) {
|
|
254
|
+
return { ok: true, raw: spawn.stdout };
|
|
255
|
+
}
|
|
256
|
+
const read = readArtifact(workdir, command.artifacts);
|
|
257
|
+
if (!read.ok)
|
|
258
|
+
return { ok: false, reason: read.reason };
|
|
259
|
+
return { ok: true, raw: read.content, artifact: read.path };
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Read the first declared artifact that exists.
|
|
263
|
+
*
|
|
264
|
+
* A declared artifact that is missing is an `error` with a reason, never an
|
|
265
|
+
* empty result: "the tool produced no file" and "the policy passed" are
|
|
266
|
+
* different sentences and only one of them is usually true.
|
|
267
|
+
*/
|
|
268
|
+
export function readArtifact(workdir, declared) {
|
|
269
|
+
const root = path.resolve(workdir);
|
|
270
|
+
for (const rel of declared) {
|
|
271
|
+
const abs = path.resolve(root, rel);
|
|
272
|
+
if (abs !== root && !abs.startsWith(root + path.sep)) {
|
|
273
|
+
return { ok: false, reason: `artifact ${rel} resolves outside the scan workdir` };
|
|
274
|
+
}
|
|
275
|
+
let stat;
|
|
276
|
+
try {
|
|
277
|
+
stat = fs.statSync(abs);
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
if (!stat.isFile())
|
|
283
|
+
continue;
|
|
284
|
+
if (stat.size > OUTPUT_CAP_BYTES) {
|
|
285
|
+
return {
|
|
286
|
+
ok: false,
|
|
287
|
+
reason: `artifact ${rel} is ${stat.size} bytes, over the output cap of ${OUTPUT_CAP_BYTES}`,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
return { ok: true, path: path.relative(root, abs), content: fs.readFileSync(abs, 'utf8') };
|
|
291
|
+
}
|
|
292
|
+
return { ok: false, reason: `declared artifact not produced: ${declared.join(', ')}` };
|
|
293
|
+
}
|
|
294
|
+
/** The two checks that can refuse a run before a process exists. */
|
|
295
|
+
function runGates(adapter, probe, target, config, options) {
|
|
296
|
+
if (!probe.available) {
|
|
297
|
+
return {
|
|
298
|
+
id: adapter.id,
|
|
299
|
+
available: false,
|
|
300
|
+
version: '',
|
|
301
|
+
command: [],
|
|
302
|
+
status: 'unavailable',
|
|
303
|
+
reason: probe.reason ?? 'executable not found',
|
|
304
|
+
evidenceCount: 0,
|
|
305
|
+
elapsedMs: 0,
|
|
306
|
+
needsNetwork: Boolean(adapter.needsNetwork),
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
const command = adapter.buildCommand(target, config);
|
|
310
|
+
if (command.network && !options.network) {
|
|
311
|
+
return {
|
|
312
|
+
id: adapter.id,
|
|
313
|
+
available: true,
|
|
314
|
+
version: probe.version,
|
|
315
|
+
command: command.argv,
|
|
316
|
+
status: 'unavailable',
|
|
317
|
+
reason: adapter.networkConfigKey
|
|
318
|
+
? `needs network unless configured offline — set ${adapter.networkConfigKey}`
|
|
319
|
+
: 'adapter needs network but this run denied it',
|
|
320
|
+
evidenceCount: 0,
|
|
321
|
+
elapsedMs: 0,
|
|
322
|
+
needsNetwork: true,
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
return null;
|
|
326
|
+
}
|
|
327
|
+
function spawnScanner(adapter, target, argv, timeoutMs) {
|
|
328
|
+
const startedAt = Date.now();
|
|
329
|
+
const proc = spawnSync(argv[0], argv.slice(1), {
|
|
330
|
+
cwd: target.workdir,
|
|
331
|
+
env: childEnv(ENV_ALLOW),
|
|
332
|
+
encoding: 'buffer',
|
|
333
|
+
timeout: timeoutMs,
|
|
334
|
+
killSignal: 'SIGTERM',
|
|
335
|
+
maxBuffer: OUTPUT_CAP_BYTES,
|
|
336
|
+
});
|
|
337
|
+
const elapsedMs = Date.now() - startedAt;
|
|
338
|
+
if (proc.error || proc.signal === 'SIGTERM' || proc.status === null) {
|
|
339
|
+
return { failure: spawnFailure(adapter, argv, proc, timeoutMs, elapsedMs) };
|
|
340
|
+
}
|
|
341
|
+
return {
|
|
342
|
+
stdout: proc.stdout ? proc.stdout.toString('utf8') : '',
|
|
343
|
+
exitCode: proc.status,
|
|
344
|
+
elapsedMs,
|
|
345
|
+
startedAt,
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
/** A process that died (including by timeout) is a blind spot, not a verdict. */
|
|
349
|
+
function spawnFailure(adapter, argv, proc, timeoutMs, elapsedMs) {
|
|
350
|
+
const timedOut = proc.error?.code === 'ETIMEDOUT' ||
|
|
351
|
+
proc.signal === 'SIGTERM';
|
|
352
|
+
return {
|
|
353
|
+
id: adapter.id,
|
|
354
|
+
available: true,
|
|
355
|
+
version: '',
|
|
356
|
+
command: argv,
|
|
357
|
+
status: timedOut ? 'timeout' : 'error',
|
|
358
|
+
reason: timedOut
|
|
359
|
+
? `timed out after ${timeoutMs}ms`
|
|
360
|
+
: `failed to start: ${proc.error?.message ?? 'unknown error'}`,
|
|
361
|
+
evidenceCount: 0,
|
|
362
|
+
elapsedMs,
|
|
363
|
+
needsNetwork: false,
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
/** The runner owns provenance, so no adapter can invent one. */
|
|
367
|
+
function stampProvenance(evidence, provenance) {
|
|
368
|
+
for (const item of evidence)
|
|
369
|
+
item.provenance = provenance;
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Copy the target into the scratch directory so no scanner ever runs against,
|
|
373
|
+
* or writes into, the checkout.
|
|
374
|
+
*
|
|
375
|
+
* Skips VCS and installed dependencies: a scanner that reads `node_modules`
|
|
376
|
+
* produces findings about vendored code, not about the project. The skip list
|
|
377
|
+
* is deliberately short and explicit — an unexpected large tree costs time, an
|
|
378
|
+
* unexpected *silent* miss costs an audit.
|
|
379
|
+
*/
|
|
380
|
+
const COPY_SKIP = new Set(['.git', 'node_modules', 'dist', 'build', 'coverage', '.usa']);
|
|
381
|
+
export function copyTreeForScan(from, into) {
|
|
382
|
+
for (const entry of fs.readdirSync(from, { withFileTypes: true })) {
|
|
383
|
+
if (COPY_SKIP.has(entry.name))
|
|
384
|
+
continue;
|
|
385
|
+
const src = path.join(from, entry.name);
|
|
386
|
+
const dest = path.join(into, entry.name);
|
|
387
|
+
if (entry.isDirectory()) {
|
|
388
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
389
|
+
copyTreeForScan(src, dest);
|
|
390
|
+
}
|
|
391
|
+
else if (entry.isSymbolicLink()) {
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
394
|
+
else if (entry.isFile()) {
|
|
395
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
396
|
+
fs.copyFileSync(src, dest);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
/** The commit the checkout points at, or `unversioned` — never blank. */
|
|
401
|
+
export function detectRevision(dir) {
|
|
402
|
+
const head = path.join(dir, '.git', 'HEAD');
|
|
403
|
+
try {
|
|
404
|
+
if (fs.existsSync(head)) {
|
|
405
|
+
const ref = fs.readFileSync(head, 'utf8').trim();
|
|
406
|
+
if (ref.startsWith('ref:')) {
|
|
407
|
+
const p = path.join(dir, '.git', ref.slice(5).trim());
|
|
408
|
+
if (fs.existsSync(p))
|
|
409
|
+
return fs.readFileSync(p, 'utf8').trim().slice(0, 40);
|
|
410
|
+
}
|
|
411
|
+
return ref.slice(0, 40);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
catch {
|
|
415
|
+
/* fall through */
|
|
416
|
+
}
|
|
417
|
+
return 'unversioned';
|
|
418
|
+
}
|
|
419
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/scanner/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SARIF → Evidence.
|
|
3
|
+
*
|
|
4
|
+
* SARIF is the interchange format for three of our four Tier-1 tools, so the
|
|
5
|
+
* parser is shared and lives here rather than inside any one adapter. It is
|
|
6
|
+
* deliberately conservative: only the fields the spec defines are read, and a
|
|
7
|
+
* missing region becomes `null` (no location) rather than a zero.
|
|
8
|
+
*/
|
|
9
|
+
import type { Evidence, ScannerSeverity } from './types.js';
|
|
10
|
+
/** SARIF level → our severity scale. A level is not a severity; the mapping is a policy. */
|
|
11
|
+
export declare function sarifLevelToSeverity(level: unknown): ScannerSeverity;
|
|
12
|
+
export interface SarifEvidenceOptions {
|
|
13
|
+
tool: string;
|
|
14
|
+
kind: string;
|
|
15
|
+
adapterVersion: string;
|
|
16
|
+
/** Confidence for this tool's SARIF results. */
|
|
17
|
+
confidence?: number;
|
|
18
|
+
}
|
|
19
|
+
/** Parse a SARIF log into evidence rows, one per result (plus one per run failure). */
|
|
20
|
+
export declare function evidenceFromSarif(raw: string, options: SarifEvidenceOptions): Evidence[];
|
|
21
|
+
//# sourceMappingURL=sarif.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sarif.d.ts","sourceRoot":"","sources":["../../src/scanner/sarif.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAI5D,4FAA4F;AAC5F,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAWpE;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,QAAQ,EAAE,CASxF"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { buildEvidence } from './identity.js';
|
|
2
|
+
import { dig, tryParseJson } from './normalize.js';
|
|
3
|
+
/** SARIF level → our severity scale. A level is not a severity; the mapping is a policy. */
|
|
4
|
+
export function sarifLevelToSeverity(level) {
|
|
5
|
+
switch (String(level ?? '').toLowerCase()) {
|
|
6
|
+
case 'error':
|
|
7
|
+
return 'HIGH';
|
|
8
|
+
case 'warning':
|
|
9
|
+
return 'MEDIUM';
|
|
10
|
+
case 'note':
|
|
11
|
+
return 'LOW';
|
|
12
|
+
default:
|
|
13
|
+
return 'INFO';
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/** Parse a SARIF log into evidence rows, one per result (plus one per run failure). */
|
|
17
|
+
export function evidenceFromSarif(raw, options) {
|
|
18
|
+
const parsed = tryParseJson(raw);
|
|
19
|
+
if (!parsed.ok)
|
|
20
|
+
return [unknown(options.tool, options.adapterVersion, `not valid JSON: ${parsed.error}`)];
|
|
21
|
+
const runs = dig(parsed.value, ['runs']);
|
|
22
|
+
if (!Array.isArray(runs)) {
|
|
23
|
+
return [unknown(options.tool, options.adapterVersion, 'SARIF log had no runs array')];
|
|
24
|
+
}
|
|
25
|
+
return runs.flatMap((run, runIndex) => runEvidence(run, runIndex, options));
|
|
26
|
+
}
|
|
27
|
+
/** One SARIF run → evidence rows. A run with no results contributes nothing. */
|
|
28
|
+
function runEvidence(run, runIndex, options) {
|
|
29
|
+
const driver = dig(run, ['tool', 'driver']);
|
|
30
|
+
const toolVersion = String(dig(driver, ['version']) ?? options.adapterVersion);
|
|
31
|
+
const rules = ruleIndex(dig(driver, ['rules']));
|
|
32
|
+
const results = dig(run, ['results']);
|
|
33
|
+
if (!Array.isArray(results))
|
|
34
|
+
return [];
|
|
35
|
+
return results.map((result, index) => resultToEvidence(result, { index, runIndex, toolVersion, rules, options }));
|
|
36
|
+
}
|
|
37
|
+
function ruleIndex(rules) {
|
|
38
|
+
const index = new Map();
|
|
39
|
+
if (!Array.isArray(rules))
|
|
40
|
+
return index;
|
|
41
|
+
for (const rule of rules) {
|
|
42
|
+
const id = String(dig(rule, ['id']) ?? '');
|
|
43
|
+
if (id) {
|
|
44
|
+
const tags = dig(rule, ['properties', 'tags']);
|
|
45
|
+
const level = dig(rule, ['defaultConfiguration', 'level']);
|
|
46
|
+
index.set(id, {
|
|
47
|
+
// `name` is the id in every SARIF producer we consume, so a claim built
|
|
48
|
+
// from it reads "js/insufficient-key-size: <message>" — the identifier
|
|
49
|
+
// twice and a human title nowhere. shortDescription is the title.
|
|
50
|
+
text: titleOf(rule),
|
|
51
|
+
cwes: cwesOfTags(tags),
|
|
52
|
+
...(typeof level === 'string' ? { level } : {}),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return index;
|
|
57
|
+
}
|
|
58
|
+
function titleOf(rule) {
|
|
59
|
+
const short = dig(rule, ['shortDescription', 'text']);
|
|
60
|
+
if (typeof short === 'string' && short.length > 0)
|
|
61
|
+
return short;
|
|
62
|
+
const name = dig(rule, ['name']);
|
|
63
|
+
return typeof name === 'string' && name.length > 0 ? name : undefined;
|
|
64
|
+
}
|
|
65
|
+
function resultToEvidence(result, run) {
|
|
66
|
+
const { index, runIndex, toolVersion, rules, options } = run;
|
|
67
|
+
const ruleId = String(dig(result, ['ruleId']) ?? 'unknown-rule');
|
|
68
|
+
const message = firstMessage(result);
|
|
69
|
+
// SARIF 3.27.10: a result may omit `level` when it equals the rule's
|
|
70
|
+
// default. CodeQL omits it for every result, so reading only `result.level`
|
|
71
|
+
// turned every CodeQL finding into INFO — an error-severity certificate
|
|
72
|
+
// check and a warning-severity key-size check became indistinguishable.
|
|
73
|
+
const level = dig(result, ['level']) ?? rules.get(ruleId)?.level;
|
|
74
|
+
return buildEvidence({
|
|
75
|
+
source: {
|
|
76
|
+
tool: options.tool,
|
|
77
|
+
kind: options.kind,
|
|
78
|
+
version: toolVersion,
|
|
79
|
+
identifier: ruleId,
|
|
80
|
+
},
|
|
81
|
+
provenance: placeholder(),
|
|
82
|
+
claim: `${rules.get(ruleId)?.text ?? ruleId}: ${message}`,
|
|
83
|
+
severity: sarifLevelToSeverity(level),
|
|
84
|
+
confidence: options.confidence ?? 1.0,
|
|
85
|
+
status: 'FAIL',
|
|
86
|
+
location: locationOf(dig(result, ['locations', 0])),
|
|
87
|
+
rawReference: {
|
|
88
|
+
jsonPath: `runs[${runIndex}].results[${index}]`,
|
|
89
|
+
excerpt: message.slice(0, 160),
|
|
90
|
+
},
|
|
91
|
+
cwes: rules.get(ruleId)?.cwes,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
/** SARIF rule tags look like `external/cwe/cwe-094`. */
|
|
95
|
+
function cwesOfTags(tags) {
|
|
96
|
+
if (!Array.isArray(tags))
|
|
97
|
+
return undefined;
|
|
98
|
+
const out = new Set();
|
|
99
|
+
for (const tag of tags) {
|
|
100
|
+
const match = /cwe[-_]?(\d{1,5})/i.exec(String(tag));
|
|
101
|
+
if (match)
|
|
102
|
+
out.add(`CWE-${Number(match[1])}`);
|
|
103
|
+
}
|
|
104
|
+
return out.size > 0 ? [...out] : undefined;
|
|
105
|
+
}
|
|
106
|
+
function firstMessage(result) {
|
|
107
|
+
const direct = dig(result, ['message', 'text']);
|
|
108
|
+
if (typeof direct === 'string' && direct.length > 0)
|
|
109
|
+
return direct;
|
|
110
|
+
const parts = dig(result, ['message', 'arguments']);
|
|
111
|
+
if (Array.isArray(parts))
|
|
112
|
+
return parts
|
|
113
|
+
.map((p) => String(p))
|
|
114
|
+
.join(' ')
|
|
115
|
+
.slice(0, 160);
|
|
116
|
+
return 'no message';
|
|
117
|
+
}
|
|
118
|
+
function locationOf(loc) {
|
|
119
|
+
const file = dig(loc, ['physicalLocation', 'artifactLocation', 'uri']);
|
|
120
|
+
if (typeof file !== 'string' || file.length === 0)
|
|
121
|
+
return null;
|
|
122
|
+
const line = Number(dig(loc, ['physicalLocation', 'region', 'startLine']));
|
|
123
|
+
const column = Number(dig(loc, ['physicalLocation', 'region', 'startColumn']));
|
|
124
|
+
return {
|
|
125
|
+
file,
|
|
126
|
+
line: Number.isFinite(line) && line > 0 ? line : undefined,
|
|
127
|
+
column: Number.isFinite(column) && column > 0 ? column : undefined,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function unknown(tool, version, reason) {
|
|
131
|
+
return {
|
|
132
|
+
id: `UNKNOWN-${tool}-${reason}`.replace(/[^A-Za-z0-9-]/g, '-').slice(0, 48),
|
|
133
|
+
source: { tool, version, kind: 'check', identifier: 'UNKNOWN' },
|
|
134
|
+
provenance: placeholder(),
|
|
135
|
+
claim: reason,
|
|
136
|
+
severity: 'INFO',
|
|
137
|
+
severitySource: 'adapter-default',
|
|
138
|
+
confidence: 1.0,
|
|
139
|
+
status: 'UNKNOWN',
|
|
140
|
+
location: null,
|
|
141
|
+
rawReference: {},
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function placeholder() {
|
|
145
|
+
return {
|
|
146
|
+
executionId: '',
|
|
147
|
+
command: [],
|
|
148
|
+
config: {},
|
|
149
|
+
repositoryRevision: '',
|
|
150
|
+
timestamp: '',
|
|
151
|
+
executable: '',
|
|
152
|
+
timeoutMs: 0,
|
|
153
|
+
elapsedMs: 0,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=sarif.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sarif.js","sourceRoot":"","sources":["../../src/scanner/sarif.ts"],"names":[],"mappings":"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"}
|