diff --git a/src/gmp/models/__tests__/cve.js b/src/gmp/models/__tests__/cve.js index 9411b27a1a..48d087e66b 100644 --- a/src/gmp/models/__tests__/cve.js +++ b/src/gmp/models/__tests__/cve.js @@ -140,7 +140,6 @@ describe('CVE model tests', () => { }, }; const cve = Cve.fromElement(elem); - expect(cve.products).toEqual(['foo:bar/dolor', 'ipsum:lorem']); }); @@ -194,40 +193,6 @@ describe('CVE model tests', () => { expect(cve.references).toEqual(res); }); - test('should parse cvss source', () => { - const elem = { - raw_data: { - entry: { - 'published-datetime': '2018-10-10T11:41:23.022Z', - 'last-modified-datetime': '2018-10-10T11:41:23.022Z', - cvss: { - base_metrics: { - source: 'prot://url', - }, - }, - }, - }, - }; - const cve = Cve.fromElement(elem); - - expect(cve.source).toEqual('prot://url'); - }); - - test('should parse summary', () => { - const elem = { - raw_data: { - entry: { - 'published-datetime': '2018-10-10T11:41:23.022Z', - 'last-modified-datetime': '2018-10-10T11:41:23.022Z', - summary: 'lorem ipsum', - }, - }, - }; - const cve = Cve.fromElement(elem); - - expect(cve.description).toEqual('lorem ipsum'); - }); - test('should parse vulnerable products from raw data', () => { const elem = { raw_data: { @@ -245,20 +210,6 @@ describe('CVE model tests', () => { expect(cve.products).toEqual(['lorem', 'ipsum']); }); - test('should delete raw data', () => { - const elem = { - raw_data: { - entry: { - 'published-datetime': {__text: '2018-10-10T11:41:23.022Z'}, - 'last-modified-datetime': {__text: '2018-10-10T11:41:23.022Z'}, - }, - }, - }; - const cve = Cve.fromElement(elem); - - expect(cve.raw_data).toBeUndefined(); - }); - test('should return empty array for references if no raw data is given', () => { const cve = Cve.fromElement({}); diff --git a/src/gmp/models/cpe.js b/src/gmp/models/cpe.js index 270a519a0b..6d51357030 100644 --- a/src/gmp/models/cpe.js +++ b/src/gmp/models/cpe.js @@ -39,12 +39,17 @@ class Cpe extends Info { delete ret.update_time; } - if (isDefined(ret.raw_data) && isDefined(ret.raw_data['cpe-item'])) { - const cpeItem = ret.raw_data['cpe-item']; - if (isDefined(cpeItem._deprecated_by)) { - ret.deprecatedBy = cpeItem._deprecated_by; - } + /* + * This code includes a backup check for deprecated field `raw_data`. + * Once `raw_data` is removed from the API, this backup check can be removed. + */ + + if (ret.deprecated === 1 && isDefined(ret.deprecated_by)) { + ret.deprecatedBy = ret.deprecated_by._cpe_id; + } else if (isDefined(ret.raw_data?.['cpe-item']?._deprecated_by)) { + ret.deprecatedBy = ret.raw_data['cpe-item']._deprecated_by; } + return ret; } } diff --git a/src/gmp/models/cve.js b/src/gmp/models/cve.js index 3a7227ee04..5c90b12d73 100644 --- a/src/gmp/models/cve.js +++ b/src/gmp/models/cve.js @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -import {parseSeverity, parseDate, setProperties} from 'gmp/parser'; +import {parseDate, parseSeverity, setProperties} from 'gmp/parser'; import { parseCvssV2BaseFromVector, parseCvssV3BaseFromVector, @@ -114,52 +114,82 @@ class Cve extends Info { } ret.cvssBaseVector = ret.cvss_vector; - ret.products = isEmpty(ret.products) ? [] : ret.products.split(' '); - - if (isDefined(ret.raw_data) && isDefined(ret.raw_data.entry)) { - const {entry} = ret.raw_data; - ret.publishedTime = parseDate(entry['published-datetime']); - ret.lastModifiedTime = parseDate(entry['last-modified-datetime']); + ret.products = isEmpty(ret.products) ? [] : ret.products.split(' '); - ret.references = map(entry.references, ref => ({ - name: ref.reference.__text, - href: ref.reference._href, + /* + * The following code blocks for published-datetime, last-modified-datetime, products, and references + * include a backup check for deprecated field `raw_data`. + * Once `raw_data` is removed from the API, this check can be removed. + */ + + ret.publishedTime = parseDate( + ret['creationTime'] ?? ret.raw_data?.entry?.['published-datetime'], + ); + ret.lastModifiedTime = parseDate( + ret['modificationTime'] ?? + ret.raw_data?.entry?.['last-modified-datetime'], + ); + + ret.references = []; + if (element.cve && isDefined(element.cve.references?.reference)) { + ret.references = map(element.cve.references.reference, ref => { + let tags = []; + if (isArray(ref.tags.tag)) { + tags = ref.tags.tag; + } else if (isDefined(ref.tags.tag)) { + tags = [ref.tags.tag]; + } + return { + name: ref.url, + tags: tags, + href: ref.url, + }; + }); + } else { + const {entry} = ret.raw_data ?? {}; + const referencesList = entry?.references || []; + ret.references = map(referencesList, ref => ({ + name: ref.reference?.__text, + href: ref.reference?._href, source: ref.source, reference_type: ref._reference_type, })); + } - if ( - isDefined(entry.cvss) && - isDefined(entry.cvss.base_metrics) && - isDefined(entry.cvss.base_metrics.source) - ) { - ret.source = entry.cvss.base_metrics.source; - } - - if (isDefined(entry.summary)) { - // really don't know why entry.summary and ret.description can differ - // but xslt did use the summary and and e.g. the description of - // CVE-2017-2988 was empty but summary not - ret.description = entry.summary; - } - - const products = entry['vulnerable-software-list']; - if (isDefined(products)) { - if (isDefined(products.product)) { - ret.products = isArray(products.product) - ? products.product - : [products.product]; - } else { - ret.products = []; + if ( + ret.products && + ret.products.length === 0 && + isDefined(element.cve?.configuration_nodes?.node) + ) { + const nodes = isArray(element.cve.configuration_nodes.node) + ? element.cve.configuration_nodes.node + : [element.cve.configuration_nodes.node]; + nodes.forEach(node => { + if ( + node.match_string?.vulnerable === 1 && + isDefined(node.match_string?.matched_cpes?.cpe) + ) { + const cpes = isArray(node.match_string.matched_cpes.cpe) + ? node.match_string.matched_cpes.cpe + : [node.match_string.matched_cpes.cpe]; + cpes.forEach(cpe => { + if (isDefined(cpe._id)) { + ret.products.push(cpe._id); + } + }); } - } - - delete ret.raw_data; + }); } else { - ret.references = []; + const productsEntry = + ret.raw_data?.entry?.['vulnerable-software-list']?.product; + if (productsEntry) { + ret.products = isArray(productsEntry) ? productsEntry : [productsEntry]; + } } + ret.products = ret.products.filter(product => product !== ''); + return ret; } } diff --git a/src/web/pages/cves/detailspage.jsx b/src/web/pages/cves/detailspage.jsx index 78e796934b..aefdcf5e4e 100644 --- a/src/web/pages/cves/detailspage.jsx +++ b/src/web/pages/cves/detailspage.jsx @@ -4,6 +4,7 @@ */ import _ from 'gmp/locale'; +import {isDefined} from 'gmp/utils/identity'; import React from 'react'; import DateTime from 'web/components/date/datetime'; import CveIcon from 'web/components/icon/cveicon'; @@ -144,15 +145,23 @@ const EntityInfo = ({entity}) => {
{id}
{_('Published:')}
- + {isDefined(publishedTime) ? ( + + ) : ( + _('N/A') + )}
{_('Modified:')}
- + {isDefined(updateTime) ? : _('N/A')}
{_('Last updated:')}
- + {isDefined(lastModifiedTime) ? ( + + ) : ( + _('N/A') + )}
);