Skip to content

Commit

Permalink
Added Severity Label validation to All Vulns table (CRASM-822) (#720)
Browse files Browse the repository at this point in the history
* Added Severity Label validation to All Vulns table

- Ensured that null or empty string values are displayed as 'N/A' in the severity column of the All Vulns table.
- Ensured that values of Other or any value that does not include 'Critical', 'High', 'Medium', or 'Low' are displayed as 'Other' in the severity column of the All Vulns table..
- Formatted the severity column of the All Vulns table to display the severity label in title case.
- Updated the vulnerability search endpoint to return vulnerabilities with a severity of 'Other' if the severity is not 'Critical', 'High', 'Medium', or 'Low'.
- Updated the vulnerability search endpoint to return vulnerabilities with a severity of 'N/A' if the severity is null or an empty string.
- Updated the vulnerability search endpoint to return vulnerabilities regardless of the case of the severity value.

* Resolved issue with frontend snapshot

- Could be from the HTML encodings for the org search introduced in CRASM-746/PR #691

* Reverted edit to RegionAndOrganizationFilters.tsx

- Added an if statement and a console.log to help troubleshoot a github actions issue.
- This change was reverted because it was erroneously included in the draft pull request.

* Resolve fixes

---------

Co-authored-by: Janson Bunce <janson.bunce@associates.cisa.dhs.gov>
  • Loading branch information
hawkishpolicy and Janson Bunce authored Nov 18, 2024
1 parent 96a12ee commit 36eb23c
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 28 deletions.
25 changes: 22 additions & 3 deletions backend/src/api/vulnerabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,28 @@ class VulnerabilitySearch {
});
}
if (this.filters?.severity) {
qs.andWhere('vulnerability.severity ILIKE :severity', {
severity: `%${this.filters.severity}%`
});
if (this.filters.severity === 'N/A') {
qs.andWhere(
"vulnerability.severity IS NULL OR vulnerability.severity = ''"
);
} else if (this.filters.severity === 'Other') {
qs.andWhere(
`vulnerability.severity NOT ILIKE 'N/A' AND
vulnerability.severity NOT ILIKE 'Low' AND
vulnerability.severity NOT ILIKE 'Medium' AND
vulnerability.severity NOT ILIKE 'High' AND
vulnerability.severity NOT ILIKE 'Critical'AND
vulnerability.severity NOT ILIKE '' OR
vulnerability.severity ILIKE :other`,
{
other: 'Other'
}
);
} else {
qs.andWhere('vulnerability.severity ILIKE :severity', {
severity: `%${this.filters.severity}%`
});
}
}
if (this.filters?.cpe) {
qs.andWhere('vulnerability.cpe ILIKE :cpe', {
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/RegionAndOrganizationFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export const RegionAndOrganizationFilters: React.FC<
regions
}
});

const orgs = results.body.hits.hits.map((hit) => hit._source);
// Filter out organizations that match the exclusions
const refinedOrgs = orgs.filter((org) => {
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/pages/Risk/VulnerabilityBarChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,11 @@ const VulnerabilityBarChart = (props: {

// Place null values in "N/A" and capitalize the first letter of each word in the data.
const titleCaseData: BarData[] = data.map((d) => {
if (d.id === 'null') {
if (d.id === 'null' || d.id === null || d.id === '') {
return { id: 'N/A', value: d.value };
} else {
return {
id: d.id[0].toUpperCase() + d.id.slice(1).toLowerCase(),
id: d.id[0]?.toUpperCase() + d.id.slice(1)?.toLowerCase(),
value: d.value
};
}
Expand Down
67 changes: 44 additions & 23 deletions frontend/src/pages/Vulnerabilities/Vulnerabilities.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -306,29 +306,50 @@ export const Vulnerabilities: React.FC<{ groupBy?: string }> = ({
});
}, [fetchVulnerabilities, initialFilters]);

const vulRows: VulnerabilityRow[] = vulnerabilities.map((vuln) => ({
id: vuln.id,
title: vuln.title,
severity: vuln.severity ?? 'N/A',
kev: vuln.isKev ? 'Yes' : 'No',
domain: vuln?.domain?.name,
domainId: vuln?.domain?.id,
product: vuln.cpe
? vuln.cpe
: vuln.service &&
vuln.service.products &&
vuln.service.products.length > 0 &&
vuln.service.products[0].cpe
? vuln.service.products[0].cpe || 'N/A'
: 'N/A',
createdAt: vuln?.createdAt
? `${differenceInCalendarDays(
Date.now(),
parseISO(vuln?.createdAt)
)} days`
: '',
state: vuln.state + (vuln.substate ? ` (${vuln.substate})` : '')
}));
const vulRows: VulnerabilityRow[] = vulnerabilities.map((vuln) => {
//The following logic is to format irregular severity levels to match those used in VulnerabilityBarChart.tsx

const titleCase = (str: string) =>
str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();

const severityLevels: string[] = ['Low', 'Medium', 'High', 'Critical'];

const formatSeverity = (severity: string) => {
if (severity === null || severity === '' || severity === 'N/A') {
return 'N/A';
} else if (severityLevels.includes(titleCase(severity))) {
return titleCase(severity);
} else {
return 'Other';
}
};

const severity = formatSeverity(vuln.severity ?? '');

return {
id: vuln.id,
title: vuln.title,
severity: severity,
kev: vuln.isKev ? 'Yes' : 'No',
domain: vuln?.domain?.name,
domainId: vuln?.domain?.id,
product: vuln.cpe
? vuln.cpe
: vuln.service &&
vuln.service.products &&
vuln.service.products.length > 0 &&
vuln.service.products[0].cpe
? vuln.service.products[0].cpe || 'N/A'
: 'N/A',
createdAt: vuln?.createdAt
? `${differenceInCalendarDays(
Date.now(),
parseISO(vuln?.createdAt)
)} days`
: '',
state: vuln.state + (vuln.substate ? ` (${vuln.substate})` : '')
};
});

const vulCols: GridColDef[] = [
{
Expand Down

0 comments on commit 36eb23c

Please sign in to comment.