diff --git a/pkg/sbombastic-image-vulnerability-scanner/components/CveDetails.vue b/pkg/sbombastic-image-vulnerability-scanner/components/CveDetails.vue index 35d9afe..463ba7b 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/components/CveDetails.vue +++ b/pkg/sbombastic-image-vulnerability-scanner/components/CveDetails.vue @@ -31,7 +31,7 @@ export default { PRODUCT_NAME, RESOURCE, PAGE, - cveDetail: cveDetail, + cveDetail: null, rows: images, images_table: VULNERABILITIES_DETAIL_IMAGE_LIST_TABLE, group_by_repository_table: VULNERABILITIES_DETAIL_GROUP_BY_REPOSITORY_TABLE, @@ -49,12 +49,31 @@ export default { } }, - async fetch() { - this.preprocessedDataset = this.preprocessData(this.rows); - console.log("this.preprocessedDataset", this.preprocessedDataset); - }, methods: { + async loadData() { + this.preprocessedDataset = this.preprocessData(this.rows); + console.log("this.preprocessedDataset", this.preprocessedDataset); + + const vulReport = await this.$store.dispatch('cluster/findAll', {type: RESOURCE.VULNERABILITY_REPORT}); + + const cveId = this.$route.params.id; + + this.affectedImages = []; + + const {cveMetaData, affectedImages, totalScanned } = this.getCveMetaData(vulReport, cveId); + + this.affectedImages = affectedImages; + this.totalScanned = totalScanned; + + this.cveDetail = { + ...cveMetaData, + id: cveId, + affectedImages: affectedImages.length, + totalImages: totalScanned, + }; + }, + updateData(event) { console.log("isGrouped", this.isGrouped); }, @@ -89,7 +108,6 @@ export default { }, showVendorPopup(vendor) { this.selectedVendor = vendor; - this.showPopup = true; }, getSeverityColor(severity) { @@ -104,7 +122,125 @@ export default { return colors[severity] || colors.none; }, + getCveMetaData(vulReports, cveId) { + let affectedImages = []; + let cveMetaData = null; + + vulReports.forEach(report => { + const { imageMetadata, report: { results = [] } } = report; + + results.forEach( result => { + (result.vulnerabilities || []).forEach( vuln => { + if (vuln.cve === cveId) { + if(!cveMetaData) { + cveMetaData = { + score: this.getNvdV3Score(vuln.cvss), + sources: this.convertCvssToSources(vuln.cvss), + severity: vuln.severity, + cvssScores: this.convertCvss(vuln.cvss), + description: vuln.title, + title: vuln.title, + advisoryVendors: this.groupReferencesByDomain(vuln.references), + } + } + affectedImages.push({ + image: `${imageMetadata.registryURI}/${imageMetadata.repository}:${imageMetadata.tag}`, + repository: imageMetadata.repository, + registry: imageMetadata.registry, + packageName: vuln.packageName, + packageVersion: vuln.installedVersion, + fixedVersions: vuln.fixedVersions, + severity: vuln.severity, + path: result.target, + cve: vuln.cve + }); + } + }) + }) + }); + + + const totalScanned = vulReports.length; + + return { + cve: cveId, + cveMetaData, + affectedImages, + totalScanned + }; + }, + + groupReferencesByDomain(urls){ + const vendorMap = new Map(); + urls.forEach(url => { + const { hostname } = new URL(url); + + //extract domain base (drop subdomains) + let name = hostname.replace(/^www\./, ''); + const parts = name.split('.'); + if (parts.length > 2) { + name = parts[parts.length - 2]; + }else{ + name = parts[0]; + } + + //Capitalize first letter + name = name.charAt(0).toUpperCase() + name.slice(1); + if( !vendorMap.has(name) ){ + vendorMap.set( name, []); + } + vendorMap.get(name).push(url); + }); + return Array.from(vendorMap.entries()).map( + ([name, references]) => ({ + name, + references, + }) + ); + }, + + convertCvss(cvssObj) { + const cvssScores = []; + Object.entries(cvssObj).forEach(([source, values]) => { + Object.entries(values).forEach(([key, val]) => { + if (key.toLowerCase().includes("score")) { + cvssScores.push({ + source: `${source.charAt(0).toUpperCase() + source.slice(1)} ${key}`, + score: val + }); + } + }) + }); + + return cvssScores; + }, + + getNvdV3Score(cvss) { + if (cvss.nvd && cvss.nvd.v3score) { + return `${cvss.nvd.v3score} (v3)`; + } + return "N/A"; + }, + + convertCvssToSources(cvss){ + return Object.keys(cvss).map(key => { + return { + name: key.toUpperCase(), + link: "" + }; + }); + } + }, + + watch: { + '$route.params.id': { + immediate: true, + handler() { + this.loadData(); + } + } + } } @@ -335,10 +471,10 @@ export default { .description { display: flex; max-width: 900px; - height: 21px; + max-height: calc(21px * 3); flex-direction: column; justify-content: center; - overflow: hidden; + overflow-y: auto; color: #717179; font-family: Lato; font-size: 14px; diff --git a/pkg/sbombastic-image-vulnerability-scanner/components/ImageDetails.vue b/pkg/sbombastic-image-vulnerability-scanner/components/ImageDetails.vue index f033de1..f32ccf9 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/components/ImageDetails.vue +++ b/pkg/sbombastic-image-vulnerability-scanner/components/ImageDetails.vue @@ -424,7 +424,7 @@ export default { getMockVulnerabilityDetails() { return [ { - cveId: 'CVE-2017-5337', + cveId: 'CVE-2018-25032', score: '9.9 (v3)', package: 'tomcat-embed-jasper-9.1', fixAvailable: true, diff --git a/pkg/sbombastic-image-vulnerability-scanner/constants/scan-interval-options.ts b/pkg/sbombastic-image-vulnerability-scanner/constants/scan-interval-options.ts index 006d48a..031de59 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/constants/scan-interval-options.ts +++ b/pkg/sbombastic-image-vulnerability-scanner/constants/scan-interval-options.ts @@ -17,13 +17,11 @@ export const SCAN_INTERVAL_OPTIONS = [ ]; export const REGISTRY_TYPE = { - DOCKERHUB: 'dockerhub' -} - -export const REGISTRY_DEFAULT_URI = { - DOCKERHUB: "index.docker.io" + DOCKERHUB: 'dockerhub', + NO_CATALOG: 'noCatalog' }; export const REGISTRY_TYPE_OPTIONS: {label: string; value: string }[] = [ - { label: 'Docker Hub', value: REGISTRY_TYPE.DOCKERHUB } + { label: 'Docker Hub', value: REGISTRY_TYPE.DOCKERHUB }, + { label: 'No Catalog', value: REGISTRY_TYPE.NO_CATALOG } ]; diff --git a/pkg/sbombastic-image-vulnerability-scanner/data/sbombastic.rancher.io.cveDetails.js b/pkg/sbombastic-image-vulnerability-scanner/data/sbombastic.rancher.io.cveDetails.js index e632399..d00f127 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/data/sbombastic.rancher.io.cveDetails.js +++ b/pkg/sbombastic-image-vulnerability-scanner/data/sbombastic.rancher.io.cveDetails.js @@ -1,5 +1,5 @@ export const cveDetail = { - "id": "CVE-2017-5337", + "id": "CVE-2018-25032", "severity": "critical", "description": "The ReadMATImageV4 function in ImageMagick 7.0.8-7 uses an uninitialized variable, leading to memory corruption.", "score": "9.9", @@ -30,8 +30,8 @@ export const cveDetail = { "name": "SUSE", "references": [ { - "url": "https://www.suse.com/security/cve/CVE-2017-5337/", - "title": "SUSE Security CVE-2017-5337" + "url": "https://www.suse.com/security/cve/CVE-2018-25032/", + "title": "SUSE Security CVE-2018-25032" } ] }, @@ -39,8 +39,8 @@ export const cveDetail = { "name": "Red Hat", "references": [ { - "url": "https://access.redhat.com/security/cve/CVE-2017-5337", - "title": "Red Hat CVE-2017-5337" + "url": "https://access.redhat.com/security/cve/CVE-2018-25032", + "title": "Red Hat CVE-2018-25032" } ] }, @@ -48,8 +48,8 @@ export const cveDetail = { "name": "Alpine", "references": [ { - "url": "https://security.alpinelinux.org/vuln/CVE-2017-5337", - "title": "Alpine Linux CVE-2017-5337" + "url": "https://security.alpinelinux.org/vuln/CVE-2018-25032", + "title": "Alpine Linux CVE-2018-25032" } ] }, @@ -57,8 +57,8 @@ export const cveDetail = { "name": "CISA", "references": [ { - "url": "https://www.cisa.gov/known-exploited-vulnerabilities-catalog/CVE-2017-5337", - "title": "CISA Known Exploited Vulnerabilities - CVE-2017-5337" + "url": "https://www.cisa.gov/known-exploited-vulnerabilities-catalog/CVE-2018-25032", + "title": "CISA Known Exploited Vulnerabilities - CVE-2018-25032" } ] } @@ -67,12 +67,12 @@ export const cveDetail = { { "source": "NVD CVSSv3", "score": 9.9, - "link": "https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?name=CVE-2017-5337" + "link": "https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?name=CVE-2018-25032" }, { "source": "NVD CVSSv2", "score": 9.8, - "link": "https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator?name=CVE-2017-5337" + "link": "https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator?name=CVE-2018-25032" } ], "affectedImages": 150, @@ -83,7 +83,7 @@ export const cveDetail = { "sources": [ { "name": "NVD", - "link": "https://nvd.nist.gov/vuln/detail/CVE-2017-5337" + "link": "https://nvd.nist.gov/vuln/detail/CVE-2018-25032" }, { "name": "GHSA", @@ -106,7 +106,7 @@ export const cveDetail = { "packagePath": "/usr/local/bin/", "repository": "coredns", "registry": "Docker Hub", - "cve": "CVE-2017-5337" + "cve": "CVE-2018-25032" }, { "id": "imagemagick:4.8.5613", @@ -121,7 +121,7 @@ export const cveDetail = { "packagePath": "/usr/local/bin/", "repository": "demo-cody-protected", "registry": "demo.suse-security-ivs.io", - "cve": "CVE-2017-5337" + "cve": "CVE-2018-25032" }, { "id": "centos:7.1908", @@ -136,7 +136,7 @@ export const cveDetail = { "packagePath": "/", "repository": "kube-controller-manager", "registry": "Docker Hub", - "cve": "CVE-2017-5337" + "cve": "CVE-2018-25032" }, { "id": "nginx:1.19.10", @@ -151,7 +151,7 @@ export const cveDetail = { "packagePath": "/", "repository": "kube-apiserver", "registry": "demo.suse-security-ivs.io", - "cve": "CVE-2017-5337" + "cve": "CVE-2018-25032" }, { "id": "docker-compose:1.29.2", @@ -166,7 +166,7 @@ export const cveDetail = { "packagePath": "/usr/bin/", "repository": "coredns", "registry": "Docker Hub", - "cve": "CVE-2017-5337" + "cve": "CVE-2018-25032" }, { "id": "python:3.9.7", @@ -181,7 +181,7 @@ export const cveDetail = { "packagePath": "/home/klipper-helm/lo...", "repository": "flask-app", "registry": "ecr.ap-southeast-emea.2", - "cve": "CVE-2017-5337" + "cve": "CVE-2018-25032" }, { "id": "nodejs:14.17.3", @@ -196,7 +196,7 @@ export const cveDetail = { "packagePath": "/home/klipper-helm/lo...", "repository": "data-store", "registry": "ecr.ap-southeast-emea.2", - "cve": "CVE-2017-5337" + "cve": "CVE-2018-25032" }, { "id": "redis:5.0.7", @@ -211,7 +211,7 @@ export const cveDetail = { "packagePath": "/usr/local/bin/", "repository": "cache-service", "registry": "Docker Hub", - "cve": "CVE-2017-5337" + "cve": "CVE-2018-25032" }, { "id": "mongodb:4.4.1", @@ -226,7 +226,7 @@ export const cveDetail = { "packagePath": "/usr/local/bin/", "repository": "data-store", "registry": "ecr.ap-southeast-emea.2", - "cve": "CVE-2017-5337" + "cve": "CVE-2018-25032" }, { "id": "colangi:1.6.5", @@ -241,7 +241,7 @@ export const cveDetail = { "packagePath": "/usr/bin/", "repository": "api-gateway", "registry": "ecr.ap-southeast-emea.2", - "cve": "CVE-2017-5337" + "cve": "CVE-2018-25032" }, { "id": "ruby:2.7.3", @@ -256,7 +256,7 @@ export const cveDetail = { "packagePath": "/usr/bin/", "repository": "web-application", "registry": "demo.suse-security-ivs.io", - "cve": "CVE-2017-5337" + "cve": "CVE-2018-25032" }, { "id": "postgres:13.4", @@ -271,7 +271,7 @@ export const cveDetail = { "packagePath": "/usr/lib/", "repository": "etcd", "registry": "demo.suse-security-ivs.io", - "cve": "CVE-2017-5337" + "cve": "CVE-2018-25032" }, { "id": "elasticsearch:7.15.2", @@ -286,7 +286,7 @@ export const cveDetail = { "packagePath": "/opt/elasticsearch/", "repository": "search-service", "registry": "demo.suse-security-ivs.io", - "cve": "CVE-2017-5337" + "cve": "CVE-2018-25032" }, { "id": "kafka:2.8.0", @@ -301,7 +301,7 @@ export const cveDetail = { "packagePath": "/usr/local/kafka/", "repository": "message-broker", "registry": "demo.suse-security-ivs.io", - "cve": "CVE-2017-5337" + "cve": "CVE-2018-25032" }, { "id": "jenkins:2.319.1", @@ -316,6 +316,6 @@ export const cveDetail = { "packagePath": "/var/jenkins_home/", "repository": "ci-cd-pipeline", "registry": "Docker Hub", - "cve": "CVE-2017-5337" + "cve": "CVE-2018-25032" } ]; \ No newline at end of file diff --git a/pkg/sbombastic-image-vulnerability-scanner/data/sbombastic.rancher.io.vulnerability.js b/pkg/sbombastic-image-vulnerability-scanner/data/sbombastic.rancher.io.vulnerability.js index bde751f..4af6322 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/data/sbombastic.rancher.io.vulnerability.js +++ b/pkg/sbombastic-image-vulnerability-scanner/data/sbombastic.rancher.io.vulnerability.js @@ -8,9 +8,9 @@ export const severityDistribution = { export const cves = [ { - id: 'CVE-2017-5337', + id: 'CVE-2018-25032', metadata: { - name: 'CVE-2017-5337', + name: 'CVE-2018-25032', }, spec: { scoreV3: '9.9', @@ -26,9 +26,9 @@ export const cves = [ } }, { - id: 'CVE-2017-5336', + id: 'CVE-2022-37434', metadata: { - name: 'CVE-2017-5336', + name: 'CVE-2022-37434', }, spec: { scoreV3: '9.6', @@ -44,9 +44,9 @@ export const cves = [ } }, { - id: 'CVE-2017-5335', + id: 'CVE-2023-42363', metadata: { - name: 'CVE-2017-5335', + name: 'CVE-2023-42363', }, spec: { scoreV3: '8.8', @@ -62,9 +62,9 @@ export const cves = [ } }, { - id: 'CVE-2017-5334', + id: 'CVE-2023-42364', metadata: { - name: 'CVE-2017-5334', + name: 'CVE-2023-42364', }, spec: { scoreV3: '8.6', @@ -80,9 +80,9 @@ export const cves = [ } }, { - id: 'CVE-2017-5333', + id: 'CVE-2023-42365', metadata: { - name: 'CVE-2017-5333', + name: 'CVE-2023-42365', }, spec: { scoreV3: '8.5', @@ -98,9 +98,9 @@ export const cves = [ } }, { - id: 'CVE-2017-5332', + id: 'CVE-2023-42366', metadata: { - name: 'CVE-2017-5332', + name: 'CVE-2023-42366', }, spec: { scoreV3: '7.5', @@ -116,9 +116,9 @@ export const cves = [ } }, { - id: 'CVE-2017-5331', + id: 'CVE-2021-3711', metadata: { - name: 'CVE-2017-5331', + name: 'CVE-2021-3711', }, spec: { scoreV3: '7.2', @@ -134,9 +134,9 @@ export const cves = [ } }, { - id: 'CVE-2017-5330', + id: 'CVE-2020-1967', metadata: { - name: 'CVE-2017-5330', + name: 'CVE-2020-1967', }, spec: { scoreV3: '6.8', @@ -152,9 +152,9 @@ export const cves = [ } }, { - id: 'CVE-2017-5329', + id: 'CVE-2021-23840', metadata: { - name: 'CVE-2017-5329', + name: 'CVE-2021-23840', }, spec: { scoreV3: '5.5', @@ -170,9 +170,9 @@ export const cves = [ } }, { - id: 'CVE-2017-5328', + id: 'CVE-2021-3450', metadata: { - name: 'CVE-2017-5328', + name: 'CVE-2021-3450', }, spec: { scoreV3: '4.3', @@ -188,9 +188,9 @@ export const cves = [ } }, { - id: 'CVE-2017-5327', + id: 'CVE-2021-3712', metadata: { - name: 'CVE-2017-5327', + name: 'CVE-2021-3712', }, spec: { scoreV3: '3.1', @@ -204,23 +204,5 @@ export const cves = [ nonBase: 50, }, } - }, - { - id: 'CVE-2017-5326', - metadata: { - name: 'CVE-2017-5326', - }, - spec: { - scoreV3: '1.0', - severity: 'None', - identifiedImages: { - base: 5, - nonBase: 10, - }, - impactedImages: { - base: 5, - nonBase: 50, - }, - } - }, + } ]; \ No newline at end of file diff --git a/pkg/sbombastic-image-vulnerability-scanner/types/sbombastic-image-vulnerability-scanner.ts b/pkg/sbombastic-image-vulnerability-scanner/types/sbombastic-image-vulnerability-scanner.ts index b89071b..04500a7 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/types/sbombastic-image-vulnerability-scanner.ts +++ b/pkg/sbombastic-image-vulnerability-scanner/types/sbombastic-image-vulnerability-scanner.ts @@ -14,6 +14,9 @@ export const RESOURCE = { REGISTRY: "sbombastic.rancher.io.registry", SCAN_JOB: "sbombastic.rancher.io.scanjob", VEX_HUB: "sbombastic.rancher.io.vexhub", + VULNERABILITY_REPORT: "storage.sbombastic.rancher.io.vulnerabilityreport", + IMAGE: "storage.sbombastic.rancher.io.image", + SBOM: "storage.sbombastic.rancher.io.sbom", }; export const PAGE = { DASHBOARD: "dashboard",