Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions src/views/portfolio/vulnerabilities/SelectAliasModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<template>
<b-modal
id="selectAliasModal"
size="md"
hide-header-close
:title="$t('message.aliases')"
>
<bootstrap-table
ref="table"
:columns="columns"
:data="data"
:options="options"
>
</bootstrap-table>
<template v-slot:modal-footer="{ cancel }">
<b-button size="md" variant="secondary" @click="cancel()">{{
$t('message.cancel')
}}</b-button>
<b-button
size="md"
variant="primary"
@click="$emit('selection', $refs.table.getSelections())"
>{{ $t('message.select') }}</b-button
>
</template>
</b-modal>
</template>

<script>
import xssFilters from 'xss-filters';
import permissionsMixin from '../../../mixins/permissionsMixin';
import common from '../../../shared/common';

export default {
mixins: [permissionsMixin],
data() {
return {
labelIcon: {
dataOn: '\u2713',
dataOff: '\u2715',
},
columns: [
{
field: 'state',
checkbox: true,
align: 'center',
},
{
title: 'Source',
field: 'source',
sortable: false,
formatter(value, row, index) {
return xssFilters.inHTMLData(common.valueWithDefault(value, ''));
},
},
{
title: this.$t('message.name'),
field: 'vulnId',
sortable: true,
formatter(value, row, index) {
return xssFilters.inHTMLData(common.valueWithDefault(value, ''));
},
},
],
data: [],
options: {
search: true,
showColumns: true,
showRefresh: true,
pagination: true,
silentSort: false,
sidePagination: 'server',
queryParamsType: 'pageSize',
pageList: '[10, 25, 50, 100]',
pageSize: 10,
icons: {
refresh: 'fa-refresh',
},
responseHandler: function (res, xhr) {
res.total = xhr.getResponseHeader('X-Total-Count');
return res;
},
url: `${this.$api.BASE_URL}/${this.$api.URL_VULNERABILITY}`,
},
};
},
};
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,23 @@
/>
</b-col>
</b-row>
<b-form-group :label="this.$t('message.aliases')">
<div class="list-group">
<span v-for="alias in resolveAliases(selectableAliases)">
<actionable-list-group-item
:value="alias"
:delete-icon="!isReadonly"
v-on:actionClicked="removeAlias(alias)"
/>
</span>
<actionable-list-group-item
:add-icon="!isReadonly"
v-on:actionClicked="
$root.$emit('bv::show::modal', 'selectAliasModal')
"
/>
</div>
</b-form-group>
<b-form-group :label="this.$t('message.cwe')">
<div class="list-group">
<span v-for="cwe in selectableCwes">
Expand Down Expand Up @@ -893,6 +910,7 @@
}}</b-button>
</template>
<select-cwe-modal v-on:selection="updateCweSelection" />
<select-alias-modal v-on:selection="updateAliasSelection" />
<add-affected-component-modal
v-on:affectedComponentAdded="addAffectedComponent"
/>
Expand All @@ -908,6 +926,7 @@ import { Switch as cSwitch } from '@coreui/vue';
import permissionsMixin from '../../../mixins/permissionsMixin';
import ActionableListGroupItem from '../../components/ActionableListGroupItem';
import SelectCweModal from './SelectCweModal';
import SelectAliasModal from './SelectAliasModal';
import AddAffectedComponentModal from './AddAffectedComponentModal';
import VueEasyPieChart from 'vue-easy-pie-chart';
import { getStyle } from '@coreui/coreui/dist/js/coreui-utilities';
Expand All @@ -924,6 +943,7 @@ export default {
BInputGroupFormInput,
BInputGroupFormSelect,
SelectCweModal,
SelectAliasModal,
AddAffectedComponentModal,
VueEasyPieChart,
VueTagsInput,
Expand All @@ -940,6 +960,7 @@ export default {
currentCritical: 7.1,
cvssv2Test: null,
selectableCwes: [],
selectableAliases: [],
vulnerability: {
vulnId: null, // This has to be null on initial load so that the vulnId gets populated.
source: 'INTERNAL',
Expand Down Expand Up @@ -1483,6 +1504,20 @@ export default {
this.vulnerability.vulnId = response.data;
});
},
resolveAliases: function (aliases) {
let aliasList = [];
if (aliases.length !== 0) {
let keys = Object.keys(aliases[0]);
for (let i = 0; i < keys.length; i++) {
let key = keys[i];
if (key !== 'internalId' && aliases[0][key] !== null) {
aliasList.push(aliases[0][key]);
}
}
return aliasList;
}
return [];
},
createVulnerability: function () {
let url = `${this.$api.BASE_URL}/${this.$api.URL_VULNERABILITY}`;
this.axios
Expand All @@ -1502,6 +1537,7 @@ export default {
cvssV3Vector: this.generateCvssV3Vector(),
owaspRRVector: this.generateOwaspRRVector(),
cwes: this.selectableCwes,
aliases: this.selectableAliases,
affectedComponents: this.vulnerability.affectedComponents,
})
.then((response) => {
Expand Down Expand Up @@ -1542,6 +1578,34 @@ export default {
}
}
},
updateAliasSelection: function (selections) {
this.$root.$emit('bv::hide::modal', 'selectAliasModal');
let alias = this.vulnerability.aliases?.[0] ?? {
internalId: this.vulnerability.vulnId,
cveId: null,
ghsaId: null,
osvId: null,
};

selections.forEach((s) => {
if (s.source === 'NVD') alias.cveId = s.vulnId;
if (s.source === 'GITHUB') alias.ghsaId = s.vulnId;
if (s.source === 'OSV') alias.osvId = s.vulnId;
});

this.selectableAliases = [{ ...alias }];
this.vulnerability.aliases = [{ ...alias }];
},
removeAlias: function (alias) {
if (!this.selectableAliases.length) return;
const oldAliases = this.selectableAliases[0];
const newAliases = {};
Object.keys(oldAliases).forEach((key) => {
newAliases[key] = oldAliases[key] === alias ? null : oldAliases[key];
});
this.selectableAliases = [newAliases];
this.vulnerability.aliases = [newAliases];
},
removeAffectedComponent: function (affectedComponent) {
for (let i = 0; i < this.vulnerability.affectedComponents.length; i++) {
let a = this.vulnerability.affectedComponents[i];
Expand Down
63 changes: 59 additions & 4 deletions src/views/portfolio/vulnerabilities/VulnerabilityDetailsModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,17 @@
</b-row>
<b-form-group :label="this.$t('message.aliases')">
<div class="list-group">
<span v-for="alias in resolveVulnAliases(vulnerability.aliases)">
<span v-for="alias in resolveAliases(selectableAliases)">
<actionable-list-group-item
:value="alias.vulnId"
:delete-icon="false"
:value="alias"
:delete-icon="!isReadonly"
v-on:actionClicked="removeAlias(alias)"
/>
</span>
<actionable-list-group-item
:add-icon="!isReadonly"
v-on:actionClicked="
$root.$emit('bv::show::modal', 'selectCweModal')
$root.$emit('bv::show::modal', 'selectAliasModal')
"
/>
</div>
Expand Down Expand Up @@ -954,6 +955,7 @@
>{{ $t('message.update') }}</b-button
>
</template>
<select-alias-modal v-on:selection="updateAliasSelection" />
<select-cwe-modal v-on:selection="updateCweSelection" />
<add-affected-component-modal
v-on:affectedComponentAdded="addAffectedComponent"
Expand All @@ -970,6 +972,7 @@ import { Switch as cSwitch } from '@coreui/vue';
import permissionsMixin from '../../../mixins/permissionsMixin';
import ActionableListGroupItem from '../../components/ActionableListGroupItem';
import SelectCweModal from './SelectCweModal';
import SelectAliasModal from './SelectAliasModal';
import AddAffectedComponentModal from './AddAffectedComponentModal';
import VueEasyPieChart from 'vue-easy-pie-chart';
import { getStyle } from '@coreui/coreui/dist/js/coreui-utilities';
Expand All @@ -985,6 +988,7 @@ export default {
BInputGroupFormInput,
BInputGroupFormSelect,
SelectCweModal,
SelectAliasModal,
AddAffectedComponentModal,
VueEasyPieChart,
VueTagsInput,
Expand Down Expand Up @@ -1555,6 +1559,12 @@ export default {
if (this.vulnerability.cwes && this.vulnerability.cwes.length > 0) {
this.selectableCwes = this.vulnerability.cwes;
}
if (
this.vulnerability.aliases &&
Object.values(this.vulnerability.aliases).length > 0
) {
this.selectableAliases[0] = this.vulnerability.aliases[0];
}
}
},
},
Expand Down Expand Up @@ -1745,6 +1755,7 @@ export default {
cvssV3Vector: this.generateCvssV3Vector(),
owaspRRVector: this.generateOwaspRRVector(),
cwes: this.selectableCwes,
aliases: this.selectableAliases,
affectedComponents: this.vulnerability.affectedComponents,
})
.then((response) => {
Expand Down Expand Up @@ -1773,6 +1784,50 @@ export default {
this.$toastr.w(this.$t('condition.unsuccessful_action'));
});
},
resolveAliases: function (aliases) {
let aliasList = [];
if (aliases.length !== 0) {
let keys = Object.keys(aliases[0]);
for (let i = 0; i < keys.length; i++) {
let key = keys[i];
if (
key !== 'internalId' &&
key !== 'uuid' &&
aliases[0][key] !== null
) {
aliasList.push(aliases[0][key]);
}
}
return aliasList;
}
return [];
},
updateAliasSelection: function (selections) {
this.$root.$emit('bv::hide::modal', 'selectAliasModal');
let alias = this.vulnerability.aliases?.[0] ?? {
internalId: this.vulnerability.vulnId,
cveId: null,
ghsaId: null,
osvId: null,
};
selections.forEach((s) => {
if (s.source === 'NVD') alias.cveId = s.vulnId;
if (s.source === 'GITHUB') alias.ghsaId = s.vulnId;
if (s.source === 'OSV') alias.osvId = s.vulnId;
});
this.selectableAliases = [{ ...alias }];
this.vulnerability.aliases = [{ ...alias }];
},
removeAlias: function (alias) {
if (!this.selectableAliases.length) return;
const oldAliases = this.selectableAliases[0];
const newAliases = {};
Object.keys(oldAliases).forEach((key) => {
newAliases[key] = oldAliases[key] === alias ? null : oldAliases[key];
});
this.selectableAliases = [newAliases];
this.vulnerability.aliases = [newAliases];
},
updateCweSelection: function (selections) {
this.$root.$emit('bv::hide::modal', 'selectCweModal');
for (let i = 0; i < selections.length; i++) {
Expand Down