From 2b2c8403e84b0b445e1c7d3cccbc5cc5d8abc213 Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Thu, 16 Jan 2025 15:37:59 +0000 Subject: [PATCH 1/6] Code Scanning alert severity ordered first by security severity --- dist/index.js | 30 +++++++++++++++++------------- src/types/common/main.d.ts | 1 + src/utils/AlertMetrics.ts | 31 +++++++++++++++++-------------- 3 files changed, 35 insertions(+), 27 deletions(-) diff --git a/dist/index.js b/dist/index.js index fed982f..982d7aa 100644 --- a/dist/index.js +++ b/dist/index.js @@ -64470,8 +64470,19 @@ const FilterBetweenDates = (stringDate, minDate, maxDate) => { const date = Date.parse(stringDate); return date >= minDate.getTime() && date < maxDate.getTime(); }; +function getAlertSeverity(alert) { + if (isDependancyAlert(alert)) { + return alert.security_advisory.severity.toLowerCase(); + } + else if (isCodeScanningAlert(alert)) { + const codeScanningAlert = alert; + return codeScanningAlert.rule?.security_severity_level + ? codeScanningAlert.rule?.security_severity_level.toLowerCase() + : codeScanningAlert.rule?.severity.toLowerCase() || "none"; + } + return "none"; +} function compareAlertSeverity(a, b) { - //critical, high, medium, low, warning, note, error const weight = { critical: 7, high: 6, @@ -64482,22 +64493,15 @@ function compareAlertSeverity(a, b) { error: 1, none: 0, }; - let comparison = 0; - let severity1 = "none"; - let severity2 = "none"; - severity1 = isDependancyAlert(a) - ? a.security_advisory.severity.toLowerCase() - : a.rule?.severity.toLowerCase(); - severity2 = isDependancyAlert(b) - ? b.security_advisory.severity.toLowerCase() - : b.rule?.severity.toLowerCase(); + const severity1 = getAlertSeverity(a); + const severity2 = getAlertSeverity(b); if (weight[severity1] < weight[severity2]) { - comparison = 1; + return 1; } else if (weight[severity1] > weight[severity2]) { - comparison = -1; + return -1; } - return comparison; + return 0; } function isDependancyAlert(alert) { return "security_advisory" in alert; diff --git a/src/types/common/main.d.ts b/src/types/common/main.d.ts index 0cf6539..330a67c 100644 --- a/src/types/common/main.d.ts +++ b/src/types/common/main.d.ts @@ -187,6 +187,7 @@ export interface Rule { description: string; name: string; tags: string[]; + security_severity_level: string; } export interface Tool { diff --git a/src/utils/AlertMetrics.ts b/src/utils/AlertMetrics.ts index ef01ca9..87925cd 100644 --- a/src/utils/AlertMetrics.ts +++ b/src/utils/AlertMetrics.ts @@ -156,8 +156,19 @@ const FilterBetweenDates = ( return date >= minDate.getTime() && date < maxDate.getTime(); }; +function getAlertSeverity(alert: Alert): string { + if (isDependancyAlert(alert)) { + return alert.security_advisory.severity.toLowerCase(); + } else if (isCodeScanningAlert(alert)) { + const codeScanningAlert = alert as CodeScanningAlert; + return codeScanningAlert.rule?.security_severity_level + ? codeScanningAlert.rule?.security_severity_level.toLowerCase() + : codeScanningAlert.rule?.severity.toLowerCase() || "none"; + } + return "none"; +} + function compareAlertSeverity(a: Alert, b: Alert) { - //critical, high, medium, low, warning, note, error const weight: { [key: string]: number } = { critical: 7, high: 6, @@ -168,24 +179,16 @@ function compareAlertSeverity(a: Alert, b: Alert) { error: 1, none: 0, }; - let comparison = 0; - let severity1 = "none"; - let severity2 = "none"; - severity1 = isDependancyAlert(a) - ? a.security_advisory.severity.toLowerCase() - : (a as CodeScanningAlert).rule?.severity.toLowerCase(); - severity2 = isDependancyAlert(b) - ? b.security_advisory.severity.toLowerCase() - : (b as CodeScanningAlert).rule?.severity.toLowerCase(); + const severity1 = getAlertSeverity(a); + const severity2 = getAlertSeverity(b); if (weight[severity1] < weight[severity2]) { - comparison = 1; + return 1; } else if (weight[severity1] > weight[severity2]) { - comparison = -1; + return -1; } - - return comparison; + return 0; } export function isDependancyAlert(alert: Alert): alert is DependancyAlert { From 5d03478c1cfb135f42e4524a6e0a4140c007aa5d Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Thu, 16 Jan 2025 16:37:38 +0000 Subject: [PATCH 2/6] refactor: reorder alert severity weights for improved comparison logic --- src/utils/AlertMetrics.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/utils/AlertMetrics.ts b/src/utils/AlertMetrics.ts index 87925cd..ee94144 100644 --- a/src/utils/AlertMetrics.ts +++ b/src/utils/AlertMetrics.ts @@ -172,21 +172,21 @@ function compareAlertSeverity(a: Alert, b: Alert) { const weight: { [key: string]: number } = { critical: 7, high: 6, - medium: 5, - low: 4, + error: 5, + medium: 4, warning: 3, - note: 2, - error: 1, + low: 2, + note: 1, none: 0, }; const severity1 = getAlertSeverity(a); const severity2 = getAlertSeverity(b); - if (weight[severity1] < weight[severity2]) { - return 1; - } else if (weight[severity1] > weight[severity2]) { + if (weight[severity1] > weight[severity2]) { return -1; + } else if (weight[severity1] < weight[severity2]) { + return 1; } return 0; } From eb0f1c53f99b53bdf0a757736d3895be07f75146 Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Thu, 16 Jan 2025 16:39:27 +0000 Subject: [PATCH 3/6] compile --- dist/index.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/dist/index.js b/dist/index.js index 982d7aa..8e8a455 100644 --- a/dist/index.js +++ b/dist/index.js @@ -64486,21 +64486,21 @@ function compareAlertSeverity(a, b) { const weight = { critical: 7, high: 6, - medium: 5, - low: 4, + error: 5, + medium: 4, warning: 3, - note: 2, - error: 1, + low: 2, + note: 1, none: 0, }; const severity1 = getAlertSeverity(a); const severity2 = getAlertSeverity(b); - if (weight[severity1] < weight[severity2]) { - return 1; - } - else if (weight[severity1] > weight[severity2]) { + if (weight[severity1] > weight[severity2]) { return -1; } + else if (weight[severity1] < weight[severity2]) { + return 1; + } return 0; } function isDependancyAlert(alert) { From 07d5793b55f76c12b8841b4f56a607b18f80e5eb Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Thu, 16 Jan 2025 17:27:28 +0000 Subject: [PATCH 4/6] fix: prioritize security severity level in summary output --- dist/index.js | 2 +- src/context/CodeScanning.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index 8e8a455..ec2b456 100644 --- a/dist/index.js +++ b/dist/index.js @@ -64718,7 +64718,7 @@ class CodeScanning extends Printable { summaryTop10() { return this.metrics.top10.map((a) => [ a.rule?.name || "", - a.rule?.severity || "", + a.rule?.security_severity_level || a.rule?.severity || "", a.tool?.name || "", a.most_recent_instance?.location.path || "", a.html_url, diff --git a/src/context/CodeScanning.ts b/src/context/CodeScanning.ts index 9639e6e..f8c1b92 100644 --- a/src/context/CodeScanning.ts +++ b/src/context/CodeScanning.ts @@ -49,7 +49,7 @@ export class CodeScanning extends Printable implements Feature { summaryTop10(): string[][] { return this.metrics.top10.map((a: CodeScanningAlert) => [ a.rule?.name || "", - a.rule?.severity || "", + a.rule?.security_severity_level || a.rule?.severity || "", a.tool?.name || "", a.most_recent_instance?.location.path || "", a.html_url, From 8d507fd0dda9cd93243616ef608471bdd0775c40 Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Thu, 16 Jan 2025 19:49:58 +0000 Subject: [PATCH 5/6] feat: add CWE extraction from tags and include in summary output --- dist/index.js | 16 ++++++++++++++++ src/context/CodeScanning.ts | 17 +++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/dist/index.js b/dist/index.js index ec2b456..8987eff 100644 --- a/dist/index.js +++ b/dist/index.js @@ -64703,6 +64703,7 @@ class CodeScanning extends Printable { attributes = [ "Vulnerability", "Severity", + "Weakness", "Tool", "Vulnerable file", "Link", @@ -64715,10 +64716,25 @@ class CodeScanning extends Printable { this.metrics = AlertsMetrics(alerts, frequency, "fixed_at", "fixed", true, "commitDate", "created_at"); return this.metrics; } + //Extracts CWE-### from CodeScanningAlert.rule.tags[] from any format like "external/cwe/cwe-247" or "CWE-352: Cross-Site Request Forgery (CSRF)" + cweFromTags(rule) { + const cwe = rule.rule?.tags + .map((tag) => { + const cwe = tag.match(/cwe-(\d+)/i); + if (cwe) { + return `CWE-${cwe[1]}`; + } + return ""; + }) + .filter((cwe) => cwe !== "") + .join(", "); + return cwe; + } summaryTop10() { return this.metrics.top10.map((a) => [ a.rule?.name || "", a.rule?.security_severity_level || a.rule?.severity || "", + this.cweFromTags(a), a.tool?.name || "", a.most_recent_instance?.location.path || "", a.html_url, diff --git a/src/context/CodeScanning.ts b/src/context/CodeScanning.ts index f8c1b92..2dfddf2 100644 --- a/src/context/CodeScanning.ts +++ b/src/context/CodeScanning.ts @@ -16,6 +16,7 @@ export class CodeScanning extends Printable implements Feature { attributes: string[] = [ "Vulnerability", "Severity", + "Weakness", "Tool", "Vulnerable file", "Link", @@ -46,10 +47,26 @@ export class CodeScanning extends Printable implements Feature { return this.metrics; } + //Extracts CWE-### from CodeScanningAlert.rule.tags[] from any format like "external/cwe/cwe-247" or "CWE-352: Cross-Site Request Forgery (CSRF)" + cweFromTags(rule: CodeScanningAlert): string { + const cwe = rule.rule?.tags + .map((tag) => { + const cwe = tag.match(/cwe-(\d+)/i); + if (cwe) { + return `CWE-${cwe[1]}`; + } + return ""; + }) + .filter((cwe) => cwe !== "") + .join(", "); + return cwe; + } + summaryTop10(): string[][] { return this.metrics.top10.map((a: CodeScanningAlert) => [ a.rule?.name || "", a.rule?.security_severity_level || a.rule?.severity || "", + this.cweFromTags(a), a.tool?.name || "", a.most_recent_instance?.location.path || "", a.html_url, From 7c74de52a4f7e511902adcffc230dd4df8957d69 Mon Sep 17 00:00:00 2001 From: Chad Bentz <1760475+felickz@users.noreply.github.com> Date: Thu, 16 Jan 2025 21:48:22 +0000 Subject: [PATCH 6/6] feat: include line number in location path for most recent instance --- dist/index.js | 4 +++- src/context/CodeScanning.ts | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index 8987eff..4f3aa30 100644 --- a/dist/index.js +++ b/dist/index.js @@ -64736,7 +64736,9 @@ class CodeScanning extends Printable { a.rule?.security_severity_level || a.rule?.severity || "", this.cweFromTags(a), a.tool?.name || "", - a.most_recent_instance?.location.path || "", + a.most_recent_instance?.location?.path + ? `${a.most_recent_instance.location.path}#L${a.most_recent_instance.location.start_line}` + : "", a.html_url, ]); } diff --git a/src/context/CodeScanning.ts b/src/context/CodeScanning.ts index 2dfddf2..ee790a3 100644 --- a/src/context/CodeScanning.ts +++ b/src/context/CodeScanning.ts @@ -68,7 +68,9 @@ export class CodeScanning extends Printable implements Feature { a.rule?.security_severity_level || a.rule?.severity || "", this.cweFromTags(a), a.tool?.name || "", - a.most_recent_instance?.location.path || "", + a.most_recent_instance?.location?.path + ? `${a.most_recent_instance.location.path}#L${a.most_recent_instance.location.start_line}` + : "", a.html_url, ]); }