|
65 | 65 | <div class="mt-2"> |
66 | 66 | <div :id="onPageMenu[cveRecordHeading].anchorId"> |
67 | 67 | <h2 class="title">{{cveRecordHeading}}</h2> |
68 | | - <AdpVulnerabilityEnrichment v-if="publishedRecord.hasCna" |
| 68 | + <AdpVulnerabilityEnrichment |
| 69 | + v-if="publishedRecord.hasCna && !cnaViolation" |
69 | 70 | :datePublished="publishedRecord.datePublished" |
70 | 71 | :containerObject="publishedRecord.cna" |
71 | 72 | :orgId="`cna-${publishedRecord.cna.orgId}`" |
|
82 | 83 | {{onPageMenu[cveRecordHeading].items['CVE Program'].label}} |
83 | 84 | </h1> |
84 | 85 | </AdpVulnerabilityEnrichment> |
| 86 | + <AdpVulnerabilityEnrichment |
| 87 | + v-if="cnaViolation" |
| 88 | + :datePublished="publishedRecord.datePublished" |
| 89 | + :containerObject="publishedRecord.cna" |
| 90 | + :orgId="`cna-${publishedRecord.cna.orgId}`" |
| 91 | + :id="onPageMenu[cveRecordHeading].items['CNA'].anchorId"> |
| 92 | + <h1 class="mb-1 has-text-white"> |
| 93 | + {{ onPageMenu[cveRecordHeading].items['CNA'].label }} |
| 94 | + </h1> |
| 95 | + </AdpVulnerabilityEnrichment> |
85 | 96 | </div> |
86 | 97 | <div v-if="publishedRecord.hasAdp" |
87 | 98 | :id="onPageMenu[adpRecordHeading].anchorId" class="mt-6"> |
@@ -155,6 +166,7 @@ export default { |
155 | 166 | isMessageExpanded: false, |
156 | 167 | isHelpTestShown: false, |
157 | 168 | originalRecordData: usecveRecordStore().recordData || {}, |
| 169 | + cnaViolation: false, |
158 | 170 | cveServicesBaseUrl: this.GenericGlobalsStore.currentServicesUrl, |
159 | 171 | cveRecordStore: usecveRecordStore(), |
160 | 172 | partnerStore: usePartnerStore(), |
@@ -280,12 +292,60 @@ export default { |
280 | 292 | this.publishedRecord = new CveObject(this.cveRecordStore.idData); |
281 | 293 | this.publishedRecord.apply(this.originalRecordData); |
282 | 294 | this.onPageMenuData(); |
| 295 | + this.cnaViolation = this.isViolatingCna(); |
| 296 | +
|
283 | 297 | }, |
| 298 | + isViolatingCna() { |
| 299 | +
|
| 300 | + // If a CVE Program container exists for this CVE record, and one of |
| 301 | + // the references' URLs ends with the following, then the CVE is |
| 302 | + // considered "in violation" and the CNA will be displayed differently |
| 303 | + // to indicate this violation. |
| 304 | +
|
| 305 | + const targetUrl = '/preserving-vulnerability-level-identification'; |
| 306 | +
|
| 307 | + const isViolating = this.publishedRecord.cveProgram?.references.some((ref) => { |
| 308 | +
|
| 309 | + return ref.url.toLowerCase().endsWith(targetUrl); |
| 310 | + }) |
| 311 | +
|
| 312 | + return !!isViolating; |
| 313 | + }, |
| 314 | + handleCnaViolation() { |
| 315 | +
|
| 316 | + // For a CVE record violation, both the subtitle on the on-page menu and |
| 317 | + // the accordion section heading for the CNA are changed to indicate the |
| 318 | + // violation. The CNA accordion section is initially collapsed, which is |
| 319 | + // also a difference from a "conforming" CVE record. |
| 320 | +
|
| 321 | + const cnaLabelRegex = /^CNA:\s+(?<cnaName>.*)$/i; |
| 322 | + const onPageMenuItems = this.onPageMenu[this.cveRecordHeading].items; |
| 323 | + const cnaItem = onPageMenuItems['CNA']; |
| 324 | + const newMenuItems = {}; |
| 325 | + const violationText = 'CNA (incomplete; multiple vulnerabilities)'; |
| 326 | +
|
| 327 | + for (const [key, item] of Object.entries(onPageMenuItems)) { |
| 328 | +
|
| 329 | + if (key !== 'CNA') { |
| 330 | + newMenuItems[key] = item; |
| 331 | + } |
| 332 | + } |
| 333 | +
|
| 334 | + cnaItem.label = cnaItem.label.replace(cnaLabelRegex, |
| 335 | + `${violationText}: $<cnaName>`); |
| 336 | +
|
| 337 | + newMenuItems['CNA'] = cnaItem; |
| 338 | +
|
| 339 | + this.cveRecordStore.accordionState[cnaItem.anchorId] = false; |
| 340 | + } |
284 | 341 | }, |
285 | 342 | beforeMount() { |
286 | 343 |
|
287 | 344 | this.initializeFields(); |
288 | 345 | this.setupAccordionStateOnPageMenu(); |
| 346 | +
|
| 347 | + if (this.isViolatingCna()) |
| 348 | + this.handleCnaViolation(); |
289 | 349 | } |
290 | 350 | }; |
291 | 351 |
|
|
0 commit comments