Skip to content

Commit 884e975

Browse files
author
AvrAlexandra
committed
count deleted vulnerable dependencies as fixed
1 parent 0533702 commit 884e975

File tree

1 file changed

+43
-41
lines changed

1 file changed

+43
-41
lines changed

src/commands/history-metrics/metrics-generator.ts

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -87,41 +87,35 @@ export function VulnerabilityFixBySeverityMetric(
8787
): Record<string, Record<string, number>> {
8888
const timeline: Record<string, Record<string, number>> = {};
8989

90-
for (const [, commitEntry] of Object.entries(commitHistory)) {
91-
if (!commitEntry || !Array.isArray(commitEntry.history)) continue;
92-
const historyArray = commitEntry.history;
93-
94-
for (const entry of historyArray) {
95-
if (
96-
entry.action !== 'MODIFIED' ||
97-
!entry.fromVersion ||
98-
!entry.toVersion ||
99-
!entry.date ||
100-
!entry.depinderDependencyName
101-
) continue;
90+
const isSemverVulnerable = (version: string | undefined, range: string): boolean =>
91+
!!version && semver.valid(version) !== null && semver.satisfies(version, range);
10292

103-
const libKey = Object.keys(libraryInfoMap).find(k => k.endsWith(`:${entry.depinderDependencyName}`));
93+
for (const [, commitEntry] of Object.entries(commitHistory)) {
94+
if (!commitEntry?.history?.length) continue;
95+
for (const entry of commitEntry.history) {
96+
if (!entry.date || !entry.depinderDependencyName) continue;
97+
const libKey = Object.keys(libraryInfoMap).find(k =>
98+
k.endsWith(`:${entry.depinderDependencyName}`)
99+
);
104100
if (!libKey) continue;
105-
106-
const libInfo = libraryInfoMap[libKey];
107-
const libVulnerabilities = libInfo?.info?.vulnerabilities || [];
108-
101+
const vulnerabilities = libraryInfoMap[libKey]?.info?.vulnerabilities || [];
109102
const month = entry.date.slice(0, 7);
110-
111-
for (const vuln of libVulnerabilities) {
103+
for (const vuln of vulnerabilities) {
112104
if (!vuln.vulnerableRange || !vuln.severity) continue;
113105
const cleanRange = vuln.vulnerableRange.replace(/,/g, ' ').trim();
114-
115-
const wasVulnerable =
116-
semver.valid(entry.fromVersion) && semver.satisfies(entry.fromVersion, cleanRange);
117-
const stillVulnerable =
118-
semver.valid(entry.toVersion) && semver.satisfies(entry.toVersion, cleanRange);
119-
const isFixed = wasVulnerable && !stillVulnerable;
120-
106+
const severity = vuln.severity;
107+
let isFixed = false;
108+
if (entry.action === 'MODIFIED') {
109+
const wasVulnerable = isSemverVulnerable(entry.fromVersion, cleanRange);
110+
const stillVulnerable = isSemverVulnerable(entry.toVersion, cleanRange);
111+
isFixed = wasVulnerable && !stillVulnerable;
112+
}
113+
if (entry.action === 'DELETED') {
114+
isFixed = isSemverVulnerable(entry.version, cleanRange);
115+
}
121116
if (isFixed) {
122117
if (!timeline[month]) timeline[month] = {};
123-
if (!timeline[month][vuln.severity]) timeline[month][vuln.severity] = 0;
124-
timeline[month][vuln.severity]++;
118+
timeline[month][severity] = (timeline[month][severity] || 0) + 1;
125119
}
126120
}
127121
}
@@ -153,8 +147,10 @@ export function VulnerabilityFixTimelinessMetric(
153147
if (!commitEntry?.history?.length) continue;
154148

155149
for (const entry of commitEntry.history) {
156-
if (!entry.date || !entry.fromVersion || !entry.depinderDependencyName) continue;
157-
const libKey = Object.keys(libraryInfoMap).find(k => k.endsWith(`:${entry.depinderDependencyName}`));
150+
if (!entry.date || !entry.depinderDependencyName) continue;
151+
const libKey = Object.keys(libraryInfoMap).find(k =>
152+
k.endsWith(`:${entry.depinderDependencyName}`)
153+
);
158154
if (!libKey) continue;
159155

160156
const vulnerabilities = libraryInfoMap[libKey]?.info?.vulnerabilities || [];
@@ -164,26 +160,32 @@ export function VulnerabilityFixTimelinessMetric(
164160
if (!vuln.vulnerableRange || !vuln.severity) continue;
165161
const cleanRange = vuln.vulnerableRange.replace(/,/g, ' ').trim();
166162
const key = `${entry.depinderDependencyName}@@${cleanRange}`;
167-
168-
const seenValid = semver.valid(entry.fromVersion) && semver.satisfies(entry.fromVersion, cleanRange);
169-
if (seenValid) {
163+
const versionToCheck =
164+
entry.action === 'MODIFIED' ? entry.fromVersion :
165+
entry.action === 'DELETED' ? entry.version :
166+
undefined;
167+
const isVersionVulnerable =
168+
!!versionToCheck && semver.valid(versionToCheck) && semver.satisfies(versionToCheck, cleanRange);
169+
if (isVersionVulnerable) {
170170
if (!firstSeenMap[key] || entryDate < firstSeenMap[key]) {
171171
firstSeenMap[key] = entryDate;
172172
}
173173
}
174-
175-
const isFix = entry.action === 'MODIFIED' &&
174+
const isFixViaModification =
175+
entry.action === 'MODIFIED' &&
176176
!!entry.toVersion &&
177-
semver.valid(entry.fromVersion) &&
178177
semver.valid(entry.toVersion) &&
179-
semver.satisfies(entry.fromVersion, cleanRange) &&
178+
isVersionVulnerable &&
180179
!semver.satisfies(entry.toVersion, cleanRange);
181-
180+
const isFixViaDeletion =
181+
entry.action === 'DELETED' &&
182+
isVersionVulnerable;
183+
const isFix = isFixViaModification || isFixViaDeletion;
182184
if (isFix) {
183185
const introducedDate = firstSeenMap[key] ?? entryDate;
184-
const daysToFix: number = differenceInBusinessDays(entryDate, introducedDate);
185-
const severity: SeverityLevel = vuln.severity.toUpperCase() as SeverityLevel;
186-
const fixDeadlineDays: number = severityFixTimeLimits[severity] ?? 999;
186+
const daysToFix = differenceInBusinessDays(entryDate, introducedDate);
187+
const severity = vuln.severity.toUpperCase() as SeverityLevel;
188+
const fixDeadlineDays: any= severityFixTimeLimits[severity] ?? 999;
187189
const fixCategory: FixCategory = daysToFix <= fixDeadlineDays ? 'fixedInTime' : 'fixedLate';
188190
const month = entryDate.toISOString().slice(0, 7);
189191

0 commit comments

Comments
 (0)