sentinello 3.3.1 → 3.4.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/README.md +1 -1
- package/dist/cli.cjs +214 -131
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<!-- Absolute URLs throughout: npm does not resolve relative links, and this file ships in the package. -->
|
|
4
4
|
<p>
|
|
5
5
|
<a href="https://github.com/walkofcode/sentinello/actions/workflows/ci.yml"><img src="https://github.com/walkofcode/sentinello/actions/workflows/ci.yml/badge.svg" alt="CI status" /></a>
|
|
6
|
-
<a href="https://github.com/walkofcode/sentinello/blob/main/CONTRIBUTING.md#tests"><img src="https://img.shields.io/badge/coverage-
|
|
6
|
+
<a href="https://github.com/walkofcode/sentinello/blob/main/CONTRIBUTING.md#tests"><img src="https://img.shields.io/badge/coverage-100%25-brightgreen" alt="100% statement, branch, function and line coverage, enforced by CI" /></a>
|
|
7
7
|
<img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT licensed" />
|
|
8
8
|
</p>
|
|
9
9
|
|
package/dist/cli.cjs
CHANGED
|
@@ -1525,14 +1525,14 @@ var require_min_version = __commonJS({
|
|
|
1525
1525
|
var require_valid2 = __commonJS({
|
|
1526
1526
|
"../../node_modules/.pnpm/semver@7.7.4/node_modules/semver/ranges/valid.js"(exports2, module2) {
|
|
1527
1527
|
var Range2 = require_range();
|
|
1528
|
-
var
|
|
1528
|
+
var validRange3 = (range, options) => {
|
|
1529
1529
|
try {
|
|
1530
1530
|
return new Range2(range, options).range || "*";
|
|
1531
1531
|
} catch (er) {
|
|
1532
1532
|
return null;
|
|
1533
1533
|
}
|
|
1534
1534
|
};
|
|
1535
|
-
module2.exports =
|
|
1535
|
+
module2.exports = validRange3;
|
|
1536
1536
|
}
|
|
1537
1537
|
});
|
|
1538
1538
|
|
|
@@ -1882,7 +1882,7 @@ var require_semver2 = __commonJS({
|
|
|
1882
1882
|
var maxSatisfying = require_max_satisfying();
|
|
1883
1883
|
var minSatisfying = require_min_satisfying();
|
|
1884
1884
|
var minVersion = require_min_version();
|
|
1885
|
-
var
|
|
1885
|
+
var validRange3 = require_valid2();
|
|
1886
1886
|
var outside = require_outside();
|
|
1887
1887
|
var gtr = require_gtr();
|
|
1888
1888
|
var ltr = require_ltr();
|
|
@@ -1920,7 +1920,7 @@ var require_semver2 = __commonJS({
|
|
|
1920
1920
|
maxSatisfying,
|
|
1921
1921
|
minSatisfying,
|
|
1922
1922
|
minVersion,
|
|
1923
|
-
validRange:
|
|
1923
|
+
validRange: validRange3,
|
|
1924
1924
|
outside,
|
|
1925
1925
|
gtr,
|
|
1926
1926
|
ltr,
|
|
@@ -13152,9 +13152,19 @@ function isSourceUnavailableReason(code) {
|
|
|
13152
13152
|
return SOURCE_UNAVAILABLE_REASON_CODES.includes(code);
|
|
13153
13153
|
}
|
|
13154
13154
|
|
|
13155
|
+
// ../../packages/core/src/errors.ts
|
|
13156
|
+
function errText(err) {
|
|
13157
|
+
if (err instanceof Error) return err.message || String(err);
|
|
13158
|
+
return String(err);
|
|
13159
|
+
}
|
|
13160
|
+
function asError(err) {
|
|
13161
|
+
if (err instanceof Error) return err;
|
|
13162
|
+
return new Error(String(err));
|
|
13163
|
+
}
|
|
13164
|
+
|
|
13155
13165
|
// ../../packages/core/src/advisory-rows.ts
|
|
13156
|
-
var OSV_NORMALIZER_VERSION =
|
|
13157
|
-
var GEMNASIUM_NORMALIZER_VERSION =
|
|
13166
|
+
var OSV_NORMALIZER_VERSION = 6;
|
|
13167
|
+
var GEMNASIUM_NORMALIZER_VERSION = 7;
|
|
13158
13168
|
|
|
13159
13169
|
// ../../packages/core/src/advisory-export.ts
|
|
13160
13170
|
var DEFAULT_EXPORT_PROMPT = `You are helping a development team triage and fix the vulnerabilities listed at the bottom of this document. Treat this as a remediation work list, not a checklist to rubber-stamp. Work in a planning posture from the start: if your tooling has a read-only planning mode (Claude Code's plan mode, for example), enter it now and stay in it until the human has approved the triage below. Nothing in this document authorises you to edit a file before then.
|
|
@@ -13421,10 +13431,14 @@ function getEcosystem(id) {
|
|
|
13421
13431
|
}
|
|
13422
13432
|
return null;
|
|
13423
13433
|
}
|
|
13434
|
+
function cacheEcosystemKey(ecosystem) {
|
|
13435
|
+
const def = getEcosystem(ecosystem);
|
|
13436
|
+
return def ? def.osvEcosystem : ecosystem;
|
|
13437
|
+
}
|
|
13424
13438
|
var GEMNASIUM_SEED_DOWNLOAD_BYTES = 52 * 1024 * 1024;
|
|
13425
13439
|
|
|
13426
13440
|
// ../../packages/scanners/src/lockfile-cross-check.ts
|
|
13427
|
-
var
|
|
13441
|
+
var import_semver7 = __toESM(require_semver2());
|
|
13428
13442
|
|
|
13429
13443
|
// ../../packages/versions/src/range.ts
|
|
13430
13444
|
function isZeroVersion(version2) {
|
|
@@ -13468,7 +13482,7 @@ function aboveLowerBound(installed, range, comparator) {
|
|
|
13468
13482
|
}
|
|
13469
13483
|
|
|
13470
13484
|
// ../../packages/versions/src/compare.ts
|
|
13471
|
-
__toESM(require_semver2());
|
|
13485
|
+
var import_semver2 = __toESM(require_semver2());
|
|
13472
13486
|
|
|
13473
13487
|
// ../../packages/versions/src/comparators/semver.ts
|
|
13474
13488
|
var import_semver = __toESM(require_semver2());
|
|
@@ -13498,6 +13512,63 @@ var semverComparator = {
|
|
|
13498
13512
|
}
|
|
13499
13513
|
};
|
|
13500
13514
|
|
|
13515
|
+
// ../../packages/versions/src/compare.ts
|
|
13516
|
+
function compareVersions(a, b) {
|
|
13517
|
+
const left = normalizeSemver(a);
|
|
13518
|
+
const right = normalizeSemver(b);
|
|
13519
|
+
if (left === null || right === null) {
|
|
13520
|
+
if (left === null && right === null) return a < b ? -1 : a > b ? 1 : 0;
|
|
13521
|
+
return left === null ? -1 : 1;
|
|
13522
|
+
}
|
|
13523
|
+
if ((0, import_semver2.lt)(left, right)) return -1;
|
|
13524
|
+
if ((0, import_semver2.gt)(left, right)) return 1;
|
|
13525
|
+
return 0;
|
|
13526
|
+
}
|
|
13527
|
+
function highestVersion(versions) {
|
|
13528
|
+
let best = null;
|
|
13529
|
+
for (const candidate of versions) {
|
|
13530
|
+
if (best === null || compareVersions(candidate, best) > 0) best = candidate;
|
|
13531
|
+
}
|
|
13532
|
+
return best;
|
|
13533
|
+
}
|
|
13534
|
+
|
|
13535
|
+
// ../../packages/versions/src/dialect.ts
|
|
13536
|
+
var import_semver4 = __toESM(require_semver2());
|
|
13537
|
+
function canonicaliseRange(raw, dialect) {
|
|
13538
|
+
if (dialect !== "npm") return raw;
|
|
13539
|
+
const trimmed = raw.trim();
|
|
13540
|
+
if (!/[0-9]/.test(trimmed)) return null;
|
|
13541
|
+
if (ZERO_EXCLUSIVE_LOWER.test(trimmed)) return raw;
|
|
13542
|
+
const canonical = (0, import_semver4.validRange)(trimmed);
|
|
13543
|
+
if (canonical === null) return raw;
|
|
13544
|
+
if (canonical === "*" || canonical.length === 0) return ">=0";
|
|
13545
|
+
return stripSynthesisedPrereleaseMarker(canonical, raw);
|
|
13546
|
+
}
|
|
13547
|
+
var ZERO_EXCLUSIVE_LOWER = /^>\s*v?0(\.0)*$/i;
|
|
13548
|
+
var SYNTHESISED_PRERELEASE_MARKER = /<([0-9][0-9A-Za-z.+-]*)-0(?![0-9A-Za-z.-])/g;
|
|
13549
|
+
var EXPLICIT_PRERELEASE_ZERO = /[0-9][0-9A-Za-z.+-]*-0(?![0-9A-Za-z.-])/g;
|
|
13550
|
+
function stripSynthesisedPrereleaseMarker(canonical, raw) {
|
|
13551
|
+
const explicit = new Set(raw.match(EXPLICIT_PRERELEASE_ZERO) ?? []);
|
|
13552
|
+
return canonical.replace(SYNTHESISED_PRERELEASE_MARKER, function keepExplicit(whole, base) {
|
|
13553
|
+
return explicit.has(base + "-0") ? whole : "<" + base;
|
|
13554
|
+
});
|
|
13555
|
+
}
|
|
13556
|
+
function canMatchSomething(range) {
|
|
13557
|
+
const inclusiveUpper = range.lastAffected ?? null;
|
|
13558
|
+
const upper = inclusiveUpper !== null ? inclusiveUpper : range.fixed;
|
|
13559
|
+
if (upper === null) return true;
|
|
13560
|
+
if (upper === range.introduced) return inclusiveUpper !== null && range.introducedExclusive !== true;
|
|
13561
|
+
if (inclusiveUpper === null && isZeroVersion(range.introduced) && isZeroVersion(upper)) return false;
|
|
13562
|
+
if (range.type !== "SEMVER") return true;
|
|
13563
|
+
const normalizedUpper = normalizeSemver(upper);
|
|
13564
|
+
const normalizedIntroduced = normalizeSemver(range.introduced);
|
|
13565
|
+
if (normalizedUpper === null || normalizedIntroduced === null) return true;
|
|
13566
|
+
if (normalizedUpper === normalizedIntroduced) {
|
|
13567
|
+
return inclusiveUpper !== null && range.introducedExclusive !== true;
|
|
13568
|
+
}
|
|
13569
|
+
return (0, import_semver4.gt)(normalizedUpper, normalizedIntroduced);
|
|
13570
|
+
}
|
|
13571
|
+
|
|
13501
13572
|
// ../../packages/versions/src/comparators/pep440.ts
|
|
13502
13573
|
var PRE_RANK = { a: 0, b: 1, rc: 2 };
|
|
13503
13574
|
var PEP440_RE = new RegExp(
|
|
@@ -13515,13 +13586,9 @@ function parsePep440(raw) {
|
|
|
13515
13586
|
const m = PEP440_RE.exec(raw.trim());
|
|
13516
13587
|
if (!m || !m.groups) return null;
|
|
13517
13588
|
const g = m.groups;
|
|
13518
|
-
if (!g.release) return null;
|
|
13519
13589
|
const release = g.release.split(".").map(function toInt(s) {
|
|
13520
13590
|
return parseInt(s, 10);
|
|
13521
13591
|
});
|
|
13522
|
-
if (release.some(function bad(n) {
|
|
13523
|
-
return Number.isNaN(n);
|
|
13524
|
-
})) return null;
|
|
13525
13592
|
let pre = null;
|
|
13526
13593
|
if (g.preL) {
|
|
13527
13594
|
pre = { letter: foldPreLetter(g.preL), n: g.preN ? parseInt(g.preN, 10) : 0 };
|
|
@@ -13577,8 +13644,8 @@ function cmpPre(a, b) {
|
|
|
13577
13644
|
const kb = preKind(b);
|
|
13578
13645
|
if (ka !== kb) return ka < kb ? -1 : 1;
|
|
13579
13646
|
if (ka !== 0 || !a.pre || !b.pre) return 0;
|
|
13580
|
-
const la = PRE_RANK[a.pre.letter]
|
|
13581
|
-
const lb = PRE_RANK[b.pre.letter]
|
|
13647
|
+
const la = PRE_RANK[a.pre.letter];
|
|
13648
|
+
const lb = PRE_RANK[b.pre.letter];
|
|
13582
13649
|
if (la !== lb) return la < lb ? -1 : 1;
|
|
13583
13650
|
if (a.pre.n !== b.pre.n) return a.pre.n < b.pre.n ? -1 : 1;
|
|
13584
13651
|
return 0;
|
|
@@ -13675,7 +13742,7 @@ function shouldKeep(finding) {
|
|
|
13675
13742
|
const installed = finding.installedVersion.trim();
|
|
13676
13743
|
const range = finding.vulnerableRange.trim();
|
|
13677
13744
|
if (!installed || !range) return true;
|
|
13678
|
-
if ((0,
|
|
13745
|
+
if ((0, import_semver7.validRange)(range) === null) return true;
|
|
13679
13746
|
const candidates = installed.split(/,\s*/).map(function trim(s) {
|
|
13680
13747
|
return s.trim();
|
|
13681
13748
|
}).filter(Boolean);
|
|
@@ -13683,7 +13750,7 @@ function shouldKeep(finding) {
|
|
|
13683
13750
|
for (const candidate of candidates) {
|
|
13684
13751
|
const cleaned = normalizeVersion(candidate);
|
|
13685
13752
|
if (cleaned === null) return true;
|
|
13686
|
-
if ((0,
|
|
13753
|
+
if ((0, import_semver7.satisfies)(cleaned, range, { includePrerelease: true })) return true;
|
|
13687
13754
|
}
|
|
13688
13755
|
return false;
|
|
13689
13756
|
}
|
|
@@ -28172,7 +28239,7 @@ function date4(params) {
|
|
|
28172
28239
|
config(en_default());
|
|
28173
28240
|
|
|
28174
28241
|
// ../../packages/scanners/src/version-fix.ts
|
|
28175
|
-
var
|
|
28242
|
+
var import_semver8 = __toESM(require_semver2());
|
|
28176
28243
|
var VERSION_LITERAL_RE = /\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?/g;
|
|
28177
28244
|
function parseRangeSafely(input) {
|
|
28178
28245
|
if (!input) return null;
|
|
@@ -28180,7 +28247,7 @@ function parseRangeSafely(input) {
|
|
|
28180
28247
|
if (!trimmed) return null;
|
|
28181
28248
|
if (trimmed === "<0.0.0") return null;
|
|
28182
28249
|
try {
|
|
28183
|
-
return new
|
|
28250
|
+
return new import_semver8.Range(trimmed, { includePrerelease: false });
|
|
28184
28251
|
} catch {
|
|
28185
28252
|
return null;
|
|
28186
28253
|
}
|
|
@@ -28191,13 +28258,12 @@ function extractLiteralCandidates(input) {
|
|
|
28191
28258
|
if (!matches) return [];
|
|
28192
28259
|
const out = [];
|
|
28193
28260
|
for (const m of matches) {
|
|
28194
|
-
if ((0,
|
|
28261
|
+
if ((0, import_semver8.valid)(m)) out.push(m);
|
|
28195
28262
|
}
|
|
28196
28263
|
return out;
|
|
28197
28264
|
}
|
|
28198
28265
|
function bumpPatch(v) {
|
|
28199
|
-
const sv = (0,
|
|
28200
|
-
if (!sv) return null;
|
|
28266
|
+
const sv = (0, import_semver8.coerce)(v);
|
|
28201
28267
|
return sv.major + "." + sv.minor + "." + (sv.patch + 1);
|
|
28202
28268
|
}
|
|
28203
28269
|
function extractRangeLowerBounds(range) {
|
|
@@ -28207,13 +28273,12 @@ function extractRangeLowerBounds(range) {
|
|
|
28207
28273
|
for (const c of conjuncts) {
|
|
28208
28274
|
if (!c.semver || !c.semver.version) continue;
|
|
28209
28275
|
const v = c.semver.version;
|
|
28210
|
-
if (!(0, import_semver6.valid)(v)) continue;
|
|
28211
28276
|
const op = c.operator;
|
|
28212
28277
|
if (op === ">=" || op === "=" || op === "") {
|
|
28213
|
-
if (!candidate || (0,
|
|
28278
|
+
if (!candidate || (0, import_semver8.gt)(v, candidate)) candidate = v;
|
|
28214
28279
|
} else if (op === ">") {
|
|
28215
28280
|
const inc = bumpPatch(v);
|
|
28216
|
-
if (
|
|
28281
|
+
if (!candidate || (0, import_semver8.gt)(inc, candidate)) candidate = inc;
|
|
28217
28282
|
}
|
|
28218
28283
|
}
|
|
28219
28284
|
if (candidate) out.push(candidate);
|
|
@@ -28226,13 +28291,11 @@ function extractRangeUpperBoundsBeyond(range) {
|
|
|
28226
28291
|
for (const c of conjuncts) {
|
|
28227
28292
|
if (!c.semver || !c.semver.version) continue;
|
|
28228
28293
|
const v = c.semver.version;
|
|
28229
|
-
if (!(0, import_semver6.valid)(v)) continue;
|
|
28230
28294
|
const op = c.operator;
|
|
28231
28295
|
if (op === "<") {
|
|
28232
28296
|
out.push(v);
|
|
28233
28297
|
} else if (op === "<=") {
|
|
28234
|
-
|
|
28235
|
-
if (inc) out.push(inc);
|
|
28298
|
+
out.push(bumpPatch(v));
|
|
28236
28299
|
}
|
|
28237
28300
|
}
|
|
28238
28301
|
}
|
|
@@ -28245,8 +28308,8 @@ function pickHighestInstalled(installed) {
|
|
|
28245
28308
|
for (const raw of parts) {
|
|
28246
28309
|
const part = raw.trim();
|
|
28247
28310
|
if (!part) continue;
|
|
28248
|
-
if (!(0,
|
|
28249
|
-
if (!highest || (0,
|
|
28311
|
+
if (!(0, import_semver8.valid)(part)) continue;
|
|
28312
|
+
if (!highest || (0, import_semver8.gt)(part, highest)) highest = part;
|
|
28250
28313
|
}
|
|
28251
28314
|
return highest;
|
|
28252
28315
|
}
|
|
@@ -28268,10 +28331,10 @@ function pickSafeFixVersion(args) {
|
|
|
28268
28331
|
if (candidates.size === 0) return null;
|
|
28269
28332
|
let best = null;
|
|
28270
28333
|
for (const v of candidates) {
|
|
28271
|
-
if (patchedRange && !(0,
|
|
28272
|
-
if (vulnRange && (0,
|
|
28273
|
-
if (installedFloor && !(0,
|
|
28274
|
-
if (!best || (0,
|
|
28334
|
+
if (patchedRange && !(0, import_semver8.satisfies)(v, patchedRange)) continue;
|
|
28335
|
+
if (vulnRange && (0, import_semver8.satisfies)(v, vulnRange)) continue;
|
|
28336
|
+
if (installedFloor && !(0, import_semver8.gte)(v, installedFloor)) continue;
|
|
28337
|
+
if (!best || (0, import_semver8.gt)(best, v)) best = v;
|
|
28275
28338
|
}
|
|
28276
28339
|
return best;
|
|
28277
28340
|
}
|
|
@@ -28390,17 +28453,15 @@ function classifyPackageManagerNotFound(stderr, packageManager) {
|
|
|
28390
28453
|
return re1.test(stderr) || re2.test(stderr);
|
|
28391
28454
|
}
|
|
28392
28455
|
function pickAuditCommand(lockfile) {
|
|
28393
|
-
if (lockfile.packageManager === "pnpm") return "pnpm audit --json";
|
|
28394
|
-
if (lockfile.packageManager === "npm") return "npm audit --json";
|
|
28395
|
-
return "yarn npm audit --json";
|
|
28456
|
+
if (lockfile.packageManager === "pnpm") return ["pnpm", "audit", "--json"];
|
|
28457
|
+
if (lockfile.packageManager === "npm") return ["npm", "audit", "--json"];
|
|
28458
|
+
return ["yarn", "npm", "audit", "--json"];
|
|
28396
28459
|
}
|
|
28397
28460
|
function parseYarnMajor(value) {
|
|
28398
28461
|
if (typeof value !== "string") return null;
|
|
28399
28462
|
const match = value.trim().match(/^yarn@(\d+)(?:\.|$)/);
|
|
28400
28463
|
if (!match || !match[1]) return null;
|
|
28401
|
-
|
|
28402
|
-
if (Number.isNaN(parsed)) return null;
|
|
28403
|
-
return parsed;
|
|
28464
|
+
return parseInt(match[1], 10);
|
|
28404
28465
|
}
|
|
28405
28466
|
function unauditableResult(reasonCode, reason, startedAt, rawJson) {
|
|
28406
28467
|
return {
|
|
@@ -28544,9 +28605,7 @@ function normalizeAuditOutput(parsed, installedVersions, classifier) {
|
|
|
28544
28605
|
const findings = [];
|
|
28545
28606
|
let hadVulnerabilityWithoutConcreteAdvisory = false;
|
|
28546
28607
|
const vulns = parsed.vulnerabilities ?? {};
|
|
28547
|
-
for (const packageName of Object.
|
|
28548
|
-
const vuln = vulns[packageName];
|
|
28549
|
-
if (!vuln) continue;
|
|
28608
|
+
for (const [packageName, vuln] of Object.entries(vulns)) {
|
|
28550
28609
|
if (!vuln.via || vuln.via.length === 0) {
|
|
28551
28610
|
hadVulnerabilityWithoutConcreteAdvisory = true;
|
|
28552
28611
|
continue;
|
|
@@ -28694,10 +28753,8 @@ async function loadLockfileSnapshot(projectPath, lockfile) {
|
|
|
28694
28753
|
if (!validation.success) return empty;
|
|
28695
28754
|
const installedVersions = /* @__PURE__ */ new Map();
|
|
28696
28755
|
const packages = validation.data.packages || {};
|
|
28697
|
-
for (const nodePath of Object.
|
|
28756
|
+
for (const [nodePath, entry] of Object.entries(packages)) {
|
|
28698
28757
|
if (!nodePath) continue;
|
|
28699
|
-
const entry = packages[nodePath];
|
|
28700
|
-
if (!entry) continue;
|
|
28701
28758
|
if (entry.version) {
|
|
28702
28759
|
installedVersions.set(nodePath, entry.version);
|
|
28703
28760
|
}
|
|
@@ -28849,9 +28906,6 @@ function executeSpawnAndCapture(input, resolve5) {
|
|
|
28849
28906
|
child.stderr.on("data", onSpawnStderrData.bind(null, state));
|
|
28850
28907
|
child.on("error", onSpawnError.bind(null, ctx));
|
|
28851
28908
|
child.on("close", onSpawnClose.bind(null, ctx));
|
|
28852
|
-
if (input.opts.stdin && child.stdin) {
|
|
28853
|
-
child.stdin.end(input.opts.stdin);
|
|
28854
|
-
}
|
|
28855
28909
|
}
|
|
28856
28910
|
function spawnAndCapture(deps, cmd, args, opts) {
|
|
28857
28911
|
return new Promise(executeSpawnAndCapture.bind(null, { deps, cmd, args, opts }));
|
|
@@ -28911,17 +28965,13 @@ async function runNpmAudit(projectPath, ctx, deps = REAL_DEPS) {
|
|
|
28911
28965
|
let execCmd;
|
|
28912
28966
|
let execArgs;
|
|
28913
28967
|
if (wrapWithNvm) {
|
|
28914
|
-
const wrapped = buildBashWrappedCommand(rawCmd);
|
|
28968
|
+
const wrapped = buildBashWrappedCommand(rawCmd.join(" "));
|
|
28915
28969
|
execCmd = wrapped.cmd;
|
|
28916
28970
|
execArgs = wrapped.args;
|
|
28917
28971
|
} else {
|
|
28918
|
-
const
|
|
28919
|
-
const head = parts[0];
|
|
28920
|
-
if (!head) {
|
|
28921
|
-
return errorResult("audit_unknown_failure", "failed to construct audit command", startedAt, "");
|
|
28922
|
-
}
|
|
28972
|
+
const [head, ...rest] = rawCmd;
|
|
28923
28973
|
execCmd = head;
|
|
28924
|
-
execArgs =
|
|
28974
|
+
execArgs = rest;
|
|
28925
28975
|
}
|
|
28926
28976
|
const spawnResult = await spawnAndCapture(deps, execCmd, execArgs, {
|
|
28927
28977
|
cwd: projectPath,
|
|
@@ -28967,11 +29017,7 @@ async function runNpmAudit(projectPath, ctx, deps = REAL_DEPS) {
|
|
|
28967
29017
|
try {
|
|
28968
29018
|
parsedJson = JSON.parse(rawText);
|
|
28969
29019
|
} catch (err) {
|
|
28970
|
-
|
|
28971
|
-
if (err instanceof Error) {
|
|
28972
|
-
reason = `audit JSON parse failed: ${err.message}`;
|
|
28973
|
-
}
|
|
28974
|
-
return errorResult("audit_parse_error", reason, startedAt, rawText);
|
|
29020
|
+
return errorResult("audit_parse_error", `audit JSON parse failed: ${errText(err)}`, startedAt, rawText);
|
|
28975
29021
|
}
|
|
28976
29022
|
if (lockfile.packageManager === "pnpm") {
|
|
28977
29023
|
const pnpmValidation = pnpmAuditSchema.safeParse(parsedJson);
|
|
@@ -29035,9 +29081,7 @@ function reachableFrom(roots, adjacency) {
|
|
|
29035
29081
|
stack.push(root);
|
|
29036
29082
|
}
|
|
29037
29083
|
}
|
|
29038
|
-
|
|
29039
|
-
const node = stack.pop();
|
|
29040
|
-
if (node === void 0) break;
|
|
29084
|
+
for (let node = stack.pop(); node !== void 0; node = stack.pop()) {
|
|
29041
29085
|
const children = adjacency.get(node);
|
|
29042
29086
|
if (!children) continue;
|
|
29043
29087
|
for (const child of children) {
|
|
@@ -32387,7 +32431,7 @@ function parsePnpmV9(root) {
|
|
|
32387
32431
|
if (isProd) existing.scope.isProd = true;
|
|
32388
32432
|
if (isDev) existing.scope.isDev = true;
|
|
32389
32433
|
if (!isOptional) existing.scope.isOptional = false;
|
|
32390
|
-
|
|
32434
|
+
existing.depPaths.push(key);
|
|
32391
32435
|
} else {
|
|
32392
32436
|
byId.set(id, {
|
|
32393
32437
|
ecosystem: NPM_ECOSYSTEM2,
|
|
@@ -32409,7 +32453,6 @@ function parsePnpmLegacy(root) {
|
|
|
32409
32453
|
const parsed = parseDepKey(key);
|
|
32410
32454
|
if (!parsed) continue;
|
|
32411
32455
|
const version2 = entry.version || parsed.version;
|
|
32412
|
-
if (!version2) continue;
|
|
32413
32456
|
const isDev = entry.dev === true;
|
|
32414
32457
|
out.push({
|
|
32415
32458
|
ecosystem: NPM_ECOSYSTEM2,
|
|
@@ -32809,7 +32852,6 @@ function classifySkip(absolutePath, rootPath, layers, excludeMatcher, hasExclude
|
|
|
32809
32852
|
for (let i = layers.length - 1; i >= 0; i--) {
|
|
32810
32853
|
const layer = layers[i];
|
|
32811
32854
|
const rel = path.relative(layer.baseDir, absolutePath);
|
|
32812
|
-
if (!rel || rel.startsWith("..")) continue;
|
|
32813
32855
|
if (!layer.matcher.ignores(rel) && !layer.matcher.ignores(rel + "/")) continue;
|
|
32814
32856
|
if (layer.hasSentinelloIgnore && !layer.hasGitignore) return "sentinelloignore";
|
|
32815
32857
|
if (layer.hasGitignore && !layer.hasSentinelloIgnore) return "gitignore";
|
|
@@ -32886,9 +32928,7 @@ function detectPackageManager(dir) {
|
|
|
32886
32928
|
return "unknown";
|
|
32887
32929
|
}
|
|
32888
32930
|
function basenameOf(dir) {
|
|
32889
|
-
|
|
32890
|
-
const parts = abs.split("/");
|
|
32891
|
-
return parts[parts.length - 1] || abs;
|
|
32931
|
+
return path.basename(path.resolve(dir));
|
|
32892
32932
|
}
|
|
32893
32933
|
function readNvmrcVersion(dir) {
|
|
32894
32934
|
const nvmrcPath = path.join(dir, ".nvmrc");
|
|
@@ -32906,7 +32946,7 @@ function readGitBranch(dir, rootPath) {
|
|
|
32906
32946
|
try {
|
|
32907
32947
|
const head = fs.readFileSync(path.join(gitDir, "HEAD"), "utf8").trim();
|
|
32908
32948
|
const ref = head.match(/^ref:\s*refs\/heads\/(.+)$/);
|
|
32909
|
-
if (ref && ref[1]) return ref[1].trim()
|
|
32949
|
+
if (ref && ref[1]) return ref[1].trim();
|
|
32910
32950
|
if (/^[0-9a-f]{40}$/i.test(head)) return head.slice(0, 7);
|
|
32911
32951
|
return null;
|
|
32912
32952
|
} catch {
|
|
@@ -33057,7 +33097,7 @@ function rangesToDisplay(ranges, exactVersions) {
|
|
|
33057
33097
|
const parts = [];
|
|
33058
33098
|
for (const v of exactVersions) parts.push("=" + v);
|
|
33059
33099
|
for (const range of ranges) parts.push(formatRange(range, DISPLAY_FORMAT));
|
|
33060
|
-
return parts.
|
|
33100
|
+
return parts.join(" || ");
|
|
33061
33101
|
}
|
|
33062
33102
|
function vulnerableRangeForFix(ranges) {
|
|
33063
33103
|
return formatRanges(ranges, SEMVER_FORMAT);
|
|
@@ -33109,7 +33149,6 @@ function matchPackages(packages, lookup, isSeeded2, isEnabled) {
|
|
|
33109
33149
|
if (!comparator) continue;
|
|
33110
33150
|
const acceptedRangeTypes = acceptedRangeTypesForEcosystem(ecosystem) ?? [];
|
|
33111
33151
|
const names = uniqueNames(pkgs);
|
|
33112
|
-
if (names.length === 0) continue;
|
|
33113
33152
|
const byPackageRaw = lookup(ecosystem, names);
|
|
33114
33153
|
const byPackage = /* @__PURE__ */ new Map();
|
|
33115
33154
|
for (const [name, advisories] of byPackageRaw.entries()) {
|
|
@@ -33216,7 +33255,6 @@ function matchPackages2(packages, lookup, isEnabled) {
|
|
|
33216
33255
|
const comparator = comparatorForEcosystem(ecosystem);
|
|
33217
33256
|
if (!comparator) continue;
|
|
33218
33257
|
const names = uniqueNames2(pkgs);
|
|
33219
|
-
if (names.length === 0) continue;
|
|
33220
33258
|
const byPackageRaw = lookup(ecosystem, names);
|
|
33221
33259
|
const byPackage = /* @__PURE__ */ new Map();
|
|
33222
33260
|
for (const [name, advisories] of byPackageRaw.entries()) {
|
|
@@ -33345,10 +33383,6 @@ function signalFor(options, fallbackTimeoutMs) {
|
|
|
33345
33383
|
if (options && options.abortSignal) return AbortSignal.any([options.abortSignal, timeout]);
|
|
33346
33384
|
return timeout;
|
|
33347
33385
|
}
|
|
33348
|
-
function errText(err) {
|
|
33349
|
-
if (err instanceof Error) return err.message;
|
|
33350
|
-
return String(err);
|
|
33351
|
-
}
|
|
33352
33386
|
function isFastTransientStatus(status) {
|
|
33353
33387
|
if (status === 408 || status === 425 || status === 429) return true;
|
|
33354
33388
|
return status >= 500 && status < 600;
|
|
@@ -33535,7 +33569,7 @@ function normalizeOsvRecord(record2, ecosystem) {
|
|
|
33535
33569
|
if (!pkg2 || pkg2.ecosystem !== ecosystem) continue;
|
|
33536
33570
|
const packageName = typeof pkg2.name === "string" ? pkg2.name : null;
|
|
33537
33571
|
if (!packageName) continue;
|
|
33538
|
-
const ranges = extractRanges(affected.ranges);
|
|
33572
|
+
const ranges = extractRanges(affected.ranges, affected.database_specific?.last_known_affected_version_range, ecosystem);
|
|
33539
33573
|
const versions = extractVersions(affected.versions);
|
|
33540
33574
|
const existing = byPackage.get(packageName);
|
|
33541
33575
|
if (existing) {
|
|
@@ -33571,7 +33605,7 @@ function extractVersions(versions) {
|
|
|
33571
33605
|
}
|
|
33572
33606
|
return out;
|
|
33573
33607
|
}
|
|
33574
|
-
function extractRanges(ranges) {
|
|
33608
|
+
function extractRanges(ranges, lastKnownAffected, ecosystem) {
|
|
33575
33609
|
if (!Array.isArray(ranges)) return [];
|
|
33576
33610
|
const out = [];
|
|
33577
33611
|
for (const range of ranges) {
|
|
@@ -33584,18 +33618,20 @@ function extractRanges(ranges) {
|
|
|
33584
33618
|
if (typeof event.introduced === "string") {
|
|
33585
33619
|
if (introduced !== null) {
|
|
33586
33620
|
out.push({ type: type2, introduced, fixed: null, lastAffected });
|
|
33587
|
-
lastAffected = null;
|
|
33588
33621
|
}
|
|
33589
|
-
|
|
33622
|
+
lastAffected = null;
|
|
33623
|
+
introduced = !usesSemver(type2, ecosystem) || normalizeSemver(event.introduced) !== null ? event.introduced : null;
|
|
33590
33624
|
continue;
|
|
33591
33625
|
}
|
|
33592
33626
|
if (typeof event.fixed === "string" && introduced !== null) {
|
|
33627
|
+
if (usesSemver(type2, ecosystem) && normalizeSemver(event.fixed) === null) continue;
|
|
33593
33628
|
out.push({ type: type2, introduced, fixed: event.fixed, lastAffected: null });
|
|
33594
33629
|
introduced = null;
|
|
33595
33630
|
lastAffected = null;
|
|
33596
33631
|
continue;
|
|
33597
33632
|
}
|
|
33598
33633
|
if (typeof event.last_affected === "string" && introduced !== null) {
|
|
33634
|
+
if (usesSemver(type2, ecosystem) && normalizeSemver(event.last_affected) === null) continue;
|
|
33599
33635
|
lastAffected = event.last_affected;
|
|
33600
33636
|
}
|
|
33601
33637
|
}
|
|
@@ -33603,7 +33639,32 @@ function extractRanges(ranges) {
|
|
|
33603
33639
|
out.push({ type: type2, introduced, fixed: null, lastAffected });
|
|
33604
33640
|
}
|
|
33605
33641
|
}
|
|
33606
|
-
|
|
33642
|
+
const matchable = [];
|
|
33643
|
+
for (const range of out) {
|
|
33644
|
+
if (canRangeMatch(range, ecosystem)) matchable.push(range);
|
|
33645
|
+
}
|
|
33646
|
+
return boundOpenEndedRange(matchable, lastKnownAffected, ecosystem);
|
|
33647
|
+
}
|
|
33648
|
+
function usesSemver(type2, ecosystem) {
|
|
33649
|
+
if (type2 === "SEMVER") return true;
|
|
33650
|
+
return type2 === "ECOSYSTEM" && getEcosystem(ecosystem)?.comparator === "semver";
|
|
33651
|
+
}
|
|
33652
|
+
function canRangeMatch(range, ecosystem) {
|
|
33653
|
+
return canMatchSomething(usesSemver(range.type, ecosystem) ? { ...range, type: "SEMVER" } : range);
|
|
33654
|
+
}
|
|
33655
|
+
function boundOpenEndedRange(ranges, lastKnownAffected, ecosystem) {
|
|
33656
|
+
if (ranges.length !== 1 || typeof lastKnownAffected !== "string") return ranges;
|
|
33657
|
+
const text = lastKnownAffected.trim();
|
|
33658
|
+
const inclusive = text.startsWith("<=");
|
|
33659
|
+
if (!inclusive && !text.startsWith("<")) return ranges;
|
|
33660
|
+
const version2 = text.slice(inclusive ? 2 : 1).trim();
|
|
33661
|
+
if (version2.length === 0 || /[\s,|]/.test(version2)) return ranges;
|
|
33662
|
+
const range = ranges[0];
|
|
33663
|
+
const open = range.fixed === null && range.lastAffected === null;
|
|
33664
|
+
if (!open) return ranges;
|
|
33665
|
+
if (usesSemver(range.type, ecosystem) && normalizeSemver(version2) === null) return ranges;
|
|
33666
|
+
const bounded = { ...range, fixed: inclusive ? null : version2, lastAffected: inclusive ? version2 : null };
|
|
33667
|
+
return canRangeMatch(bounded, ecosystem) ? [bounded] : ranges;
|
|
33607
33668
|
}
|
|
33608
33669
|
function pickSeverity2(r) {
|
|
33609
33670
|
const ds = r.database_specific && r.database_specific.severity;
|
|
@@ -33846,7 +33907,7 @@ function normalizeGemnasiumRecord(record2, ecosystem, slugPrefix) {
|
|
|
33846
33907
|
const advisoryId = typeof r.identifier === "string" && r.identifier.length > 0 ? r.identifier : identifiers[0] ?? null;
|
|
33847
33908
|
if (!advisoryId) return [];
|
|
33848
33909
|
const fixedVersions = stringArray(r.fixed_versions);
|
|
33849
|
-
const parsed = parseAffectedRange(typeof r.affected_range === "string" ? r.affected_range : "", fixedVersions);
|
|
33910
|
+
const parsed = parseAffectedRange(typeof r.affected_range === "string" ? r.affected_range : "", fixedVersions, ecosystem);
|
|
33850
33911
|
if (parsed.ranges.length === 0 && parsed.versions.length === 0) return [];
|
|
33851
33912
|
const severity = severityFromCvss(
|
|
33852
33913
|
typeof r.cvss_v3 === "string" ? r.cvss_v3 : null,
|
|
@@ -33891,13 +33952,15 @@ function isRetractedUpstream(record2) {
|
|
|
33891
33952
|
return description.includes(phrase);
|
|
33892
33953
|
});
|
|
33893
33954
|
}
|
|
33894
|
-
function parseAffectedRange(affectedRange, fixedVersions) {
|
|
33955
|
+
function parseAffectedRange(affectedRange, fixedVersions, ecosystem) {
|
|
33895
33956
|
const ranges = [];
|
|
33896
33957
|
const versions = [];
|
|
33897
33958
|
const trimmed = affectedRange.trim();
|
|
33898
|
-
const disjuncts = trimmed.length > 0 ? trimmed.split("||").map(trimToken).filter(nonEmpty) : []
|
|
33959
|
+
const disjuncts = (trimmed.length > 0 ? trimmed.split("||").map(trimToken).filter(nonEmpty) : []).map(function canonical(disjunct) {
|
|
33960
|
+
return canonicaliseRange(disjunct, ecosystem);
|
|
33961
|
+
}).filter(isNotNull).map(trimToken).filter(nonEmpty);
|
|
33899
33962
|
for (const disjunct of disjuncts) {
|
|
33900
|
-
const interval = parseDisjunct(disjunct);
|
|
33963
|
+
const interval = parseDisjunct(disjunct, ecosystem);
|
|
33901
33964
|
if (!interval) continue;
|
|
33902
33965
|
if (interval.exact !== null) {
|
|
33903
33966
|
versions.push(interval.exact);
|
|
@@ -33905,31 +33968,29 @@ function parseAffectedRange(affectedRange, fixedVersions) {
|
|
|
33905
33968
|
ranges.push(toRange(interval.introduced, interval.introducedExclusive, interval.fixed, interval.lastAffected));
|
|
33906
33969
|
}
|
|
33907
33970
|
}
|
|
33908
|
-
if (versions.length === 0 && ranges.
|
|
33971
|
+
if (versions.length === 0 && !ranges.some(canMatchSomething)) return { ranges: [], versions: [] };
|
|
33909
33972
|
const only = ranges[0];
|
|
33910
33973
|
const authoritativeFixed = fixedVersions[0];
|
|
33911
|
-
if (ranges.length === 1 && versions.length === 0 && only && fixedVersions.length === 1 && authoritativeFixed !== void 0) {
|
|
33974
|
+
if (ranges.length === 1 && versions.length === 0 && only && fixedVersions.length === 1 && authoritativeFixed !== void 0 && compareVersions(authoritativeFixed, only.introduced) > 0) {
|
|
33912
33975
|
ranges[0] = toRange(only.introduced, only.introducedExclusive === true, authoritativeFixed, null);
|
|
33913
33976
|
}
|
|
33914
|
-
|
|
33977
|
+
const highestFixed = highestVersion(fixedVersions);
|
|
33978
|
+
const bounded = [];
|
|
33979
|
+
for (const range of ranges) {
|
|
33980
|
+
const openEnded = range.fixed === null && range.lastAffected === null;
|
|
33981
|
+
bounded.push(highestFixed !== null && openEnded && compareVersions(highestFixed, range.introduced) > 0 ? toRange(range.introduced, range.introducedExclusive === true, highestFixed, null) : range);
|
|
33982
|
+
}
|
|
33983
|
+
return { ranges: bounded, versions };
|
|
33915
33984
|
}
|
|
33916
33985
|
function toRange(introduced, introducedExclusive, fixed, lastAffected) {
|
|
33917
33986
|
const range = { introduced, fixed, lastAffected };
|
|
33918
33987
|
if (introducedExclusive) range.introducedExclusive = true;
|
|
33919
33988
|
return range;
|
|
33920
33989
|
}
|
|
33921
|
-
function
|
|
33922
|
-
if (range.lastAffected !== null) {
|
|
33923
|
-
return range.introducedExclusive === true && range.lastAffected === range.introduced;
|
|
33924
|
-
}
|
|
33925
|
-
if (range.fixed === null) return false;
|
|
33926
|
-
if (range.fixed === range.introduced) return true;
|
|
33927
|
-
return isZeroVersion(range.introduced) && isZeroVersion(range.fixed);
|
|
33928
|
-
}
|
|
33929
|
-
function parseDisjunct(disjunct) {
|
|
33990
|
+
function parseDisjunct(disjunct, ecosystem) {
|
|
33930
33991
|
const first = disjunct[0];
|
|
33931
33992
|
if (first === "(" || first === "[") return parseIntervalNotation(disjunct);
|
|
33932
|
-
return parseComparatorForm(disjunct);
|
|
33993
|
+
return parseComparatorForm(disjunct, ecosystem);
|
|
33933
33994
|
}
|
|
33934
33995
|
function parseIntervalNotation(disjunct) {
|
|
33935
33996
|
const open = disjunct[0];
|
|
@@ -33944,6 +34005,7 @@ function parseIntervalNotation(disjunct) {
|
|
|
33944
34005
|
const lo = inner.slice(0, comma).trim();
|
|
33945
34006
|
const hi = inner.slice(comma + 1).trim();
|
|
33946
34007
|
const hasUpper = hi.length > 0;
|
|
34008
|
+
if (lo.length === 0 && !hasUpper) return null;
|
|
33947
34009
|
return {
|
|
33948
34010
|
introduced: lo.length > 0 ? lo : "0",
|
|
33949
34011
|
// An open "(" excludes the lower bound — but only when one was actually given; "(,2.0.0)" has no
|
|
@@ -33954,17 +34016,18 @@ function parseIntervalNotation(disjunct) {
|
|
|
33954
34016
|
exact: null
|
|
33955
34017
|
};
|
|
33956
34018
|
}
|
|
33957
|
-
function parseComparatorForm(disjunct) {
|
|
33958
|
-
const tokens = disjunct.split(
|
|
33959
|
-
if (tokens.length === 0) return null;
|
|
34019
|
+
function parseComparatorForm(disjunct, ecosystem) {
|
|
34020
|
+
const tokens = bindOperators(disjunct.split(/[\s,]+/).filter(nonEmpty));
|
|
34021
|
+
if (!tokens || tokens.length === 0) return null;
|
|
33960
34022
|
let introduced = "0";
|
|
33961
34023
|
let introducedExclusive = false;
|
|
33962
34024
|
let fixed = null;
|
|
33963
34025
|
let lastAffected = null;
|
|
33964
34026
|
for (const token of tokens) {
|
|
33965
|
-
const op = readOperator(token);
|
|
34027
|
+
const op = readOperator(token, ecosystem);
|
|
33966
34028
|
if (!op) return null;
|
|
33967
34029
|
if (op.operator === "=") {
|
|
34030
|
+
if (tokens.length > 1) return null;
|
|
33968
34031
|
return { introduced: "0", introducedExclusive: false, fixed: null, lastAffected: null, exact: op.version };
|
|
33969
34032
|
}
|
|
33970
34033
|
if (op.operator === ">=" || op.operator === ">") {
|
|
@@ -33980,16 +34043,37 @@ function parseComparatorForm(disjunct) {
|
|
|
33980
34043
|
}
|
|
33981
34044
|
return { introduced, introducedExclusive, fixed, lastAffected, exact: null };
|
|
33982
34045
|
}
|
|
34046
|
+
var NAKED_OPERATOR = /^(>=|<=|>|<|=)$/;
|
|
34047
|
+
function bindOperators(tokens) {
|
|
34048
|
+
const bound = [];
|
|
34049
|
+
let pending = null;
|
|
34050
|
+
for (const token of tokens) {
|
|
34051
|
+
if (pending !== null) {
|
|
34052
|
+
bound.push(pending + token);
|
|
34053
|
+
pending = null;
|
|
34054
|
+
} else if (NAKED_OPERATOR.test(token)) {
|
|
34055
|
+
pending = token;
|
|
34056
|
+
} else {
|
|
34057
|
+
bound.push(token);
|
|
34058
|
+
}
|
|
34059
|
+
}
|
|
34060
|
+
return pending === null ? bound : null;
|
|
34061
|
+
}
|
|
33983
34062
|
var BARE_VERSION = /^[0-9]+(\.[0-9]+)*([-+][0-9A-Za-z.-]*)?$/;
|
|
33984
|
-
function readOperator(token) {
|
|
33985
|
-
if (token.startsWith(">=")) return
|
|
33986
|
-
if (token.startsWith("<=")) return
|
|
33987
|
-
if (token.startsWith(">")) return
|
|
33988
|
-
if (token.startsWith("<")) return
|
|
33989
|
-
if (token.startsWith("=")) return
|
|
34063
|
+
function readOperator(token, ecosystem) {
|
|
34064
|
+
if (token.startsWith(">=")) return buildOperator(">=", token.slice(2), ecosystem);
|
|
34065
|
+
if (token.startsWith("<=")) return buildOperator("<=", token.slice(2), ecosystem);
|
|
34066
|
+
if (token.startsWith(">")) return buildOperator(">", token.slice(1), ecosystem);
|
|
34067
|
+
if (token.startsWith("<")) return buildOperator("<", token.slice(1), ecosystem);
|
|
34068
|
+
if (token.startsWith("=")) return buildOperator("=", token.slice(1), ecosystem);
|
|
33990
34069
|
const bare = stripV(token);
|
|
33991
34070
|
return BARE_VERSION.test(bare) ? { operator: "=", version: bare } : null;
|
|
33992
34071
|
}
|
|
34072
|
+
function buildOperator(operator, rawVersion, ecosystem) {
|
|
34073
|
+
const version2 = stripV(rawVersion);
|
|
34074
|
+
if (getEcosystem(ecosystem)?.comparator === "semver" && !BARE_VERSION.test(version2)) return null;
|
|
34075
|
+
return { operator, version: version2 };
|
|
34076
|
+
}
|
|
33993
34077
|
function stripV(raw) {
|
|
33994
34078
|
const t = raw.trim();
|
|
33995
34079
|
return t.startsWith("v") || t.startsWith("V") ? t.slice(1) : t;
|
|
@@ -34012,6 +34096,9 @@ function trimToken(s) {
|
|
|
34012
34096
|
function nonEmpty(s) {
|
|
34013
34097
|
return s.length > 0;
|
|
34014
34098
|
}
|
|
34099
|
+
function isNotNull(value) {
|
|
34100
|
+
return value !== null;
|
|
34101
|
+
}
|
|
34015
34102
|
|
|
34016
34103
|
// ../../packages/feeds/src/gemnasium/feed.ts
|
|
34017
34104
|
var DEFAULT_API_BASE = "https://gitlab.com/api/v4/projects/gitlab-org%2Fsecurity-products%2Fgemnasium-db";
|
|
@@ -34106,8 +34193,7 @@ function advisoryIdFromPath(path) {
|
|
|
34106
34193
|
const file2 = segments[segments.length - 1];
|
|
34107
34194
|
if (!file2) return null;
|
|
34108
34195
|
const dot = file2.lastIndexOf(".");
|
|
34109
|
-
|
|
34110
|
-
return id.length > 0 ? id : null;
|
|
34196
|
+
return dot > 0 ? file2.slice(0, dot) : file2;
|
|
34111
34197
|
}
|
|
34112
34198
|
async function* streamGemnasiumArchive(ref, onProgress, options) {
|
|
34113
34199
|
const download = await openDownloadStream(archiveUrl(ref), onProgress, options);
|
|
@@ -34255,7 +34341,7 @@ function createRowWriter(path) {
|
|
|
34255
34341
|
let rowCount = 0;
|
|
34256
34342
|
let failed = null;
|
|
34257
34343
|
done.catch(function capture(err) {
|
|
34258
|
-
failed =
|
|
34344
|
+
failed = asError(err);
|
|
34259
34345
|
});
|
|
34260
34346
|
async function push(chunk, added) {
|
|
34261
34347
|
if (failed) throw failed;
|
|
@@ -34403,10 +34489,6 @@ async function loadCacheForPackages(cacheDir, ecosystem, packageNames, sources)
|
|
|
34403
34489
|
}
|
|
34404
34490
|
return { osv, gemnasium };
|
|
34405
34491
|
}
|
|
34406
|
-
function cacheEcosystemKey(ecosystem) {
|
|
34407
|
-
const def = getEcosystem(ecosystem);
|
|
34408
|
-
return def ? def.osvEcosystem : ecosystem;
|
|
34409
|
-
}
|
|
34410
34492
|
function toOsvAdvisory(row) {
|
|
34411
34493
|
return {
|
|
34412
34494
|
advisoryId: row.advisoryId,
|
|
@@ -34651,15 +34733,18 @@ async function seedGemnasium(options, meta3, item) {
|
|
|
34651
34733
|
}
|
|
34652
34734
|
async function refreshGemnasium(options, meta3, item) {
|
|
34653
34735
|
const state = getSourceState(meta3, "gemnasium", item.ecosystem);
|
|
34654
|
-
|
|
34655
|
-
|
|
34656
|
-
if (headSha && storedSha === headSha) {
|
|
34657
|
-
touch(meta3, "gemnasium", item.ecosystem);
|
|
34658
|
-
return { source: "gemnasium", ecosystem: item.ecosystem, status: "unchanged", rowCount: state?.recordCount ?? 0, message: null };
|
|
34736
|
+
if (!state || !state.headSha) {
|
|
34737
|
+
return await seedGemnasium(options, meta3, { ...item, kind: "seed" });
|
|
34659
34738
|
}
|
|
34660
|
-
|
|
34739
|
+
const storedSha = state.headSha;
|
|
34740
|
+
const headSha = await fetchGemnasiumHeadSha(fetchOptionsFor(options, item));
|
|
34741
|
+
if (!headSha) {
|
|
34661
34742
|
return await seedGemnasium(options, meta3, { ...item, kind: "seed" });
|
|
34662
34743
|
}
|
|
34744
|
+
if (storedSha === headSha) {
|
|
34745
|
+
touch(meta3, "gemnasium", item.ecosystem);
|
|
34746
|
+
return { source: "gemnasium", ecosystem: item.ecosystem, status: "unchanged", rowCount: state.recordCount, message: null };
|
|
34747
|
+
}
|
|
34663
34748
|
const changed = await fetchGemnasiumChangedPaths(storedSha, headSha, fetchOptionsFor(options, item));
|
|
34664
34749
|
if (changed.status === "unavailable") {
|
|
34665
34750
|
return await seedGemnasium(options, meta3, { ...item, kind: "seed" });
|
|
@@ -34671,8 +34756,8 @@ async function refreshGemnasium(options, meta3, item) {
|
|
|
34671
34756
|
return pathEcosystemMatches(path, item.ecosystem);
|
|
34672
34757
|
});
|
|
34673
34758
|
if (relevant.length === 0 && removed.length === 0) {
|
|
34674
|
-
touchGemnasiumSha(
|
|
34675
|
-
return { source: "gemnasium", ecosystem: item.ecosystem, status: "unchanged", rowCount: state
|
|
34759
|
+
touchGemnasiumSha(state, headSha);
|
|
34760
|
+
return { source: "gemnasium", ecosystem: item.ecosystem, status: "unchanged", rowCount: state.recordCount, message: null };
|
|
34676
34761
|
}
|
|
34677
34762
|
const dropAdvisoryIds = /* @__PURE__ */ new Set();
|
|
34678
34763
|
for (const path of removed.concat(relevant)) {
|
|
@@ -34713,9 +34798,7 @@ function touch(meta3, source, ecosystem, etag) {
|
|
|
34713
34798
|
state.refreshedAt = Date.now();
|
|
34714
34799
|
if (etag !== void 0) state.etag = etag;
|
|
34715
34800
|
}
|
|
34716
|
-
function touchGemnasiumSha(
|
|
34717
|
-
const state = getSourceState(meta3, "gemnasium", ecosystem);
|
|
34718
|
-
if (!state) return;
|
|
34801
|
+
function touchGemnasiumSha(state, headSha) {
|
|
34719
34802
|
state.refreshedAt = Date.now();
|
|
34720
34803
|
state.headSha = headSha;
|
|
34721
34804
|
}
|
|
@@ -34944,7 +35027,7 @@ async function applyConfigFile(options, explicitFlags) {
|
|
|
34944
35027
|
try {
|
|
34945
35028
|
parsed = JSON.parse(text);
|
|
34946
35029
|
} catch (err) {
|
|
34947
|
-
return "sentinello.config.json is not valid JSON: " + (err
|
|
35030
|
+
return "sentinello.config.json is not valid JSON: " + errText(err);
|
|
34948
35031
|
}
|
|
34949
35032
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return "sentinello.config.json must contain an object";
|
|
34950
35033
|
const config2 = parsed;
|
|
@@ -35535,8 +35618,8 @@ function createUi(options) {
|
|
|
35535
35618
|
|
|
35536
35619
|
// src/help.ts
|
|
35537
35620
|
var CLI_VERSION = (function resolveVersion() {
|
|
35538
|
-
if ("3.
|
|
35539
|
-
return "3.
|
|
35621
|
+
if ("3.4.0".length > 0) {
|
|
35622
|
+
return "3.4.0";
|
|
35540
35623
|
}
|
|
35541
35624
|
const fromEnv = process.env.SENTINELLO_VERSION;
|
|
35542
35625
|
if (fromEnv && fromEnv.trim().length > 0) return fromEnv.trim();
|
|
@@ -35814,7 +35897,7 @@ async function runScan(options, cacheDir, ui) {
|
|
|
35814
35897
|
try {
|
|
35815
35898
|
prompt = await resolvePrompt(options);
|
|
35816
35899
|
} catch (err) {
|
|
35817
|
-
ui.error("could not read prompt file: " + (err
|
|
35900
|
+
ui.error("could not read prompt file: " + errText(err));
|
|
35818
35901
|
return EXIT_ERROR;
|
|
35819
35902
|
}
|
|
35820
35903
|
const document2 = options.json ? renderJson(summary, options, generatedAt) : renderMarkdown(summary, options, prompt, generatedAt);
|