sentinello 3.3.2 → 3.5.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 +179 -136
- 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) {
|
|
@@ -13518,6 +13532,43 @@ function highestVersion(versions) {
|
|
|
13518
13532
|
return best;
|
|
13519
13533
|
}
|
|
13520
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
|
+
|
|
13521
13572
|
// ../../packages/versions/src/comparators/pep440.ts
|
|
13522
13573
|
var PRE_RANK = { a: 0, b: 1, rc: 2 };
|
|
13523
13574
|
var PEP440_RE = new RegExp(
|
|
@@ -13535,13 +13586,9 @@ function parsePep440(raw) {
|
|
|
13535
13586
|
const m = PEP440_RE.exec(raw.trim());
|
|
13536
13587
|
if (!m || !m.groups) return null;
|
|
13537
13588
|
const g = m.groups;
|
|
13538
|
-
if (!g.release) return null;
|
|
13539
13589
|
const release = g.release.split(".").map(function toInt(s) {
|
|
13540
13590
|
return parseInt(s, 10);
|
|
13541
13591
|
});
|
|
13542
|
-
if (release.some(function bad(n) {
|
|
13543
|
-
return Number.isNaN(n);
|
|
13544
|
-
})) return null;
|
|
13545
13592
|
let pre = null;
|
|
13546
13593
|
if (g.preL) {
|
|
13547
13594
|
pre = { letter: foldPreLetter(g.preL), n: g.preN ? parseInt(g.preN, 10) : 0 };
|
|
@@ -13597,8 +13644,8 @@ function cmpPre(a, b) {
|
|
|
13597
13644
|
const kb = preKind(b);
|
|
13598
13645
|
if (ka !== kb) return ka < kb ? -1 : 1;
|
|
13599
13646
|
if (ka !== 0 || !a.pre || !b.pre) return 0;
|
|
13600
|
-
const la = PRE_RANK[a.pre.letter]
|
|
13601
|
-
const lb = PRE_RANK[b.pre.letter]
|
|
13647
|
+
const la = PRE_RANK[a.pre.letter];
|
|
13648
|
+
const lb = PRE_RANK[b.pre.letter];
|
|
13602
13649
|
if (la !== lb) return la < lb ? -1 : 1;
|
|
13603
13650
|
if (a.pre.n !== b.pre.n) return a.pre.n < b.pre.n ? -1 : 1;
|
|
13604
13651
|
return 0;
|
|
@@ -13695,7 +13742,7 @@ function shouldKeep(finding) {
|
|
|
13695
13742
|
const installed = finding.installedVersion.trim();
|
|
13696
13743
|
const range = finding.vulnerableRange.trim();
|
|
13697
13744
|
if (!installed || !range) return true;
|
|
13698
|
-
if ((0,
|
|
13745
|
+
if ((0, import_semver7.validRange)(range) === null) return true;
|
|
13699
13746
|
const candidates = installed.split(/,\s*/).map(function trim(s) {
|
|
13700
13747
|
return s.trim();
|
|
13701
13748
|
}).filter(Boolean);
|
|
@@ -13703,7 +13750,7 @@ function shouldKeep(finding) {
|
|
|
13703
13750
|
for (const candidate of candidates) {
|
|
13704
13751
|
const cleaned = normalizeVersion(candidate);
|
|
13705
13752
|
if (cleaned === null) return true;
|
|
13706
|
-
if ((0,
|
|
13753
|
+
if ((0, import_semver7.satisfies)(cleaned, range, { includePrerelease: true })) return true;
|
|
13707
13754
|
}
|
|
13708
13755
|
return false;
|
|
13709
13756
|
}
|
|
@@ -28192,7 +28239,7 @@ function date4(params) {
|
|
|
28192
28239
|
config(en_default());
|
|
28193
28240
|
|
|
28194
28241
|
// ../../packages/scanners/src/version-fix.ts
|
|
28195
|
-
var
|
|
28242
|
+
var import_semver8 = __toESM(require_semver2());
|
|
28196
28243
|
var VERSION_LITERAL_RE = /\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?/g;
|
|
28197
28244
|
function parseRangeSafely(input) {
|
|
28198
28245
|
if (!input) return null;
|
|
@@ -28200,7 +28247,7 @@ function parseRangeSafely(input) {
|
|
|
28200
28247
|
if (!trimmed) return null;
|
|
28201
28248
|
if (trimmed === "<0.0.0") return null;
|
|
28202
28249
|
try {
|
|
28203
|
-
return new
|
|
28250
|
+
return new import_semver8.Range(trimmed, { includePrerelease: false });
|
|
28204
28251
|
} catch {
|
|
28205
28252
|
return null;
|
|
28206
28253
|
}
|
|
@@ -28211,13 +28258,12 @@ function extractLiteralCandidates(input) {
|
|
|
28211
28258
|
if (!matches) return [];
|
|
28212
28259
|
const out = [];
|
|
28213
28260
|
for (const m of matches) {
|
|
28214
|
-
if ((0,
|
|
28261
|
+
if ((0, import_semver8.valid)(m)) out.push(m);
|
|
28215
28262
|
}
|
|
28216
28263
|
return out;
|
|
28217
28264
|
}
|
|
28218
28265
|
function bumpPatch(v) {
|
|
28219
|
-
const sv = (0,
|
|
28220
|
-
if (!sv) return null;
|
|
28266
|
+
const sv = (0, import_semver8.coerce)(v);
|
|
28221
28267
|
return sv.major + "." + sv.minor + "." + (sv.patch + 1);
|
|
28222
28268
|
}
|
|
28223
28269
|
function extractRangeLowerBounds(range) {
|
|
@@ -28227,13 +28273,12 @@ function extractRangeLowerBounds(range) {
|
|
|
28227
28273
|
for (const c of conjuncts) {
|
|
28228
28274
|
if (!c.semver || !c.semver.version) continue;
|
|
28229
28275
|
const v = c.semver.version;
|
|
28230
|
-
if (!(0, import_semver6.valid)(v)) continue;
|
|
28231
28276
|
const op = c.operator;
|
|
28232
28277
|
if (op === ">=" || op === "=" || op === "") {
|
|
28233
|
-
if (!candidate || (0,
|
|
28278
|
+
if (!candidate || (0, import_semver8.gt)(v, candidate)) candidate = v;
|
|
28234
28279
|
} else if (op === ">") {
|
|
28235
28280
|
const inc = bumpPatch(v);
|
|
28236
|
-
if (
|
|
28281
|
+
if (!candidate || (0, import_semver8.gt)(inc, candidate)) candidate = inc;
|
|
28237
28282
|
}
|
|
28238
28283
|
}
|
|
28239
28284
|
if (candidate) out.push(candidate);
|
|
@@ -28246,13 +28291,11 @@ function extractRangeUpperBoundsBeyond(range) {
|
|
|
28246
28291
|
for (const c of conjuncts) {
|
|
28247
28292
|
if (!c.semver || !c.semver.version) continue;
|
|
28248
28293
|
const v = c.semver.version;
|
|
28249
|
-
if (!(0, import_semver6.valid)(v)) continue;
|
|
28250
28294
|
const op = c.operator;
|
|
28251
28295
|
if (op === "<") {
|
|
28252
28296
|
out.push(v);
|
|
28253
28297
|
} else if (op === "<=") {
|
|
28254
|
-
|
|
28255
|
-
if (inc) out.push(inc);
|
|
28298
|
+
out.push(bumpPatch(v));
|
|
28256
28299
|
}
|
|
28257
28300
|
}
|
|
28258
28301
|
}
|
|
@@ -28265,8 +28308,8 @@ function pickHighestInstalled(installed) {
|
|
|
28265
28308
|
for (const raw of parts) {
|
|
28266
28309
|
const part = raw.trim();
|
|
28267
28310
|
if (!part) continue;
|
|
28268
|
-
if (!(0,
|
|
28269
|
-
if (!highest || (0,
|
|
28311
|
+
if (!(0, import_semver8.valid)(part)) continue;
|
|
28312
|
+
if (!highest || (0, import_semver8.gt)(part, highest)) highest = part;
|
|
28270
28313
|
}
|
|
28271
28314
|
return highest;
|
|
28272
28315
|
}
|
|
@@ -28288,10 +28331,10 @@ function pickSafeFixVersion(args) {
|
|
|
28288
28331
|
if (candidates.size === 0) return null;
|
|
28289
28332
|
let best = null;
|
|
28290
28333
|
for (const v of candidates) {
|
|
28291
|
-
if (patchedRange && !(0,
|
|
28292
|
-
if (vulnRange && (0,
|
|
28293
|
-
if (installedFloor && !(0,
|
|
28294
|
-
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;
|
|
28295
28338
|
}
|
|
28296
28339
|
return best;
|
|
28297
28340
|
}
|
|
@@ -28410,17 +28453,15 @@ function classifyPackageManagerNotFound(stderr, packageManager) {
|
|
|
28410
28453
|
return re1.test(stderr) || re2.test(stderr);
|
|
28411
28454
|
}
|
|
28412
28455
|
function pickAuditCommand(lockfile) {
|
|
28413
|
-
if (lockfile.packageManager === "pnpm") return "pnpm audit --json";
|
|
28414
|
-
if (lockfile.packageManager === "npm") return "npm audit --json";
|
|
28415
|
-
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"];
|
|
28416
28459
|
}
|
|
28417
28460
|
function parseYarnMajor(value) {
|
|
28418
28461
|
if (typeof value !== "string") return null;
|
|
28419
28462
|
const match = value.trim().match(/^yarn@(\d+)(?:\.|$)/);
|
|
28420
28463
|
if (!match || !match[1]) return null;
|
|
28421
|
-
|
|
28422
|
-
if (Number.isNaN(parsed)) return null;
|
|
28423
|
-
return parsed;
|
|
28464
|
+
return parseInt(match[1], 10);
|
|
28424
28465
|
}
|
|
28425
28466
|
function unauditableResult(reasonCode, reason, startedAt, rawJson) {
|
|
28426
28467
|
return {
|
|
@@ -28564,9 +28605,7 @@ function normalizeAuditOutput(parsed, installedVersions, classifier) {
|
|
|
28564
28605
|
const findings = [];
|
|
28565
28606
|
let hadVulnerabilityWithoutConcreteAdvisory = false;
|
|
28566
28607
|
const vulns = parsed.vulnerabilities ?? {};
|
|
28567
|
-
for (const packageName of Object.
|
|
28568
|
-
const vuln = vulns[packageName];
|
|
28569
|
-
if (!vuln) continue;
|
|
28608
|
+
for (const [packageName, vuln] of Object.entries(vulns)) {
|
|
28570
28609
|
if (!vuln.via || vuln.via.length === 0) {
|
|
28571
28610
|
hadVulnerabilityWithoutConcreteAdvisory = true;
|
|
28572
28611
|
continue;
|
|
@@ -28714,10 +28753,8 @@ async function loadLockfileSnapshot(projectPath, lockfile) {
|
|
|
28714
28753
|
if (!validation.success) return empty;
|
|
28715
28754
|
const installedVersions = /* @__PURE__ */ new Map();
|
|
28716
28755
|
const packages = validation.data.packages || {};
|
|
28717
|
-
for (const nodePath of Object.
|
|
28756
|
+
for (const [nodePath, entry] of Object.entries(packages)) {
|
|
28718
28757
|
if (!nodePath) continue;
|
|
28719
|
-
const entry = packages[nodePath];
|
|
28720
|
-
if (!entry) continue;
|
|
28721
28758
|
if (entry.version) {
|
|
28722
28759
|
installedVersions.set(nodePath, entry.version);
|
|
28723
28760
|
}
|
|
@@ -28869,9 +28906,6 @@ function executeSpawnAndCapture(input, resolve5) {
|
|
|
28869
28906
|
child.stderr.on("data", onSpawnStderrData.bind(null, state));
|
|
28870
28907
|
child.on("error", onSpawnError.bind(null, ctx));
|
|
28871
28908
|
child.on("close", onSpawnClose.bind(null, ctx));
|
|
28872
|
-
if (input.opts.stdin && child.stdin) {
|
|
28873
|
-
child.stdin.end(input.opts.stdin);
|
|
28874
|
-
}
|
|
28875
28909
|
}
|
|
28876
28910
|
function spawnAndCapture(deps, cmd, args, opts) {
|
|
28877
28911
|
return new Promise(executeSpawnAndCapture.bind(null, { deps, cmd, args, opts }));
|
|
@@ -28931,17 +28965,13 @@ async function runNpmAudit(projectPath, ctx, deps = REAL_DEPS) {
|
|
|
28931
28965
|
let execCmd;
|
|
28932
28966
|
let execArgs;
|
|
28933
28967
|
if (wrapWithNvm) {
|
|
28934
|
-
const wrapped = buildBashWrappedCommand(rawCmd);
|
|
28968
|
+
const wrapped = buildBashWrappedCommand(rawCmd.join(" "));
|
|
28935
28969
|
execCmd = wrapped.cmd;
|
|
28936
28970
|
execArgs = wrapped.args;
|
|
28937
28971
|
} else {
|
|
28938
|
-
const
|
|
28939
|
-
const head = parts[0];
|
|
28940
|
-
if (!head) {
|
|
28941
|
-
return errorResult("audit_unknown_failure", "failed to construct audit command", startedAt, "");
|
|
28942
|
-
}
|
|
28972
|
+
const [head, ...rest] = rawCmd;
|
|
28943
28973
|
execCmd = head;
|
|
28944
|
-
execArgs =
|
|
28974
|
+
execArgs = rest;
|
|
28945
28975
|
}
|
|
28946
28976
|
const spawnResult = await spawnAndCapture(deps, execCmd, execArgs, {
|
|
28947
28977
|
cwd: projectPath,
|
|
@@ -28987,11 +29017,7 @@ async function runNpmAudit(projectPath, ctx, deps = REAL_DEPS) {
|
|
|
28987
29017
|
try {
|
|
28988
29018
|
parsedJson = JSON.parse(rawText);
|
|
28989
29019
|
} catch (err) {
|
|
28990
|
-
|
|
28991
|
-
if (err instanceof Error) {
|
|
28992
|
-
reason = `audit JSON parse failed: ${err.message}`;
|
|
28993
|
-
}
|
|
28994
|
-
return errorResult("audit_parse_error", reason, startedAt, rawText);
|
|
29020
|
+
return errorResult("audit_parse_error", `audit JSON parse failed: ${errText(err)}`, startedAt, rawText);
|
|
28995
29021
|
}
|
|
28996
29022
|
if (lockfile.packageManager === "pnpm") {
|
|
28997
29023
|
const pnpmValidation = pnpmAuditSchema.safeParse(parsedJson);
|
|
@@ -29055,9 +29081,7 @@ function reachableFrom(roots, adjacency) {
|
|
|
29055
29081
|
stack.push(root);
|
|
29056
29082
|
}
|
|
29057
29083
|
}
|
|
29058
|
-
|
|
29059
|
-
const node = stack.pop();
|
|
29060
|
-
if (node === void 0) break;
|
|
29084
|
+
for (let node = stack.pop(); node !== void 0; node = stack.pop()) {
|
|
29061
29085
|
const children = adjacency.get(node);
|
|
29062
29086
|
if (!children) continue;
|
|
29063
29087
|
for (const child of children) {
|
|
@@ -32407,7 +32431,7 @@ function parsePnpmV9(root) {
|
|
|
32407
32431
|
if (isProd) existing.scope.isProd = true;
|
|
32408
32432
|
if (isDev) existing.scope.isDev = true;
|
|
32409
32433
|
if (!isOptional) existing.scope.isOptional = false;
|
|
32410
|
-
|
|
32434
|
+
existing.depPaths.push(key);
|
|
32411
32435
|
} else {
|
|
32412
32436
|
byId.set(id, {
|
|
32413
32437
|
ecosystem: NPM_ECOSYSTEM2,
|
|
@@ -32429,7 +32453,6 @@ function parsePnpmLegacy(root) {
|
|
|
32429
32453
|
const parsed = parseDepKey(key);
|
|
32430
32454
|
if (!parsed) continue;
|
|
32431
32455
|
const version2 = entry.version || parsed.version;
|
|
32432
|
-
if (!version2) continue;
|
|
32433
32456
|
const isDev = entry.dev === true;
|
|
32434
32457
|
out.push({
|
|
32435
32458
|
ecosystem: NPM_ECOSYSTEM2,
|
|
@@ -32829,7 +32852,6 @@ function classifySkip(absolutePath, rootPath, layers, excludeMatcher, hasExclude
|
|
|
32829
32852
|
for (let i = layers.length - 1; i >= 0; i--) {
|
|
32830
32853
|
const layer = layers[i];
|
|
32831
32854
|
const rel = path.relative(layer.baseDir, absolutePath);
|
|
32832
|
-
if (!rel || rel.startsWith("..")) continue;
|
|
32833
32855
|
if (!layer.matcher.ignores(rel) && !layer.matcher.ignores(rel + "/")) continue;
|
|
32834
32856
|
if (layer.hasSentinelloIgnore && !layer.hasGitignore) return "sentinelloignore";
|
|
32835
32857
|
if (layer.hasGitignore && !layer.hasSentinelloIgnore) return "gitignore";
|
|
@@ -32906,9 +32928,7 @@ function detectPackageManager(dir) {
|
|
|
32906
32928
|
return "unknown";
|
|
32907
32929
|
}
|
|
32908
32930
|
function basenameOf(dir) {
|
|
32909
|
-
|
|
32910
|
-
const parts = abs.split("/");
|
|
32911
|
-
return parts[parts.length - 1] || abs;
|
|
32931
|
+
return path.basename(path.resolve(dir));
|
|
32912
32932
|
}
|
|
32913
32933
|
function readNvmrcVersion(dir) {
|
|
32914
32934
|
const nvmrcPath = path.join(dir, ".nvmrc");
|
|
@@ -32926,7 +32946,7 @@ function readGitBranch(dir, rootPath) {
|
|
|
32926
32946
|
try {
|
|
32927
32947
|
const head = fs.readFileSync(path.join(gitDir, "HEAD"), "utf8").trim();
|
|
32928
32948
|
const ref = head.match(/^ref:\s*refs\/heads\/(.+)$/);
|
|
32929
|
-
if (ref && ref[1]) return ref[1].trim()
|
|
32949
|
+
if (ref && ref[1]) return ref[1].trim();
|
|
32930
32950
|
if (/^[0-9a-f]{40}$/i.test(head)) return head.slice(0, 7);
|
|
32931
32951
|
return null;
|
|
32932
32952
|
} catch {
|
|
@@ -33077,7 +33097,7 @@ function rangesToDisplay(ranges, exactVersions) {
|
|
|
33077
33097
|
const parts = [];
|
|
33078
33098
|
for (const v of exactVersions) parts.push("=" + v);
|
|
33079
33099
|
for (const range of ranges) parts.push(formatRange(range, DISPLAY_FORMAT));
|
|
33080
|
-
return parts.
|
|
33100
|
+
return parts.join(" || ");
|
|
33081
33101
|
}
|
|
33082
33102
|
function vulnerableRangeForFix(ranges) {
|
|
33083
33103
|
return formatRanges(ranges, SEMVER_FORMAT);
|
|
@@ -33129,7 +33149,6 @@ function matchPackages(packages, lookup, isSeeded2, isEnabled) {
|
|
|
33129
33149
|
if (!comparator) continue;
|
|
33130
33150
|
const acceptedRangeTypes = acceptedRangeTypesForEcosystem(ecosystem) ?? [];
|
|
33131
33151
|
const names = uniqueNames(pkgs);
|
|
33132
|
-
if (names.length === 0) continue;
|
|
33133
33152
|
const byPackageRaw = lookup(ecosystem, names);
|
|
33134
33153
|
const byPackage = /* @__PURE__ */ new Map();
|
|
33135
33154
|
for (const [name, advisories] of byPackageRaw.entries()) {
|
|
@@ -33236,7 +33255,6 @@ function matchPackages2(packages, lookup, isEnabled) {
|
|
|
33236
33255
|
const comparator = comparatorForEcosystem(ecosystem);
|
|
33237
33256
|
if (!comparator) continue;
|
|
33238
33257
|
const names = uniqueNames2(pkgs);
|
|
33239
|
-
if (names.length === 0) continue;
|
|
33240
33258
|
const byPackageRaw = lookup(ecosystem, names);
|
|
33241
33259
|
const byPackage = /* @__PURE__ */ new Map();
|
|
33242
33260
|
for (const [name, advisories] of byPackageRaw.entries()) {
|
|
@@ -33365,10 +33383,6 @@ function signalFor(options, fallbackTimeoutMs) {
|
|
|
33365
33383
|
if (options && options.abortSignal) return AbortSignal.any([options.abortSignal, timeout]);
|
|
33366
33384
|
return timeout;
|
|
33367
33385
|
}
|
|
33368
|
-
function errText(err) {
|
|
33369
|
-
if (err instanceof Error) return err.message;
|
|
33370
|
-
return String(err);
|
|
33371
|
-
}
|
|
33372
33386
|
function isFastTransientStatus(status) {
|
|
33373
33387
|
if (status === 408 || status === 425 || status === 429) return true;
|
|
33374
33388
|
return status >= 500 && status < 600;
|
|
@@ -33555,7 +33569,7 @@ function normalizeOsvRecord(record2, ecosystem) {
|
|
|
33555
33569
|
if (!pkg2 || pkg2.ecosystem !== ecosystem) continue;
|
|
33556
33570
|
const packageName = typeof pkg2.name === "string" ? pkg2.name : null;
|
|
33557
33571
|
if (!packageName) continue;
|
|
33558
|
-
const ranges = extractRanges(affected.ranges, affected.database_specific?.last_known_affected_version_range);
|
|
33572
|
+
const ranges = extractRanges(affected.ranges, affected.database_specific?.last_known_affected_version_range, ecosystem);
|
|
33559
33573
|
const versions = extractVersions(affected.versions);
|
|
33560
33574
|
const existing = byPackage.get(packageName);
|
|
33561
33575
|
if (existing) {
|
|
@@ -33591,7 +33605,7 @@ function extractVersions(versions) {
|
|
|
33591
33605
|
}
|
|
33592
33606
|
return out;
|
|
33593
33607
|
}
|
|
33594
|
-
function extractRanges(ranges, lastKnownAffected) {
|
|
33608
|
+
function extractRanges(ranges, lastKnownAffected, ecosystem) {
|
|
33595
33609
|
if (!Array.isArray(ranges)) return [];
|
|
33596
33610
|
const out = [];
|
|
33597
33611
|
for (const range of ranges) {
|
|
@@ -33604,18 +33618,20 @@ function extractRanges(ranges, lastKnownAffected) {
|
|
|
33604
33618
|
if (typeof event.introduced === "string") {
|
|
33605
33619
|
if (introduced !== null) {
|
|
33606
33620
|
out.push({ type: type2, introduced, fixed: null, lastAffected });
|
|
33607
|
-
lastAffected = null;
|
|
33608
33621
|
}
|
|
33609
|
-
|
|
33622
|
+
lastAffected = null;
|
|
33623
|
+
introduced = !usesSemver(type2, ecosystem) || normalizeSemver(event.introduced) !== null ? event.introduced : null;
|
|
33610
33624
|
continue;
|
|
33611
33625
|
}
|
|
33612
33626
|
if (typeof event.fixed === "string" && introduced !== null) {
|
|
33627
|
+
if (usesSemver(type2, ecosystem) && normalizeSemver(event.fixed) === null) continue;
|
|
33613
33628
|
out.push({ type: type2, introduced, fixed: event.fixed, lastAffected: null });
|
|
33614
33629
|
introduced = null;
|
|
33615
33630
|
lastAffected = null;
|
|
33616
33631
|
continue;
|
|
33617
33632
|
}
|
|
33618
33633
|
if (typeof event.last_affected === "string" && introduced !== null) {
|
|
33634
|
+
if (usesSemver(type2, ecosystem) && normalizeSemver(event.last_affected) === null) continue;
|
|
33619
33635
|
lastAffected = event.last_affected;
|
|
33620
33636
|
}
|
|
33621
33637
|
}
|
|
@@ -33623,21 +33639,32 @@ function extractRanges(ranges, lastKnownAffected) {
|
|
|
33623
33639
|
out.push({ type: type2, introduced, fixed: null, lastAffected });
|
|
33624
33640
|
}
|
|
33625
33641
|
}
|
|
33626
|
-
|
|
33642
|
+
const matchable = [];
|
|
33643
|
+
for (const range of out) {
|
|
33644
|
+
if (canRangeMatch(range, ecosystem)) matchable.push(range);
|
|
33645
|
+
}
|
|
33646
|
+
return boundOpenEndedRange(matchable, lastKnownAffected, ecosystem);
|
|
33627
33647
|
}
|
|
33628
|
-
function
|
|
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) {
|
|
33629
33656
|
if (ranges.length !== 1 || typeof lastKnownAffected !== "string") return ranges;
|
|
33630
33657
|
const text = lastKnownAffected.trim();
|
|
33631
33658
|
const inclusive = text.startsWith("<=");
|
|
33632
33659
|
if (!inclusive && !text.startsWith("<")) return ranges;
|
|
33633
33660
|
const version2 = text.slice(inclusive ? 2 : 1).trim();
|
|
33634
33661
|
if (version2.length === 0 || /[\s,|]/.test(version2)) return ranges;
|
|
33635
|
-
const
|
|
33636
|
-
|
|
33637
|
-
|
|
33638
|
-
|
|
33639
|
-
}
|
|
33640
|
-
return
|
|
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;
|
|
33641
33668
|
}
|
|
33642
33669
|
function pickSeverity2(r) {
|
|
33643
33670
|
const ds = r.database_specific && r.database_specific.severity;
|
|
@@ -33880,7 +33907,7 @@ function normalizeGemnasiumRecord(record2, ecosystem, slugPrefix) {
|
|
|
33880
33907
|
const advisoryId = typeof r.identifier === "string" && r.identifier.length > 0 ? r.identifier : identifiers[0] ?? null;
|
|
33881
33908
|
if (!advisoryId) return [];
|
|
33882
33909
|
const fixedVersions = stringArray(r.fixed_versions);
|
|
33883
|
-
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);
|
|
33884
33911
|
if (parsed.ranges.length === 0 && parsed.versions.length === 0) return [];
|
|
33885
33912
|
const severity = severityFromCvss(
|
|
33886
33913
|
typeof r.cvss_v3 === "string" ? r.cvss_v3 : null,
|
|
@@ -33925,13 +33952,15 @@ function isRetractedUpstream(record2) {
|
|
|
33925
33952
|
return description.includes(phrase);
|
|
33926
33953
|
});
|
|
33927
33954
|
}
|
|
33928
|
-
function parseAffectedRange(affectedRange, fixedVersions) {
|
|
33955
|
+
function parseAffectedRange(affectedRange, fixedVersions, ecosystem) {
|
|
33929
33956
|
const ranges = [];
|
|
33930
33957
|
const versions = [];
|
|
33931
33958
|
const trimmed = affectedRange.trim();
|
|
33932
|
-
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);
|
|
33933
33962
|
for (const disjunct of disjuncts) {
|
|
33934
|
-
const interval = parseDisjunct(disjunct);
|
|
33963
|
+
const interval = parseDisjunct(disjunct, ecosystem);
|
|
33935
33964
|
if (!interval) continue;
|
|
33936
33965
|
if (interval.exact !== null) {
|
|
33937
33966
|
versions.push(interval.exact);
|
|
@@ -33939,10 +33968,10 @@ function parseAffectedRange(affectedRange, fixedVersions) {
|
|
|
33939
33968
|
ranges.push(toRange(interval.introduced, interval.introducedExclusive, interval.fixed, interval.lastAffected));
|
|
33940
33969
|
}
|
|
33941
33970
|
}
|
|
33942
|
-
if (versions.length === 0 && ranges.
|
|
33971
|
+
if (versions.length === 0 && !ranges.some(canMatchSomething)) return { ranges: [], versions: [] };
|
|
33943
33972
|
const only = ranges[0];
|
|
33944
33973
|
const authoritativeFixed = fixedVersions[0];
|
|
33945
|
-
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) {
|
|
33946
33975
|
ranges[0] = toRange(only.introduced, only.introducedExclusive === true, authoritativeFixed, null);
|
|
33947
33976
|
}
|
|
33948
33977
|
const highestFixed = highestVersion(fixedVersions);
|
|
@@ -33958,18 +33987,10 @@ function toRange(introduced, introducedExclusive, fixed, lastAffected) {
|
|
|
33958
33987
|
if (introducedExclusive) range.introducedExclusive = true;
|
|
33959
33988
|
return range;
|
|
33960
33989
|
}
|
|
33961
|
-
function
|
|
33962
|
-
if (range.lastAffected !== null) {
|
|
33963
|
-
return range.introducedExclusive === true && range.lastAffected === range.introduced;
|
|
33964
|
-
}
|
|
33965
|
-
if (range.fixed === null) return false;
|
|
33966
|
-
if (range.fixed === range.introduced) return true;
|
|
33967
|
-
return isZeroVersion(range.introduced) && isZeroVersion(range.fixed);
|
|
33968
|
-
}
|
|
33969
|
-
function parseDisjunct(disjunct) {
|
|
33990
|
+
function parseDisjunct(disjunct, ecosystem) {
|
|
33970
33991
|
const first = disjunct[0];
|
|
33971
33992
|
if (first === "(" || first === "[") return parseIntervalNotation(disjunct);
|
|
33972
|
-
return parseComparatorForm(disjunct);
|
|
33993
|
+
return parseComparatorForm(disjunct, ecosystem);
|
|
33973
33994
|
}
|
|
33974
33995
|
function parseIntervalNotation(disjunct) {
|
|
33975
33996
|
const open = disjunct[0];
|
|
@@ -33984,6 +34005,7 @@ function parseIntervalNotation(disjunct) {
|
|
|
33984
34005
|
const lo = inner.slice(0, comma).trim();
|
|
33985
34006
|
const hi = inner.slice(comma + 1).trim();
|
|
33986
34007
|
const hasUpper = hi.length > 0;
|
|
34008
|
+
if (lo.length === 0 && !hasUpper) return null;
|
|
33987
34009
|
return {
|
|
33988
34010
|
introduced: lo.length > 0 ? lo : "0",
|
|
33989
34011
|
// An open "(" excludes the lower bound — but only when one was actually given; "(,2.0.0)" has no
|
|
@@ -33994,17 +34016,18 @@ function parseIntervalNotation(disjunct) {
|
|
|
33994
34016
|
exact: null
|
|
33995
34017
|
};
|
|
33996
34018
|
}
|
|
33997
|
-
function parseComparatorForm(disjunct) {
|
|
33998
|
-
const tokens = disjunct.split(/[\s,]+/).filter(nonEmpty);
|
|
33999
|
-
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;
|
|
34000
34022
|
let introduced = "0";
|
|
34001
34023
|
let introducedExclusive = false;
|
|
34002
34024
|
let fixed = null;
|
|
34003
34025
|
let lastAffected = null;
|
|
34004
34026
|
for (const token of tokens) {
|
|
34005
|
-
const op = readOperator(token);
|
|
34027
|
+
const op = readOperator(token, ecosystem);
|
|
34006
34028
|
if (!op) return null;
|
|
34007
34029
|
if (op.operator === "=") {
|
|
34030
|
+
if (tokens.length > 1) return null;
|
|
34008
34031
|
return { introduced: "0", introducedExclusive: false, fixed: null, lastAffected: null, exact: op.version };
|
|
34009
34032
|
}
|
|
34010
34033
|
if (op.operator === ">=" || op.operator === ">") {
|
|
@@ -34020,16 +34043,37 @@ function parseComparatorForm(disjunct) {
|
|
|
34020
34043
|
}
|
|
34021
34044
|
return { introduced, introducedExclusive, fixed, lastAffected, exact: null };
|
|
34022
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
|
+
}
|
|
34023
34062
|
var BARE_VERSION = /^[0-9]+(\.[0-9]+)*([-+][0-9A-Za-z.-]*)?$/;
|
|
34024
|
-
function readOperator(token) {
|
|
34025
|
-
if (token.startsWith(">=")) return
|
|
34026
|
-
if (token.startsWith("<=")) return
|
|
34027
|
-
if (token.startsWith(">")) return
|
|
34028
|
-
if (token.startsWith("<")) return
|
|
34029
|
-
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);
|
|
34030
34069
|
const bare = stripV(token);
|
|
34031
34070
|
return BARE_VERSION.test(bare) ? { operator: "=", version: bare } : null;
|
|
34032
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
|
+
}
|
|
34033
34077
|
function stripV(raw) {
|
|
34034
34078
|
const t = raw.trim();
|
|
34035
34079
|
return t.startsWith("v") || t.startsWith("V") ? t.slice(1) : t;
|
|
@@ -34052,6 +34096,9 @@ function trimToken(s) {
|
|
|
34052
34096
|
function nonEmpty(s) {
|
|
34053
34097
|
return s.length > 0;
|
|
34054
34098
|
}
|
|
34099
|
+
function isNotNull(value) {
|
|
34100
|
+
return value !== null;
|
|
34101
|
+
}
|
|
34055
34102
|
|
|
34056
34103
|
// ../../packages/feeds/src/gemnasium/feed.ts
|
|
34057
34104
|
var DEFAULT_API_BASE = "https://gitlab.com/api/v4/projects/gitlab-org%2Fsecurity-products%2Fgemnasium-db";
|
|
@@ -34146,8 +34193,7 @@ function advisoryIdFromPath(path) {
|
|
|
34146
34193
|
const file2 = segments[segments.length - 1];
|
|
34147
34194
|
if (!file2) return null;
|
|
34148
34195
|
const dot = file2.lastIndexOf(".");
|
|
34149
|
-
|
|
34150
|
-
return id.length > 0 ? id : null;
|
|
34196
|
+
return dot > 0 ? file2.slice(0, dot) : file2;
|
|
34151
34197
|
}
|
|
34152
34198
|
async function* streamGemnasiumArchive(ref, onProgress, options) {
|
|
34153
34199
|
const download = await openDownloadStream(archiveUrl(ref), onProgress, options);
|
|
@@ -34295,7 +34341,7 @@ function createRowWriter(path) {
|
|
|
34295
34341
|
let rowCount = 0;
|
|
34296
34342
|
let failed = null;
|
|
34297
34343
|
done.catch(function capture(err) {
|
|
34298
|
-
failed =
|
|
34344
|
+
failed = asError(err);
|
|
34299
34345
|
});
|
|
34300
34346
|
async function push(chunk, added) {
|
|
34301
34347
|
if (failed) throw failed;
|
|
@@ -34443,10 +34489,6 @@ async function loadCacheForPackages(cacheDir, ecosystem, packageNames, sources)
|
|
|
34443
34489
|
}
|
|
34444
34490
|
return { osv, gemnasium };
|
|
34445
34491
|
}
|
|
34446
|
-
function cacheEcosystemKey(ecosystem) {
|
|
34447
|
-
const def = getEcosystem(ecosystem);
|
|
34448
|
-
return def ? def.osvEcosystem : ecosystem;
|
|
34449
|
-
}
|
|
34450
34492
|
function toOsvAdvisory(row) {
|
|
34451
34493
|
return {
|
|
34452
34494
|
advisoryId: row.advisoryId,
|
|
@@ -34691,15 +34733,18 @@ async function seedGemnasium(options, meta3, item) {
|
|
|
34691
34733
|
}
|
|
34692
34734
|
async function refreshGemnasium(options, meta3, item) {
|
|
34693
34735
|
const state = getSourceState(meta3, "gemnasium", item.ecosystem);
|
|
34694
|
-
|
|
34695
|
-
|
|
34696
|
-
if (headSha && storedSha === headSha) {
|
|
34697
|
-
touch(meta3, "gemnasium", item.ecosystem);
|
|
34698
|
-
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" });
|
|
34699
34738
|
}
|
|
34700
|
-
|
|
34739
|
+
const storedSha = state.headSha;
|
|
34740
|
+
const headSha = await fetchGemnasiumHeadSha(fetchOptionsFor(options, item));
|
|
34741
|
+
if (!headSha) {
|
|
34701
34742
|
return await seedGemnasium(options, meta3, { ...item, kind: "seed" });
|
|
34702
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
|
+
}
|
|
34703
34748
|
const changed = await fetchGemnasiumChangedPaths(storedSha, headSha, fetchOptionsFor(options, item));
|
|
34704
34749
|
if (changed.status === "unavailable") {
|
|
34705
34750
|
return await seedGemnasium(options, meta3, { ...item, kind: "seed" });
|
|
@@ -34711,8 +34756,8 @@ async function refreshGemnasium(options, meta3, item) {
|
|
|
34711
34756
|
return pathEcosystemMatches(path, item.ecosystem);
|
|
34712
34757
|
});
|
|
34713
34758
|
if (relevant.length === 0 && removed.length === 0) {
|
|
34714
|
-
touchGemnasiumSha(
|
|
34715
|
-
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 };
|
|
34716
34761
|
}
|
|
34717
34762
|
const dropAdvisoryIds = /* @__PURE__ */ new Set();
|
|
34718
34763
|
for (const path of removed.concat(relevant)) {
|
|
@@ -34753,9 +34798,7 @@ function touch(meta3, source, ecosystem, etag) {
|
|
|
34753
34798
|
state.refreshedAt = Date.now();
|
|
34754
34799
|
if (etag !== void 0) state.etag = etag;
|
|
34755
34800
|
}
|
|
34756
|
-
function touchGemnasiumSha(
|
|
34757
|
-
const state = getSourceState(meta3, "gemnasium", ecosystem);
|
|
34758
|
-
if (!state) return;
|
|
34801
|
+
function touchGemnasiumSha(state, headSha) {
|
|
34759
34802
|
state.refreshedAt = Date.now();
|
|
34760
34803
|
state.headSha = headSha;
|
|
34761
34804
|
}
|
|
@@ -34984,7 +35027,7 @@ async function applyConfigFile(options, explicitFlags) {
|
|
|
34984
35027
|
try {
|
|
34985
35028
|
parsed = JSON.parse(text);
|
|
34986
35029
|
} catch (err) {
|
|
34987
|
-
return "sentinello.config.json is not valid JSON: " + (err
|
|
35030
|
+
return "sentinello.config.json is not valid JSON: " + errText(err);
|
|
34988
35031
|
}
|
|
34989
35032
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return "sentinello.config.json must contain an object";
|
|
34990
35033
|
const config2 = parsed;
|
|
@@ -35575,8 +35618,8 @@ function createUi(options) {
|
|
|
35575
35618
|
|
|
35576
35619
|
// src/help.ts
|
|
35577
35620
|
var CLI_VERSION = (function resolveVersion() {
|
|
35578
|
-
if ("3.
|
|
35579
|
-
return "3.
|
|
35621
|
+
if ("3.5.0".length > 0) {
|
|
35622
|
+
return "3.5.0";
|
|
35580
35623
|
}
|
|
35581
35624
|
const fromEnv = process.env.SENTINELLO_VERSION;
|
|
35582
35625
|
if (fromEnv && fromEnv.trim().length > 0) return fromEnv.trim();
|
|
@@ -35854,7 +35897,7 @@ async function runScan(options, cacheDir, ui) {
|
|
|
35854
35897
|
try {
|
|
35855
35898
|
prompt = await resolvePrompt(options);
|
|
35856
35899
|
} catch (err) {
|
|
35857
|
-
ui.error("could not read prompt file: " + (err
|
|
35900
|
+
ui.error("could not read prompt file: " + errText(err));
|
|
35858
35901
|
return EXIT_ERROR;
|
|
35859
35902
|
}
|
|
35860
35903
|
const document2 = options.json ? renderJson(summary, options, generatedAt) : renderMarkdown(summary, options, prompt, generatedAt);
|