sentinello 3.1.0 → 3.2.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.cjs +99 -26
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -13123,6 +13123,19 @@ function compareSeverity(a, b) {
|
|
|
13123
13123
|
function meetsSeverityFloor(severity, floor) {
|
|
13124
13124
|
return severityWeight(severity) >= severityWeight(floor);
|
|
13125
13125
|
}
|
|
13126
|
+
function maxSeverity(severities) {
|
|
13127
|
+
let best = "info";
|
|
13128
|
+
let bestWeight = 0;
|
|
13129
|
+
for (const s of severities) {
|
|
13130
|
+
const normalized = s.trim().toLowerCase();
|
|
13131
|
+
const known = SEVERITY_WEIGHT[normalized];
|
|
13132
|
+
if (known !== void 0 && known > bestWeight) {
|
|
13133
|
+
bestWeight = known;
|
|
13134
|
+
best = normalized;
|
|
13135
|
+
}
|
|
13136
|
+
}
|
|
13137
|
+
return best;
|
|
13138
|
+
}
|
|
13126
13139
|
var SOURCE_UNAVAILABLE_REASON_CODES = [
|
|
13127
13140
|
"osv_db_not_seeded",
|
|
13128
13141
|
"osv_db_unavailable",
|
|
@@ -13134,8 +13147,8 @@ function isSourceUnavailableReason(code) {
|
|
|
13134
13147
|
}
|
|
13135
13148
|
|
|
13136
13149
|
// ../../packages/core/src/advisory-rows.ts
|
|
13137
|
-
var OSV_NORMALIZER_VERSION =
|
|
13138
|
-
var GEMNASIUM_NORMALIZER_VERSION =
|
|
13150
|
+
var OSV_NORMALIZER_VERSION = 4;
|
|
13151
|
+
var GEMNASIUM_NORMALIZER_VERSION = 4;
|
|
13139
13152
|
|
|
13140
13153
|
// ../../packages/core/src/advisory-export.ts
|
|
13141
13154
|
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.
|
|
@@ -33204,22 +33217,51 @@ function findingIdentityKeys(finding) {
|
|
|
33204
33217
|
function findingPackageIdentity(finding) {
|
|
33205
33218
|
return (finding.ecosystem ?? DEFAULT_ECOSYSTEM) + "|" + finding.packageName;
|
|
33206
33219
|
}
|
|
33207
|
-
function reconcileAgainstReported(findings, reportedByPackage) {
|
|
33220
|
+
function reconcileAgainstReported(findings, reportedByPackage, source) {
|
|
33208
33221
|
const kept = [];
|
|
33222
|
+
const corroborations = [];
|
|
33209
33223
|
for (const finding of findings) {
|
|
33210
33224
|
const packageKey = findingPackageIdentity(finding);
|
|
33211
|
-
const existing = reportedByPackage.get(packageKey);
|
|
33225
|
+
const existing = reportedByPackage.get(packageKey) || /* @__PURE__ */ new Map();
|
|
33212
33226
|
const keys = findingIdentityKeys(finding);
|
|
33213
|
-
const
|
|
33214
|
-
|
|
33215
|
-
|
|
33216
|
-
|
|
33227
|
+
const target = firstReported(existing, keys);
|
|
33228
|
+
if (target) {
|
|
33229
|
+
const by = { source, advisoryId: finding.advisoryId, severity: finding.severity };
|
|
33230
|
+
corroborations.push({ target, by });
|
|
33231
|
+
const attached = target.finding.corroborations || [];
|
|
33232
|
+
if (!attached.some(function already(c) {
|
|
33233
|
+
return c.source === by.source;
|
|
33234
|
+
})) attached.push(by);
|
|
33235
|
+
target.finding.corroborations = attached;
|
|
33236
|
+
target.finding.severity = escalatedSeverity(target.severity, attached);
|
|
33237
|
+
continue;
|
|
33238
|
+
}
|
|
33217
33239
|
kept.push(finding);
|
|
33218
|
-
const
|
|
33219
|
-
|
|
33220
|
-
|
|
33240
|
+
const reported = {
|
|
33241
|
+
source,
|
|
33242
|
+
advisoryId: finding.advisoryId,
|
|
33243
|
+
packageName: finding.packageName,
|
|
33244
|
+
ecosystem: finding.ecosystem ?? DEFAULT_ECOSYSTEM,
|
|
33245
|
+
severity: finding.severity,
|
|
33246
|
+
finding
|
|
33247
|
+
};
|
|
33248
|
+
for (const key of keys) existing.set(key, reported);
|
|
33249
|
+
reportedByPackage.set(packageKey, existing);
|
|
33221
33250
|
}
|
|
33222
|
-
return kept;
|
|
33251
|
+
return { kept, corroborations };
|
|
33252
|
+
}
|
|
33253
|
+
function firstReported(existing, keys) {
|
|
33254
|
+
for (const key of keys) {
|
|
33255
|
+
const found = existing.get(key);
|
|
33256
|
+
if (found) return found;
|
|
33257
|
+
}
|
|
33258
|
+
return null;
|
|
33259
|
+
}
|
|
33260
|
+
function escalatedSeverity(own, corroborations) {
|
|
33261
|
+
if (corroborations.length === 0) return own;
|
|
33262
|
+
return maxSeverity([own, ...corroborations.map(function grade(c) {
|
|
33263
|
+
return c.severity;
|
|
33264
|
+
})]);
|
|
33223
33265
|
}
|
|
33224
33266
|
|
|
33225
33267
|
// ../../packages/scanners/src/index.ts
|
|
@@ -33428,18 +33470,21 @@ function normalizeOsvRecord(record2, ecosystem) {
|
|
|
33428
33470
|
const url2 = pickUrl(r, advisoryId);
|
|
33429
33471
|
const withdrawn = typeof r.withdrawn === "string" ? Date.parse(r.withdrawn) || null : null;
|
|
33430
33472
|
const rows = [];
|
|
33431
|
-
const
|
|
33473
|
+
const byPackage = /* @__PURE__ */ new Map();
|
|
33432
33474
|
for (const affected of r.affected) {
|
|
33433
33475
|
const pkg2 = affected.package;
|
|
33434
33476
|
if (!pkg2 || pkg2.ecosystem !== ecosystem) continue;
|
|
33435
33477
|
const packageName = typeof pkg2.name === "string" ? pkg2.name : null;
|
|
33436
33478
|
if (!packageName) continue;
|
|
33437
|
-
if (seenPackages.has(packageName)) continue;
|
|
33438
|
-
seenPackages.add(packageName);
|
|
33439
33479
|
const ranges = extractRanges(affected.ranges);
|
|
33440
33480
|
const versions = extractVersions(affected.versions);
|
|
33441
|
-
|
|
33442
|
-
|
|
33481
|
+
const existing = byPackage.get(packageName);
|
|
33482
|
+
if (existing) {
|
|
33483
|
+
for (const range of ranges) existing.ranges.push(range);
|
|
33484
|
+
for (const version2 of versions) existing.versions.push(version2);
|
|
33485
|
+
continue;
|
|
33486
|
+
}
|
|
33487
|
+
byPackage.set(packageName, {
|
|
33443
33488
|
advisoryId,
|
|
33444
33489
|
ecosystem,
|
|
33445
33490
|
packageName,
|
|
@@ -33453,6 +33498,10 @@ function normalizeOsvRecord(record2, ecosystem) {
|
|
|
33453
33498
|
withdrawn
|
|
33454
33499
|
});
|
|
33455
33500
|
}
|
|
33501
|
+
for (const row of byPackage.values()) {
|
|
33502
|
+
if (row.ranges.length === 0 && row.versions.length === 0 && !malicious) continue;
|
|
33503
|
+
rows.push(row);
|
|
33504
|
+
}
|
|
33456
33505
|
return rows;
|
|
33457
33506
|
}
|
|
33458
33507
|
function extractVersions(versions) {
|
|
@@ -33732,6 +33781,7 @@ function normalizeGemnasiumRecord(record2, ecosystem, slugPrefix) {
|
|
|
33732
33781
|
if (!slug || !slug.startsWith(slugPrefix)) return [];
|
|
33733
33782
|
const rawName = slug.slice(slugPrefix.length);
|
|
33734
33783
|
if (rawName.length === 0) return [];
|
|
33784
|
+
if (isRetractedUpstream(r)) return [];
|
|
33735
33785
|
const packageName = ecosystem === "PyPI" ? normalizePyName2(rawName) : rawName;
|
|
33736
33786
|
const identifiers = stringArray(r.identifiers);
|
|
33737
33787
|
const advisoryId = typeof r.identifier === "string" && r.identifier.length > 0 ? r.identifier : identifiers[0] ?? null;
|
|
@@ -33763,16 +33813,30 @@ function normalizeGemnasiumRecord(record2, ecosystem, slugPrefix) {
|
|
|
33763
33813
|
withdrawn: null
|
|
33764
33814
|
}];
|
|
33765
33815
|
}
|
|
33816
|
+
var RETRACTION_PHRASES = [
|
|
33817
|
+
"marked as false positive",
|
|
33818
|
+
"marked as a false positive",
|
|
33819
|
+
"this is a false positive",
|
|
33820
|
+
"this advisory has been withdrawn",
|
|
33821
|
+
"has been invalidated",
|
|
33822
|
+
"cve being rejected",
|
|
33823
|
+
"cve has been rejected"
|
|
33824
|
+
];
|
|
33825
|
+
function isRetractedUpstream(record2) {
|
|
33826
|
+
const title = typeof record2.title === "string" ? record2.title.trim().toLowerCase() : "";
|
|
33827
|
+
if (title === "false positive") return true;
|
|
33828
|
+
if (title.startsWith("withdrawn advisory:")) return true;
|
|
33829
|
+
if (title.startsWith("duplicate advisory:")) return true;
|
|
33830
|
+
const description = typeof record2.description === "string" ? record2.description.replace(/\s+/g, " ").toLowerCase() : "";
|
|
33831
|
+
return RETRACTION_PHRASES.some(function stated(phrase) {
|
|
33832
|
+
return description.includes(phrase);
|
|
33833
|
+
});
|
|
33834
|
+
}
|
|
33766
33835
|
function parseAffectedRange(affectedRange, fixedVersions) {
|
|
33767
33836
|
const ranges = [];
|
|
33768
33837
|
const versions = [];
|
|
33769
33838
|
const trimmed = affectedRange.trim();
|
|
33770
33839
|
const disjuncts = trimmed.length > 0 ? trimmed.split("||").map(trimToken).filter(nonEmpty) : [];
|
|
33771
|
-
if (disjuncts.length === 0) {
|
|
33772
|
-
const fixed = fixedVersions[0];
|
|
33773
|
-
if (fixed !== void 0) return { ranges: [{ introduced: "0", fixed }], versions };
|
|
33774
|
-
return { ranges, versions };
|
|
33775
|
-
}
|
|
33776
33840
|
for (const disjunct of disjuncts) {
|
|
33777
33841
|
const interval = parseDisjunct(disjunct);
|
|
33778
33842
|
if (!interval) continue;
|
|
@@ -33782,13 +33846,22 @@ function parseAffectedRange(affectedRange, fixedVersions) {
|
|
|
33782
33846
|
ranges.push({ introduced: interval.introduced, fixed: interval.fixed });
|
|
33783
33847
|
}
|
|
33784
33848
|
}
|
|
33849
|
+
if (versions.length === 0 && ranges.every(isEmptyInterval)) return { ranges: [], versions: [] };
|
|
33785
33850
|
const only = ranges[0];
|
|
33786
33851
|
const authoritativeFixed = fixedVersions[0];
|
|
33787
|
-
if (ranges.length === 1 && versions.length === 0 && only && authoritativeFixed !== void 0) {
|
|
33852
|
+
if (ranges.length === 1 && versions.length === 0 && only && fixedVersions.length === 1 && authoritativeFixed !== void 0) {
|
|
33788
33853
|
ranges[0] = { introduced: only.introduced, fixed: authoritativeFixed };
|
|
33789
33854
|
}
|
|
33790
33855
|
return { ranges, versions };
|
|
33791
33856
|
}
|
|
33857
|
+
function isEmptyInterval(range) {
|
|
33858
|
+
if (range.fixed === null) return false;
|
|
33859
|
+
if (range.fixed === range.introduced) return true;
|
|
33860
|
+
return isZeroVersion(range.introduced) && isZeroVersion(range.fixed);
|
|
33861
|
+
}
|
|
33862
|
+
function isZeroVersion(version2) {
|
|
33863
|
+
return /^0(\.0)*$/.test(version2);
|
|
33864
|
+
}
|
|
33792
33865
|
function parseDisjunct(disjunct) {
|
|
33793
33866
|
const first = disjunct[0];
|
|
33794
33867
|
if (first === "(" || first === "[") return parseIntervalNotation(disjunct);
|
|
@@ -35051,7 +35124,7 @@ async function scanProject(setup, resolved, scanners) {
|
|
|
35051
35124
|
durationMs: result.durationMs
|
|
35052
35125
|
});
|
|
35053
35126
|
if (result.status !== "ok") continue;
|
|
35054
|
-
for (const finding of reconcileAgainstReported(result.findings, reportedByPackage)) {
|
|
35127
|
+
for (const finding of reconcileAgainstReported(result.findings, reportedByPackage, scanner.name).kept) {
|
|
35055
35128
|
findings.push(finding);
|
|
35056
35129
|
}
|
|
35057
35130
|
}
|
|
@@ -35376,8 +35449,8 @@ function createUi(options) {
|
|
|
35376
35449
|
|
|
35377
35450
|
// src/help.ts
|
|
35378
35451
|
var CLI_VERSION = (function resolveVersion() {
|
|
35379
|
-
if ("3.
|
|
35380
|
-
return "3.
|
|
35452
|
+
if ("3.2.0".length > 0) {
|
|
35453
|
+
return "3.2.0";
|
|
35381
35454
|
}
|
|
35382
35455
|
const fromEnv = process.env.SENTINELLO_VERSION;
|
|
35383
35456
|
if (fromEnv && fromEnv.trim().length > 0) return fromEnv.trim();
|