From 37668efdaaae27d07d8a0bcba17bc3698b6d87dd Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Mon, 15 May 2023 15:52:45 -0400 Subject: [PATCH 1/6] feat(osv): handle unknown and medium severity scenarios --- lib/util/vulnerability/utils.spec.ts | 28 +++++++++++++++++++ lib/util/vulnerability/utils.ts | 2 ++ lib/workers/repository/process/types.ts | 2 +- .../repository/process/vulnerabilities.ts | 9 +++--- 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/lib/util/vulnerability/utils.spec.ts b/lib/util/vulnerability/utils.spec.ts index 0d9aa2ee34bae1..ca6d942f86020e 100644 --- a/lib/util/vulnerability/utils.spec.ts +++ b/lib/util/vulnerability/utils.spec.ts @@ -85,6 +85,20 @@ describe('util/vulnerability/utils', () => { expect(severity).toBe('MODERATE'); }); + it('child MEDIUM vulnerability severity rating is maintained', () => { + const parentConfig = { + vulnerabilitySeverity: 'LOW', + }; + + const childConfig = { + vulnerabilitySeverity: 'MEDIUM', + }; + + const severity = getHighestVulnerabilitySeverity(parentConfig, childConfig); + + expect(severity).toBe('MEDIUM'); + }); + it('parent LOW vulnerability severity rating is maintained', () => { const parentConfig = { vulnerabilitySeverity: 'LOW', @@ -113,6 +127,20 @@ describe('util/vulnerability/utils', () => { expect(severity).toBe('LOW'); }); + it('child UNKNOWN vulnerability severity rating is maintained', () => { + const parentConfig = { + vulnerabilitySeverity: undefined, + }; + + const childConfig = { + vulnerabilitySeverity: 'UNKNOWN', + }; + + const severity = getHighestVulnerabilitySeverity(parentConfig, childConfig); + + expect(severity).toBe('UNKNOWN'); + }); + it('handled undefined parent and child vulnerability severity', () => { const parentConfig = { vulnerabilitySeverity: undefined, diff --git a/lib/util/vulnerability/utils.ts b/lib/util/vulnerability/utils.ts index 5607a6de9237b8..ba6ef474233500 100644 --- a/lib/util/vulnerability/utils.ts +++ b/lib/util/vulnerability/utils.ts @@ -1,5 +1,7 @@ const severityOrder: Record = { + UNKNOWN: 0, LOW: 1, + MEDIUM: 2, MODERATE: 2, HIGH: 3, CRITICAL: 4, diff --git a/lib/workers/repository/process/types.ts b/lib/workers/repository/process/types.ts index e59c569da1d8ab..c0de869e16ab17 100644 --- a/lib/workers/repository/process/types.ts +++ b/lib/workers/repository/process/types.ts @@ -21,5 +21,5 @@ export interface DependencyVulnerabilities { export interface SeverityDetails { cvssVector: string; score: string; - severityLevel?: string; + severityLevel: string; } diff --git a/lib/workers/repository/process/vulnerabilities.ts b/lib/workers/repository/process/vulnerabilities.ts index 93483f716a0009..efb0976d3109f0 100644 --- a/lib/workers/repository/process/vulnerabilities.ts +++ b/lib/workers/repository/process/vulnerabilities.ts @@ -532,10 +532,8 @@ export class Vulnerabilities { if (severityDetails.cvssVector) { content += `- CVSS Score: ${severityDetails.score}\n`; content += `- Vector String: \`${severityDetails.cvssVector}\`\n`; - } else if (severityDetails.severityLevel) { - content += `${severityDetails.severityLevel}\n`; } else { - content += 'Unknown severity.\n'; + content += `${severityDetails.severityLevel}\n`; } content += `\n#### References\n${ @@ -566,8 +564,8 @@ export class Vulnerabilities { vulnerability: Osv.Vulnerability, affected: Osv.Affected ): SeverityDetails { - let severityLevel: string | undefined; - let score = 'Unknown'; + let severityLevel = 'UNKNOWN'; + let score = 'Unknown severity'; const cvssVector = vulnerability.severity?.find((e) => e.type === 'CVSS_V3')?.score ?? @@ -585,6 +583,7 @@ export class Vulnerabilities { const severity = vulnerability.database_specific.severity as string; severityLevel = severity.charAt(0).toUpperCase() + severity.slice(1).toLowerCase(); + score = severityLevel; } return { From 3b03622f6931910186116ab07eebb0caa355a5b7 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Tue, 16 May 2023 05:01:59 -0400 Subject: [PATCH 2/6] unknown > critical --- lib/util/vulnerability/utils.spec.ts | 2 +- lib/util/vulnerability/utils.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/util/vulnerability/utils.spec.ts b/lib/util/vulnerability/utils.spec.ts index ca6d942f86020e..4ba086a5394d85 100644 --- a/lib/util/vulnerability/utils.spec.ts +++ b/lib/util/vulnerability/utils.spec.ts @@ -129,7 +129,7 @@ describe('util/vulnerability/utils', () => { it('child UNKNOWN vulnerability severity rating is maintained', () => { const parentConfig = { - vulnerabilitySeverity: undefined, + vulnerabilitySeverity: 'CRITICAL', }; const childConfig = { diff --git a/lib/util/vulnerability/utils.ts b/lib/util/vulnerability/utils.ts index ba6ef474233500..bc451a7db53658 100644 --- a/lib/util/vulnerability/utils.ts +++ b/lib/util/vulnerability/utils.ts @@ -1,10 +1,10 @@ const severityOrder: Record = { - UNKNOWN: 0, LOW: 1, MEDIUM: 2, MODERATE: 2, HIGH: 3, CRITICAL: 4, + UNKNOWN: 5, }; export function getHighestVulnerabilitySeverity< From 0d30ab949c251cee51cca2b5de1e799eca9a1e7b Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Tue, 16 May 2023 05:04:59 -0400 Subject: [PATCH 3/6] docs: update severity types --- lib/util/template/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/util/template/index.ts b/lib/util/template/index.ts index da16eaa90f8cfd..5c3e1261e29a73 100644 --- a/lib/util/template/index.ts +++ b/lib/util/template/index.ts @@ -145,7 +145,7 @@ export const allowedFields = { versioning: 'The versioning scheme in use', versions: 'An array of ChangeLogRelease objects in the upgrade', vulnerabilitySeverity: - 'The severity for a vulnerability alert upgrade (eg: LOW, MODERATE, HIGH, CRITICAL)', + 'The severity for a vulnerability alert upgrade (LOW, MEDIUM, MODERATE, HIGH, CRITICAL, UNKNOWN)', }; const prBodyFields = [ From 4920483a83b48f9be47362275162746064621ab0 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Tue, 16 May 2023 06:36:43 -0400 Subject: [PATCH 4/6] tests: fix test --- lib/workers/repository/process/vulnerabilities.spec.ts | 2 +- lib/workers/repository/process/vulnerabilities.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/workers/repository/process/vulnerabilities.spec.ts b/lib/workers/repository/process/vulnerabilities.spec.ts index acfb0424435dba..6a57f911e735ed 100644 --- a/lib/workers/repository/process/vulnerabilities.spec.ts +++ b/lib/workers/repository/process/vulnerabilities.spec.ts @@ -944,7 +944,7 @@ describe('workers/repository/process/vulnerabilities', () => { No details. #### Severity - Unknown severity. + Unknown severity #### References No references. diff --git a/lib/workers/repository/process/vulnerabilities.ts b/lib/workers/repository/process/vulnerabilities.ts index efb0976d3109f0..c4c2d9cb8bc47a 100644 --- a/lib/workers/repository/process/vulnerabilities.ts +++ b/lib/workers/repository/process/vulnerabilities.ts @@ -533,7 +533,7 @@ export class Vulnerabilities { content += `- CVSS Score: ${severityDetails.score}\n`; content += `- Vector String: \`${severityDetails.cvssVector}\`\n`; } else { - content += `${severityDetails.severityLevel}\n`; + content += `${severityDetails.score}\n`; } content += `\n#### References\n${ From 44a485e0410c41be48e7338d9312d7f15e221500 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Tue, 16 May 2023 07:00:34 -0400 Subject: [PATCH 5/6] refactor: use severityLevel instead --- lib/workers/repository/process/vulnerabilities.spec.ts | 2 +- lib/workers/repository/process/vulnerabilities.ts | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/workers/repository/process/vulnerabilities.spec.ts b/lib/workers/repository/process/vulnerabilities.spec.ts index 6a57f911e735ed..eb63590dea7a21 100644 --- a/lib/workers/repository/process/vulnerabilities.spec.ts +++ b/lib/workers/repository/process/vulnerabilities.spec.ts @@ -944,7 +944,7 @@ describe('workers/repository/process/vulnerabilities', () => { No details. #### Severity - Unknown severity + Unknown #### References No references. diff --git a/lib/workers/repository/process/vulnerabilities.ts b/lib/workers/repository/process/vulnerabilities.ts index c4c2d9cb8bc47a..80845a711736e3 100644 --- a/lib/workers/repository/process/vulnerabilities.ts +++ b/lib/workers/repository/process/vulnerabilities.ts @@ -533,7 +533,7 @@ export class Vulnerabilities { content += `- CVSS Score: ${severityDetails.score}\n`; content += `- Vector String: \`${severityDetails.cvssVector}\`\n`; } else { - content += `${severityDetails.score}\n`; + content += `${severityDetails.severityLevel}\n`; } content += `\n#### References\n${ @@ -564,8 +564,8 @@ export class Vulnerabilities { vulnerability: Osv.Vulnerability, affected: Osv.Affected ): SeverityDetails { - let severityLevel = 'UNKNOWN'; - let score = 'Unknown severity'; + let severityLevel = 'Unknown'; + let score = 'Unknown'; const cvssVector = vulnerability.severity?.find((e) => e.type === 'CVSS_V3')?.score ?? @@ -583,7 +583,6 @@ export class Vulnerabilities { const severity = vulnerability.database_specific.severity as string; severityLevel = severity.charAt(0).toUpperCase() + severity.slice(1).toLowerCase(); - score = severityLevel; } return { From afaf681f4a9a4e13ffadc27d135f104537dbd9c7 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Tue, 16 May 2023 08:52:52 -0400 Subject: [PATCH 6/6] refactor: use title case --- lib/util/string.ts | 11 ++++++++++ .../repository/process/vulnerabilities.ts | 20 +++++++++---------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/lib/util/string.ts b/lib/util/string.ts index 4030956cdd923c..7a4d7d87608fb4 100644 --- a/lib/util/string.ts +++ b/lib/util/string.ts @@ -56,3 +56,14 @@ export function looseEquals( export function isDockerDigest(input: string): boolean { return /^sha256:[a-f0-9]{64}$/i.test(input); } + +export function titleCase(input: string): string { + const words = input.toLowerCase().split(' '); + + for (let i = 0; i < words.length; i++) { + const word = words[i]; + words[i] = word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); + } + + return words.join(' '); +} diff --git a/lib/workers/repository/process/vulnerabilities.ts b/lib/workers/repository/process/vulnerabilities.ts index 80845a711736e3..9ff98a803dfb6a 100644 --- a/lib/workers/repository/process/vulnerabilities.ts +++ b/lib/workers/repository/process/vulnerabilities.ts @@ -18,6 +18,7 @@ import { import { sanitizeMarkdown } from '../../../util/markdown'; import * as p from '../../../util/promises'; import { regEx } from '../../../util/regex'; +import { titleCase } from '../../../util/string'; import type { DependencyVulnerabilities, SeverityDetails, @@ -470,7 +471,7 @@ export class Vulnerabilities { matchCurrentVersion: depVersion, allowedVersions: fixedVersion, isVulnerabilityAlert: true, - vulnerabilitySeverity: severityDetails.severityLevel?.toUpperCase(), + vulnerabilitySeverity: severityDetails.severityLevel, prBodyNotes: this.generatePrBodyNotes(vulnerability, affected), force: { ...packageFileConfig.vulnerabilityAlerts, @@ -481,9 +482,7 @@ export class Vulnerabilities { private evaluateCvssVector(vector: string): [string, string] { try { const parsedCvss: CvssScore = parseCvssVector(vector); - const severityLevel = - parsedCvss.cvss3OverallSeverityText.charAt(0).toUpperCase() + - parsedCvss.cvss3OverallSeverityText.slice(1); + const severityLevel = parsedCvss.cvss3OverallSeverityText; return [parsedCvss.baseScore.toFixed(1), severityLevel]; } catch (err) { @@ -533,7 +532,7 @@ export class Vulnerabilities { content += `- CVSS Score: ${severityDetails.score}\n`; content += `- Vector String: \`${severityDetails.cvssVector}\`\n`; } else { - content += `${severityDetails.severityLevel}\n`; + content += `${titleCase(severityDetails.severityLevel)}\n`; } content += `\n#### References\n${ @@ -564,7 +563,7 @@ export class Vulnerabilities { vulnerability: Osv.Vulnerability, affected: Osv.Affected ): SeverityDetails { - let severityLevel = 'Unknown'; + let severityLevel = 'UNKNOWN'; let score = 'Unknown'; const cvssVector = @@ -574,15 +573,16 @@ export class Vulnerabilities { if (cvssVector) { const [baseScore, severity] = this.evaluateCvssVector(cvssVector); - severityLevel = severity; - score = baseScore ? `${baseScore} / 10 (${severityLevel})` : 'Unknown'; + severityLevel = severity.toUpperCase(); + score = baseScore + ? `${baseScore} / 10 (${titleCase(severityLevel)})` + : 'Unknown'; } else if ( vulnerability.id.startsWith('GHSA-') && vulnerability.database_specific?.severity ) { const severity = vulnerability.database_specific.severity as string; - severityLevel = - severity.charAt(0).toUpperCase() + severity.slice(1).toLowerCase(); + severityLevel = severity.toUpperCase(); } return {