diff --git a/apps/frontend/src/components/cards/sbomview/ComponentContent.vue b/apps/frontend/src/components/cards/sbomview/ComponentContent.vue index 582ecfce92..0cd17f68c0 100644 --- a/apps/frontend/src/components/cards/sbomview/ComponentContent.vue +++ b/apps/frontend/src/components/cards/sbomview/ComponentContent.vue @@ -106,7 +106,7 @@ function objectToTreeview(obj: Object, id: number): Treeview[] { */ function objectDepth(obj: Object, n: number): number { let max = n; - for (const [key, value] of Object.entries(obj)) { + for (const [_key, value] of Object.entries(obj)) { if (value instanceof Object) { const current = objectDepth(value, n + 1); if (current > max) max = current; diff --git a/apps/frontend/src/components/global/Sidebar.vue b/apps/frontend/src/components/global/Sidebar.vue index ffbfdec40b..f2a2dea011 100644 --- a/apps/frontend/src/components/global/Sidebar.vue +++ b/apps/frontend/src/components/global/Sidebar.vue @@ -61,7 +61,6 @@ import Component, {mixins} from 'vue-class-component'; import {Prop} from 'vue-property-decorator'; import {ServerModule} from '../../store/server'; import {EvaluationModule} from '@/store/evaluations'; -import _ from 'lodash'; @Component({ components: { diff --git a/apps/frontend/src/store/data_filters.ts b/apps/frontend/src/store/data_filters.ts index 6a52dccaaa..fb900d813c 100644 --- a/apps/frontend/src/store/data_filters.ts +++ b/apps/frontend/src/store/data_filters.ts @@ -12,6 +12,7 @@ import { import Store from '@/store/store'; import {execution_unique_key} from '@/utilities/format_util'; import { + componentFitsSeverityFilter, getSbomComponents, getVulnsFromBomRef, isOnlySbomFileId, @@ -521,6 +522,26 @@ export class FilteredData extends VuexModule { const components: SBOMComponent[] = []; const controls = this.controls(filter); // grab every component from each section and apply a filter if necessary + /* return evaluations + .map(getSbomComponents) + .filter((result) => result.ok) + .map((result: {value: SBOMComponentsResult}) => result.value) // compiler typechecking doesn't know that `value` is guaranteed + .flatMap((pair) => { + const executionKey = execution_unique_key(pair.evaluation); + return pair.components.filter((component) => { + if (!component.affectingVulnerabilities?.length) + return filter.severity?.includes('none'); + const vulns = []; + // collect all the controls corresponding to the ids in `affectingVulnerabilities` + for (const vulnRef of component.affectingVulnerabilities) { + const vuln = getVulnsFromBomRef(vulnRef, controls); + if (vuln.ok) vulns.push(vuln!.value); + } + // add the component if it has a vulnerability with an allowable severity + return vulns.some((v) => filter.severity?.includes(v.hdf.severity)); + }).map(component => ({...component, key: `${executionKey}-${component['bom-ref']}`})) + }); */ + for (const evaluation of evaluations) { const sbomComponents: Result = getSbomComponents(evaluation); @@ -529,22 +550,10 @@ export class FilteredData extends VuexModule { const key = `${execution_unique_key(evaluation)}-${component['bom-ref']}`; // filter components by their affecting vulnerabilities if ( - !component.affectingVulnerabilities || - component.affectingVulnerabilities.length === 0 - ) { - if (filter.severity?.includes('none')) - components.push({...component, key}); - } else { - const vulns = []; - // collect all the controls corresponding to the ids in `affectingVulnerabilities` - for (const vulnRef of component.affectingVulnerabilities) { - const vuln = getVulnsFromBomRef(vulnRef, controls); - if (vuln.ok) vulns.push(vuln.value); - } - // add the component if it has a vulnerability with an allowable severity - if (vulns.some((v) => filter.severity?.includes(v.hdf.severity))) - components.push({...component, key}); - } + !filter.severity || + componentFitsSeverityFilter(component, filter.severity, controls) + ) + components.push({...component, key}); } } return components; diff --git a/apps/frontend/src/utilities/sbom_util.ts b/apps/frontend/src/utilities/sbom_util.ts index cd5987d193..0768e1ef8c 100644 --- a/apps/frontend/src/utilities/sbom_util.ts +++ b/apps/frontend/src/utilities/sbom_util.ts @@ -6,7 +6,7 @@ import { } from '@/store/report_intake'; import {JSONValue} from '@mitre/hdf-converters/src/utils/parseJson'; import {Result} from '@mitre/hdf-converters/src/utils/result'; -import {ContextualizedControl} from 'inspecjs'; +import {ContextualizedControl, Severity} from 'inspecjs'; import _ from 'lodash'; export type SBOMProperty = {name: string; value: string}; @@ -129,6 +129,28 @@ export function getVulnsFromBomRef( return {ok: false, error: null}; } +export function componentFitsSeverityFilter( + component: SBOMComponent, + severities: Severity[], + controls: readonly ContextualizedControl[] +): boolean { + // if there are no vulnerabilities, then severity: none must be allowed + if ( + !component.affectingVulnerabilities || + component.affectingVulnerabilities.length === 0 + ) { + return severities.includes('none'); + } + + // collect all the controls corresponding to the ids in `affectingVulnerabilities` + for (const vulnRef of component.affectingVulnerabilities) { + const vuln = getVulnsFromBomRef(vulnRef, controls); + // return true if the vuln has an allowable severity + if (vuln.ok && severities.includes(vuln.value.hdf.severity)) return true; + } + return false; +} + function getSbomPassthroughSection( evaluation: SourcedContextualizedEvaluation ): Result {