Skip to content

Commit

Permalink
Add: EPSS scoring info in CVEs
Browse files Browse the repository at this point in the history
Exploit Prediction Scoring System (EPSS) info is added to CVE info if it
is available.

This provides information on the probabily of exploitation activity for
vulnerabilities.
  • Loading branch information
timopollmeier committed May 24, 2024
1 parent c0e784c commit f87d01f
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 8 deletions.
7 changes: 7 additions & 0 deletions src/web/pages/cves/__tests__/detailspage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ const entity_v2 = Cve.fromElement({
'An information disclosure issue was addressed with improved state management. This issue is fixed in macOS Catalina 10.15.6, watchOS 6.2.8. A malicious application may disclose restricted memory.',
products: 'cpe:/o:apple:mac_os_x:10.15.5 cpe:/o:apple:watchos:6.2.8',
nvts: '',
epss: {
score: 0.5,
percentile: 0.75,
},
cert: {
cert_ref: {
_type: 'CERT-Bund',
Expand Down Expand Up @@ -170,6 +174,9 @@ describe('CVE Detailspage tests', () => {
<CvePage id="CVE-2020-9997" />,
);

expect(baseElement).toHaveTextContent('Score0.50000');
expect(baseElement).toHaveTextContent('Percentile0.75000');

const links = baseElement.querySelectorAll('a');
const icons = getAllByTestId('svg-icon');

Expand Down
16 changes: 11 additions & 5 deletions src/web/pages/cves/__tests__/listpage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ const cve = Cve.fromElement({
severity: '9.3',
description: 'foo bar baz',
usage_type: 'cve',
epss: {
score: 0.5,
percentile: 0.75,
},
});

const reloadInterval = -1;
Expand Down Expand Up @@ -193,11 +197,13 @@ describe('CvesPage tests', () => {

const row = baseElement.querySelectorAll('tr');

expect(row[1]).toHaveTextContent('CVE-2020-9992');
expect(row[1]).toHaveTextContent('foo bar baz');
expect(row[1]).toHaveTextContent('Thu, Oct 22, 2020 9:15 PM CESTA');
expect(row[1]).toHaveTextContent('AV:N/AC:M/Au:N/C:C/I:C/A:C');
expect(row[1]).toHaveTextContent('9.3 (High)');
expect(row[2]).toHaveTextContent('CVE-2020-9992');
expect(row[2]).toHaveTextContent('foo bar baz');
expect(row[2]).toHaveTextContent('Thu, Oct 22, 2020 9:15 PM CESTA');
expect(row[2]).toHaveTextContent('AV:N/AC:M/Au:N/C:C/I:C/A:C');
expect(row[2]).toHaveTextContent('9.3 (High)');
expect(row[2]).toHaveTextContent('0.50000');
expect(row[2]).toHaveTextContent('0.75000');
});

test('should allow to bulk action on page contents', async () => {
Expand Down
19 changes: 18 additions & 1 deletion src/web/pages/cves/details.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const CVSS_PROPS = {
};

const CveDetails = ({entity}) => {
const {cvssBaseVector, description, references = [], severity} = entity;
const {cvssBaseVector, description, references = [], severity, epss} = entity;

return (
<Layout flex="column" grow="1">
Expand Down Expand Up @@ -97,6 +97,23 @@ const CveDetails = ({entity}) => {
</InfoTable>
</DetailsBlock>

{isDefined(epss) && (
<DetailsBlock title={_('EPSS')}>
<InfoTable>
<TableBody>
<TableRow>
<TableData>{_('Score')}</TableData>
<TableData>{epss.score.toFixed(5)}</TableData>
</TableRow>
<TableRow>
<TableData>{_('Percentile')}</TableData>
<TableData>{epss.percentile.toFixed(5)}</TableData>
</TableRow>
</TableBody>
</InfoTable>
</DetailsBlock>
)}

{references.length > 0 && (
<DetailsBlock title={_('References')}>
<InfoTable>
Expand Down
9 changes: 9 additions & 0 deletions src/web/pages/cves/row.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import React from 'react';

import {_} from 'gmp/locale/lang';

import {shorten} from 'gmp/utils/string';

import SeverityBar from 'web/components/bar/severitybar';
Expand All @@ -35,6 +37,7 @@ import EntitiesActions from 'web/entities/actions';
import {RowDetailsToggle} from 'web/entities/row';

import PropTypes from 'web/utils/proptypes';
import {isNumber} from "gmp/utils/identity";

const Row = ({
actionsComponent: ActionsComponent = EntitiesActions,
Expand Down Expand Up @@ -64,6 +67,12 @@ const Row = ({
<TableData>
<SeverityBar severity={entity.severity} />
</TableData>
<TableData>
{isNumber(entity?.epss?.score) ? entity.epss?.score.toFixed(5) : _("N/A")}
</TableData>
<TableData>
{isNumber(entity?.epss?.percentile) ? entity.epss?.percentile.toFixed(5) : _("N/A")}
</TableData>
<ActionsComponent {...props} entity={entity} />
</TableRow>
);
Expand Down
37 changes: 35 additions & 2 deletions src/web/pages/cves/table.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import TableRow from 'web/components/table/row';

import CveDetails from './details';
import CveRow from './row';
import {isDefined} from "gmp/utils/identity.js";

const Header = ({
actionsColumn,
Expand All @@ -45,6 +46,7 @@ const Header = ({
<TableHeader>
<TableRow>
<TableHead
rowSpan="2"
width="8%"
currentSortDir={currentSortDir}
currentSortBy={currentSortBy}
Expand All @@ -53,14 +55,16 @@ const Header = ({
title={_('Name')}
/>
<TableHead
width="62%"
rowSpan="2"
width="52%"
currentSortDir={currentSortDir}
currentSortBy={currentSortBy}
sortBy={sort ? 'description' : false}
onSortChange={onSortChange}
title={_('Description')}
/>
<TableHead
rowSpan="2"
width="13%"
currentSortDir={currentSortDir}
currentSortBy={currentSortBy}
Expand All @@ -69,6 +73,7 @@ const Header = ({
title={_('Published')}
/>
<TableHead
rowSpan="2"
width="17%"
currentSortDir={currentSortDir}
currentSortBy={currentSortBy}
Expand All @@ -77,14 +82,42 @@ const Header = ({
title={_('CVSS Base Vector')}
/>
<TableHead
rowSpan="2"
width="8%"
currentSortDir={currentSortDir}
currentSortBy={currentSortBy}
sortBy={sort ? 'severity' : false}
onSortChange={onSortChange}
title={_('Severity')}
/>
{actionsColumn}
<TableHead colSpan="2">
{"EPSS"}
</TableHead>
{isDefined(actionsColumn) ? (
actionsColumn
) : (
<TableHead rowSpan="2" width="5em" align="center">
{_('Actions')}
</TableHead>
)}
</TableRow>
<TableRow>
<TableHead
width="5%"
currentSortDir={currentSortDir}
currentSortBy={currentSortBy}
sortBy={sort ? 'epss_score' : false}
onSortChange={onSortChange}
title={_('Score')}
/>
<TableHead
width="5%"
currentSortDir={currentSortDir}
currentSortBy={currentSortBy}
sortBy={sort ? 'epss_percentile' : false}
onSortChange={onSortChange}
title={_('Percentile')}
/>
</TableRow>
</TableHeader>
);
Expand Down

0 comments on commit f87d01f

Please sign in to comment.