Skip to content

Commit

Permalink
add column to display vulns affecting a given component
Browse files Browse the repository at this point in the history
Signed-off-by: Kaden Emley <[email protected]>
  • Loading branch information
kemley76 committed Jul 31, 2024
1 parent ee47c70 commit dad20e3
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@
class="pa-2 mono pre-formatted"
v-html="sanitize_html(result.code_desc.trim())"
/>
<v-btn
v-if="componentRef"
@click="goToComponent()"
<v-btn v-if="componentRef" @click="goToComponent()"
>See component details <v-icon>mdi-view-list-outline</v-icon></v-btn
>
<!-- eslint-enable vue/no-v-html -->
Expand Down
98 changes: 89 additions & 9 deletions apps/frontend/src/components/cards/sbomview/ComponentTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<v-row>
<v-col>
<v-data-table
:items="items"
:items="components"
:headers="headers"
:items-per-page="-1"
:item-key="'bom-ref'"
Expand All @@ -33,7 +33,7 @@
v-model="headerColumns"
chips
multiple
:items="stringFields"
:items="headerOptions"
/>

<!--
Expand All @@ -43,7 +43,7 @@
mdi-cog-outline
</v-icon>
</template>
<v-autocomplete chips multiple v-modal.items="stringFields"></v-autocomplete>
<v-autocomplete chips multiple v-modal.items="headerOptions"></v-autocomplete>
</v-menu>
-->
</v-card-title>
Expand All @@ -56,6 +56,34 @@
</template>
</template>

<template #[`item.affectingVulnerabilities`]="{item}">
<v-chip-group
v-for="vuln in affectingVulns.get(item['bom-ref'])"
:key="vuln.data.id"
>
<v-tooltip max-width="400" left>
<template #activator="{on}">
<span v-on="on">
<v-chip
outlined
small
:color="severity_color(vuln.hdf.severity)"
>{{ vuln.data.id }}</v-chip
>
</span>
</template>
<template style="word-break: break-word">
{{ vuln.data.title?.substring(0, 100) }}
<template v-if="vuln.data.title?.length || 0 > 100"
>...</template
>
<br />
<b>click to view more details</b>
</template>
</v-tooltip>
</v-chip-group>
</template>

<template #expanded-item="{headers, item}">
<td class="m-10 p-10" :colspan="headers.length">
<v-tabs v-model="tabs">
Expand All @@ -77,7 +105,7 @@
</thead>
<tbody>
<tr
v-for="field in stringFields"
v-for="field in headerOptions"
:key="field"
:colspan="headers.length"
>
Expand Down Expand Up @@ -183,6 +211,8 @@

<script lang="ts">
import {Filter, FilteredDataModule} from '@/store/data_filters';
import {Result} from '@mitre/hdf-converters/src/utils/result';
import {ContextualizedControl} from 'inspecjs';
import * as _ from 'lodash';
import Vue from 'vue';
import Component from 'vue-class-component';
Expand Down Expand Up @@ -223,6 +253,9 @@ interface SBOMComponent {
properties?: Record<string, unknown>[];
tags?: string[];
signature?: Record<string, unknown>[];
// custom
affectingVulnerabilities: string[]; // an array of bom-refs
}
interface Passthrough {
Expand All @@ -242,13 +275,22 @@ export default class ComponentTable extends Vue {
@Prop({type: Object, required: true}) readonly filter!: Filter;
@Prop({required: true}) readonly componentRef!: string | undefined;
headerColumns = ['name', 'version', 'author', 'group', 'type', 'description'];
headerColumns = [
'name',
'version',
'author',
'group',
'type',
'description',
'affectingVulnerabilities'
];
tabs = {tab: null};
search = '';
expanded: SBOMComponent[] = [];
stringFields = [
headerOptions = [
'type',
'mime-type',
'publisher',
Expand All @@ -260,7 +302,8 @@ export default class ComponentTable extends Vue {
'scope',
'copyright',
'cpe',
'purl'
'purl',
'affectingVulnerabilities'
];
mounted() {
Expand All @@ -270,7 +313,9 @@ export default class ComponentTable extends Vue {
if (element) {
element.scrollIntoView({block: 'start', behavior: 'smooth'});
element.parentElement?.parentElement?.classList.add('highlight');
const item = this.items.find((i) => i['bom-ref'] === this.componentRef);
const item = this.components.find(
(i) => i['bom-ref'] === this.componentRef
);
if (item) {
this.expanded = [item];
}
Expand All @@ -286,7 +331,7 @@ export default class ComponentTable extends Vue {
return h;
}
get items(): SBOMComponent[] {
get components(): SBOMComponent[] {
const evaluations = FilteredDataModule.evaluations(
FilteredDataModule.selectedEvaluationIds
);
Expand All @@ -303,6 +348,41 @@ export default class ComponentTable extends Vue {
}
return sboms;
}
get all_filter(): Filter {
return {
fromFile: FilteredDataModule.selectedEvaluationIds
};
}
get affectingVulns(): Map<string, ContextualizedControl[]> {
let vulnMap: Map<string, ContextualizedControl[]> = new Map();
for (const c of this.components) {
// get the component's affecting vulnerabilities
const componentVulns = [];
for (const vulnBomRef of c.affectingVulnerabilities || []) {
let result = this.getVulns(vulnBomRef);
if (result.ok) componentVulns.push(result.value); // TODO: show components with unloaded vulns as errors?
}
// associate component bom-ref with vuln info
if (c['bom-ref']) vulnMap.set(c['bom-ref'], componentVulns);
}
return vulnMap;
}
getVulns(vulnBomRef: string): Result<ContextualizedControl, null> {
const vuln = FilteredDataModule.controls(this.all_filter).find((c) => {
// regex to get the value of bom-ref from the vuln code stored as JSON
let match = c.full_code.match(/"bom-ref": "(?<ref>.*?)"/);
return match ? match.groups?.ref === vulnBomRef : false;
});
if (vuln) return {ok: true, value: vuln};
return {ok: false, error: null};
}
severity_color(severity: string): string {
return `severity${_.startCase(severity)}`;
}
}
</script>

Expand Down

0 comments on commit dad20e3

Please sign in to comment.