Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolves #3394 Search and view basic information for a reserved and rejected CVE ID #3404

Merged
merged 30 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
296381b
Merge pull request #3342 from CVEProject/tat-3340
jdaigneau5 Dec 12, 2024
3557ac6
#3350 Add 1 News article @ Board Minutes (#3357)
rroberge Dec 17, 2024
525a444
#3353 Add 1 Blog @ CVE "Below the Surface" podcast (#3359)
rroberge Dec 17, 2024
383a583
#3551 CNA Enrichment Recognition List for 12/16/24 (#3363)
rroberge Dec 17, 2024
f3df288
#3355 remove references of 'Beta' search (#3360)
athu-tran Dec 17, 2024
e16aae6
add Buefy package; ReportRequestForNonCNAs: add auto-complete CNA sea…
rlxdev Dec 17, 2024
b7aded5
Merge pull request #3365 from CVEProject/rl-2922-missing-cna-lookup_d…
jdaigneau5 Dec 17, 2024
dd3ccf3
Revert "Resolves #2922 - create CNA search box for non-CNA reporting/…
jdaigneau5 Dec 17, 2024
5e1f09e
#3349 Add 7 new CNAs + Update 1 CNA's info (#3369)
rroberge Dec 17, 2024
5ed4223
#3370 Update News "displayOnHomepageOrder" order (#3372)
rroberge Dec 17, 2024
c8f5d8b
Resolves #3355 add feedback link (#3378)
athu-tran Dec 18, 2024
b648586
#3375 Update CNA info & Metrics page (#3377)
rroberge Dec 18, 2024
f2f106e
PublishedRecord: remove "cve-capitalize-first-letter" class from CNA …
rlxdev Dec 18, 2024
2f3d790
Merge pull request #3352 from CVEProject/jd-2812-anchors-int
athu-tran Dec 18, 2024
c264b14
Merge pull request #3382 from CVEProject/rl-3017-correctly-render-cna…
jdaigneau5 Dec 20, 2024
713717c
#3394 show reserved CVE ID on Search Results page
athu-tran Jan 3, 2025
8bc179e
#3394 update comment
athu-tran Jan 3, 2025
e4bc271
Merge pull request #3397 from CVEProject/tat-3394-cve-id
athu-tran Jan 3, 2025
a54ddea
#3394 fix rejected CVE ID with a record case where getting record des…
athu-tran Jan 6, 2025
99cc29a
#3394 move Search Results as page title and for CVE ID found cases: s…
athu-tran Jan 7, 2025
fb22b1a
Merge pull request #3398 from CVEProject/tat-3394-cve-id
athu-tran Jan 7, 2025
0f0a4e8
#3394 fix 'Reserved state' link
athu-tran Jan 7, 2025
b66561e
Merge pull request #3399 from CVEProject/tat-3394-cve-id
athu-tran Jan 7, 2025
03d38aa
#3394 only show assigner name for rejected CVE ID
athu-tran Jan 7, 2025
8b370ee
Merge pull request #3400 from CVEProject/tat-3394-cve-id
athu-tran Jan 7, 2025
19a5736
#3394 show 'Other Results' if there are search results from /search e…
athu-tran Jan 7, 2025
279ebe8
Merge pull request #3401 from CVEProject/tat-3394-cve-id
athu-tran Jan 7, 2025
2aea554
#3394 showing 'Other Results' and help text only when there is a CVE …
athu-tran Jan 7, 2025
8061c4a
Merge pull request #3403 from CVEProject/tat-3394-cve-id
athu-tran Jan 7, 2025
b1662e0
Merge remote-tracking branch 'origin/int' into tat-3394-cve-id
athu-tran Jan 7, 2025
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
66 changes: 46 additions & 20 deletions src/stores/cveListSearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const useCveListSearchStore = defineStore('cveListSearch ', {
cveId: '',
from: 0,
isArecord: undefined,
isAnId: undefined,
isSeachButtonDisabled: true,
isIdOrRecordFound: true,
isPublished: false,
Expand All @@ -19,6 +20,7 @@ export const useCveListSearchStore = defineStore('cveListSearch ', {
isLookUpRecordServerError: false,
isSearchServerError: false,
query: '',
idData: {},
recordData: {},
searchResults: [],
searchType: true,
Expand Down Expand Up @@ -73,42 +75,44 @@ export const useCveListSearchStore = defineStore('cveListSearch ', {
this.isSearching = true;
try{

// * 2nd, query search service
// * query search service
this.totalExecutingRequests = 1;
await this.getSearchResults();

// * Check if keyword is CVE ID
if (this.isCveIdPattern()) {
this.totalExecutingRequests = 2;

// 1st, lookup ID to get Record data, and continue to get CVE Records that mention that ID
// lookup ID to get Record data
this.cveId = this.query.toUpperCase();
await this.getRecordData();
await this.getRecordData();
}

} catch (error) {
throw new Error('search() >> error with getRecordData() and or getSearchResults()');
// if record is not found, find potential reserved/rejected ID
if (this.isCveIdPattern() && Object.keys(this.recordData).length === 0) {
await this.getIdData();
}

throw new Error('search() >> error with getSearchResults(), getRecordData(), or getIdData()');
} finally {
this.isSearching = false;
this.setUpInitialPagination();
}
},
async getRecordData() {
this.isLookingUpRecord = true;
const getRecordUrl = `/api/cve/${this.cveId}`;
const getRecordUrl = `${useGenericGlobalsStore().currentServicesUrl}/api/cve/${this.cveId}`;

try {
axios.defaults.baseURL = useGenericGlobalsStore().currentServicesUrl;
const response = await axios.get(getRecordUrl);
const cveRecordData = response?.data || {};
this.isArecord = true;
this.isIdOrRecordFound = false;
this.isIdOrRecordFound = true;

// format description
let descriptions = [];
cveRecordData.containers?.cna?.descriptions.forEach((description) => {
if (this.isEnglishLanguage(description.lang)) descriptions.push(this.processShowMoreShowLessDescription(description.value));
});
let descriptions = this.processDescriptionsField(cveRecordData);

let recordDataSummary = {
cveId: cveRecordData?.cveMetadata?.cveId || 'No ID provided',
cna: cveRecordData?.containers?.cna?.providerMetadata?.shortName || 'No CNA provided',
Expand All @@ -124,20 +128,42 @@ export const useCveListSearchStore = defineStore('cveListSearch ', {
this.isRejected = true;
}

} catch (e) {
} catch (error) {
this.isLookUpRecordServerError = true;

this.isPublished = false;
this.isReserved = false;
this.isRejected = false;
this.isIdOrRecordFound = false;
this.isArecord = false;
throw new Error('getRecordData >> throwing wrroe')
throw new Error('getRecordData >> throwing error');
} finally {
this.isLookingUpRecord = false;
this.decrement('totalExecutingRequests');
}
},
async getIdData() {
const getIdUrl = `${useGenericGlobalsStore().currentServicesUrl}/api/cve-id/${this.cveId}`;
try {
const response = await axios.get(getIdUrl);
const idData = response || {};
this.isIdOrRecordFound = true;
this.isAnId = true;
if (idData.status === 200 && idData?.data?.error === undefined) {
this.idData = idData.data;
if (idData.state === 'RESERVED') {
this.isReserved = true;
this.isArecord = false;
} else if (this.$store.state.idData.state === 'REJECTED') {
this.isRejected = true;
this.isArecord = false;
}
}

} catch (error) {
throw new Error('getIdData >> throwing error');
}
},
async getSearchResults() {
this.isQueryingSearchService = true;
const searchUrl = `${import.meta.env.VITE_API_BASE_URL}${import.meta.env.VITE_LIST_SEARCH_PATH}`;
Expand Down Expand Up @@ -168,7 +194,7 @@ export const useCveListSearchStore = defineStore('cveListSearch ', {
cveId: result._id,
cna: result?._source?.containers?.cna?.providerMetadata?.shortName || 'No CNA provided',
cnaOrgId: result?._source?.containers?.cna?.providerMetadata?.orgId || '',
descriptions: this.processDescriptionsField(result),
descriptions: this.processDescriptionsField(result?._source),
relevancyScore: result?._score
});
});
Expand All @@ -177,17 +203,17 @@ export const useCveListSearchStore = defineStore('cveListSearch ', {

this.searchResults = parsedResults;
},
processDescriptionsField(result){
processDescriptionsField(recordData){
let descriptions = [];
if (result?._source?.cveMetadata?.state === "PUBLISHED") {
result?._source?.containers?.cna?.descriptions.forEach((description) => {
if (recordData.cveMetadata?.state === "PUBLISHED") {
recordData.containers?.cna?.descriptions.forEach((description) => {
if (this.isEnglishLanguage(description.lang)) descriptions.push(this.processShowMoreShowLessDescription(description.value));
});
} else if (result?._source?.cveMetadata?.state === "REJECTED") {
result?._source?.containers?.cna?.rejectedReasons.forEach((rejectedReason) => {
} else if (recordData.cveMetadata?.state === "REJECTED") {
recordData.containers?.cna?.rejectedReasons.forEach((rejectedReason) => {
if (this.isEnglishLanguage(rejectedReason.lang)) descriptions.push(this.processShowMoreShowLessDescription(rejectedReason.value));
});
} else {
} else { // resevered/rejected ID w/o a CVE record does not have description, and that logic is handled in corresponding Vue file
descriptions.push('No description provided');
}

Expand Down
2 changes: 1 addition & 1 deletion src/views/CVERecord/CVERecord.vue
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ export default {
const errorToStr = error.toString() || '';
if (!errorToStr.match(regex)) {
usecveRecordStore().isPublished = false;
usecveRecordStore().isReserved = false;
usecveRecordStore().isReserved = false; // only a cve-id can be in a 'reserved' state; this should always be false
usecveRecordStore().isRejected = false;
this.handleServerError();
}
Expand Down
75 changes: 62 additions & 13 deletions src/views/CVERecord/SearchResults.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,25 +34,43 @@
<p>You are accessing <span class="has-text-weight-bold">Production</span> data from {{ resultUrl }}</p>
</div>
</div>
<div class="mb-3" v-if="Object.keys(cveListSearchStore.recordData).length > 0">
<h2 class="title">CVE Record Found</h2>
<h2 class="title">Search Results</h2>
<div class="mb-3" v-if="hasRecordData || hasIdData">
<h3 class="title is-size-5 mb-2"> CVE {{ getRecordOrIdLabel }} Found</h3>
<p class="cve-help-text">
See the CVE Record below. If you are searching for this CVE ID in other CVE Records, view the Search Results section below.
<span v-if="hasRecordData">View the CVE {{ getRecordOrIdLabel }} below.</span>
<span v-if="hasIdData">
The <router-link to="/ResourcesSupport/Glossary#glossaryCVEID">CVE ID</router-link> below has no corresponding
<router-link to="/ResourcesSupport/Glossary#glossaryRecord">CVE Record</router-link>.
</span>
If you are searching for this CVE ID in other CVE Records, view the <span class="has-text-weight-bold">Other Results</span> section below.
</p>
<div class="columns cve-columns is-variable is-1-desktop is-0-mobile mt-5 mr-2 mb-0 ml-2">
<div class="columns cve-columns is-variable is-1-desktop is-0-mobile mt-0 mr-2 mb-4 ml-2">
<div class="column cve-column">
<div class="columns cve-columns">
<div class="column cve-column">
<router-link :to="`/CVERecord?id=${cveListSearchStore.recordData.cveId}`" target="_blank">{{ cveListSearchStore.recordData.cveId }}</router-link>
<router-link v-if="hasRecordData"
:to="`/CVERecord?id=${cveListSearchStore.recordData.cveId}`" target="_blank">
{{ cveListSearchStore.recordData.cveId }}
</router-link>
<router-link v-if="hasIdData"
:to="`/CVERecord?id=${cveListSearchStore.idData.cve_id}`" target="_blank">
{{ cveListSearchStore.idData.cve_id}}
</router-link>
</div>
<div class="column cve-column">
<p>
<p v-if="hasRecordData">
<span>CNA: </span>
{{ partnerStore.partnerShortLongNameMap[cveListSearchStore.recordData.cnaOrgId] ? partnerStore.partnerShortLongNameMap[cveListSearchStore.recordData.cnaOrgId] : cveListSearchStore.recordData.cna }}</p>
{{ partnerStore.partnerShortLongNameMap[cveListSearchStore.recordData.cnaOrgId] ? partnerStore.partnerShortLongNameMap[cveListSearchStore.recordData.cnaOrgId] : cveListSearchStore.recordData.cna }}
</p>
<p v-if="hasIdData && cveListSearchStore?.idData?.state === 'REJECTED' && cveListSearchStore?.idData?.owning_cna">
<span>Assigner: </span>
<span>{{ cveListSearchStore.idData.owning_cna }}</span>
</p>
</div>
</div>
<div class="columns cve-columns">
<div class="column cve-column">
<div class="column cve-column" v-if="hasRecordData">
<div v-for="(description, index) in cveListSearchStore.recordData.descriptions" :key="description.key" class="mb-0">
<p v-if="!description.showMore" class="mb-0">
{{ description.firstChunk }}<span v-if="!description.showMore && description.secondChunk.length > 0">...</span>
Expand All @@ -67,15 +85,27 @@
</button>
</div>
</div>
<div class="column cve-column" v-if="hasIdData">
<p v-if="cveListSearchStore.idData.state === 'REJECTED'">
This CVE ID was unused by the <router-link to="/ProgramOrganization/CNAs">CNA</router-link>
</p>
<p v-if="cveListSearchStore.idData.state === 'RESERVED'">
This ID has been reserved by a <router-link to="/ProgramOrganization/CNAs">CNA</router-link> and its corresponding record
will be updated by the assigning CNA once details are available. Learn more about the
<router-link to="/ResourcesSupport/FAQs#pc_cve_recordsreserved_signify_in_cve_record">Reserved state</router-link>.
</p>
</div>
</div>
</div>
</div>
</div>
<div id="cve-search-results-container" v-if="cveListSearchStore.totalSearchResultCount > 0">
<h2 class="title">Search Results</h2>
<p class="cve-help-text" v-if="Object.keys(cveListSearchStore.recordData).length > 0">
Includes all record(s) that reference this CVE ID.
</p>
<div v-if="hasIdData || hasRecordData">
<h3 class="title is-size-5 mb-2">Other Results</h3>
<p class="cve-help-text">
Includes all record(s) that reference this CVE ID.
</p>
</div>
<div class="mt-4 mb-2">
<p>
<span>Showing </span>
Expand Down Expand Up @@ -123,7 +153,7 @@
</div>
</div>
</div>
<div v-if="Object.keys(cveListSearchStore.recordData).length > 0 || cveListSearchStore.totalSearchResultCount > 0">
<div v-if="cveListSearchStore.totalSearchResultCount > 0">
<div class="columns cve-columns" v-for="(result, resultIndex) in cveListSearchStore.searchResults" :key="result.index">
<div class="column cve-column">
<div class="column cve-column" :class="{'cve-top-border': resultIndex !== 0}">
Expand Down Expand Up @@ -282,6 +312,25 @@ function backToTop() {
const websiteEnv = computed(() => {
return import.meta.env.VITE_WEBSITE_ENVIRONMENT;
});

let getRecordOrIdLabel = computed(() => {
if (cveListSearchStore?.isArecord){
return 'Record';
} else if (Object.keys(cveListSearchStore.idData).length > 0) {
return 'ID';
} else {
return '';
}
});

let hasRecordData = computed(() => {
return Object.keys(cveListSearchStore.recordData).length > 0;
});


let hasIdData = computed(() => {
return Object.keys(cveListSearchStore.idData).length > 0;
});
</script>

<style lang="scss">
Expand Down