From 5d7ecaf8c0b872af51212c5bacab71c1c35ded5d Mon Sep 17 00:00:00 2001 From: Dor Tambour <57690513+dortam888@users.noreply.github.com> Date: Wed, 20 Nov 2024 13:19:13 +0200 Subject: [PATCH] Adding webview logic for non applicable vulnerabilities. (#63) --- .../ApplicabilityEvidence.module.css | 17 ---- .../Page/Dependency/Dependency.test.tsx | 1 + src/components/Page/Dependency/Dependency.tsx | 13 ++- .../ApplicabilityEvidence.module.css | 41 ++++++++++ .../ApplicabilityEvidence.test.tsx | 80 +++++++++++++++++++ .../ApplicabilityEvidence.tsx | 20 ++++- .../InformationTabs.module.css | 7 +- .../UI/InformationTabs/InformationTabs.tsx | 31 ++++++- 8 files changed, 180 insertions(+), 30 deletions(-) delete mode 100644 src/components/Page/Dependency/ApplicabilityEvidence.module.css create mode 100644 src/components/UI/InformationTabs/ApplicabilityEvidence.module.css create mode 100644 src/components/UI/InformationTabs/ApplicabilityEvidence.test.tsx rename src/components/{Page/Dependency => UI/InformationTabs}/ApplicabilityEvidence.tsx (72%) diff --git a/src/components/Page/Dependency/ApplicabilityEvidence.module.css b/src/components/Page/Dependency/ApplicabilityEvidence.module.css deleted file mode 100644 index 3ce43d5a..00000000 --- a/src/components/Page/Dependency/ApplicabilityEvidence.module.css +++ /dev/null @@ -1,17 +0,0 @@ -.rowList { - display: flex; - flex-direction: column; - gap: 16px; -} -.defaultContainer { - display: flex; - flex-direction: column; - gap: 16px; -} -.subtitle { - color: #f0f0f0; - font-size: 12px; - font-style: normal; - font-weight: 600; - line-height: normal; -} diff --git a/src/components/Page/Dependency/Dependency.test.tsx b/src/components/Page/Dependency/Dependency.test.tsx index 0154059c..a8f41c21 100644 --- a/src/components/Page/Dependency/Dependency.test.tsx +++ b/src/components/Page/Dependency/Dependency.test.tsx @@ -116,6 +116,7 @@ describe('Dependency page component', () => { const expectedTexts = [ TABS.WHAT_CAN_I_DO.label, + TABS.CONTEXTUAL_ANALYSIS.label, TABS.CVE_INFORMATION.label, TABS.IMPACT_GRAPH.label ] diff --git a/src/components/Page/Dependency/Dependency.tsx b/src/components/Page/Dependency/Dependency.tsx index f065bd9e..9f141cbb 100644 --- a/src/components/Page/Dependency/Dependency.tsx +++ b/src/components/Page/Dependency/Dependency.tsx @@ -2,23 +2,22 @@ import css from './Dependency.module.css' import Header from '../../UI/Header/Header' import { IDependencyPage } from '../../../model' import InformationTabs, { TABS } from '../../UI/InformationTabs/InformationTabs' -import ApplicabilityEvidence from './ApplicabilityEvidence' export interface Props { data: IDependencyPage } export default function Dependency(props: Props): JSX.Element { - const showApplicabilityEvidence = - props.data.cve?.applicableData?.evidence ?? props.data.cve?.applicableData?.searchTarget return (
- {props.data.cve?.applicableData && showApplicabilityEvidence && ( - - )}
) diff --git a/src/components/UI/InformationTabs/ApplicabilityEvidence.module.css b/src/components/UI/InformationTabs/ApplicabilityEvidence.module.css new file mode 100644 index 00000000..503e2d75 --- /dev/null +++ b/src/components/UI/InformationTabs/ApplicabilityEvidence.module.css @@ -0,0 +1,41 @@ +.rowList { + display: flex; + flex-direction: column; + gap: 16px; +} +.defaultContainer { + display: flex; + flex-direction: column; + gap: 16px; +} +.subtitle { + color: #f0f0f0; + font-size: 12px; + font-style: normal; + font-weight: 600; + line-height: normal; +} + +ul.bulletList { + list-style-type: disc; + padding-left: 20px; +} +ul.bulletList li { + color: white; + font-family: 'Arial', sans-serif; + margin-bottom: 10px; + display: flex; + align-items: center; +} +ul { + list-style-type: disc; + margin-left: 20px; +} + +ol { + list-style-type: decimal; + margin-left: 20px; +} +li { + margin-bottom: 20px; +} diff --git a/src/components/UI/InformationTabs/ApplicabilityEvidence.test.tsx b/src/components/UI/InformationTabs/ApplicabilityEvidence.test.tsx new file mode 100644 index 00000000..19b8c348 --- /dev/null +++ b/src/components/UI/InformationTabs/ApplicabilityEvidence.test.tsx @@ -0,0 +1,80 @@ +import { render, screen } from '@testing-library/react' +import ApplicabilityEvidence from './ApplicabilityEvidence' +import { IApplicableDetails, IEvidence } from '../../../model' + +// Sample data for testing +const applicableData: IApplicableDetails = { + isApplicable: true, + searchTarget: 'Example search target', + evidence: [ + { + filePathEvidence: 'file/path/evidence', + codeEvidence: 'const example = "example";', + reason: 'Reason for applicability' + } as IEvidence + ] +} + +const notApplicableData: IApplicableDetails = { + isApplicable: false, + searchTarget: 'Example search target', + evidence: [ + { + reason: 'Reason for non-applicability' + } as IEvidence + ] +} + +describe('ApplicabilityEvidence component', () => { + test('renders applicable CVE information correctly', () => { + render() + expect(screen.getByText('Contextual Analysis')).toBeInTheDocument() + expect(screen.getByText('Why is this CVE applicable?')).toBeInTheDocument() + expect(screen.getByText('Reason for applicability')).toBeInTheDocument() + expect(screen.getByText('file/path/evidence')).toBeInTheDocument() + expect(screen.getByText('const example = "example";')).toBeInTheDocument() + expect(screen.getByText('What does the scanner check/look for?')).toBeInTheDocument() + expect(screen.getByText('Example search target')).toBeInTheDocument() + }) + + test('renders non-applicable CVE information correctly', () => { + render() + expect(screen.getByText('Contextual Analysis')).toBeInTheDocument() + expect(screen.getByText('Why is this CVE not applicable?')).toBeInTheDocument() + expect(screen.getByText('Reason for non-applicability')).toBeInTheDocument() + expect(screen.getByText('What does the scanner check/look for?')).toBeInTheDocument() + expect(screen.getByText('Example search target')).toBeInTheDocument() + }) + + test('renders evidence section correctly when no evidence provided', () => { + const noEvidenceData: IApplicableDetails = { + isApplicable: true, + searchTarget: 'Example search target', + evidence: [] + } + render() + expect(screen.getByText('Contextual Analysis')).toBeInTheDocument() + expect(screen.getByText('Why is this CVE applicable?')).toBeInTheDocument() + expect(screen.getByText('What does the scanner check/look for?')).toBeInTheDocument() + expect(screen.getByText('Example search target')).toBeInTheDocument() + }) + + test('renders correctly without searchTarget', () => { + const noSearchTargetData: IApplicableDetails = { + isApplicable: true, + evidence: [ + { + filePathEvidence: 'file/path/evidence', + codeEvidence: 'const example = "example";', + reason: 'Reason for applicability' + } as IEvidence + ] + } + render() + expect(screen.getByText('Contextual Analysis')).toBeInTheDocument() + expect(screen.getByText('Why is this CVE applicable?')).toBeInTheDocument() + expect(screen.getByText('file/path/evidence')).toBeInTheDocument() + expect(screen.getByText('const example = "example";')).toBeInTheDocument() + expect(screen.queryByText('What does the scanner check/look for?')).not.toBeInTheDocument() + }) +}) diff --git a/src/components/Page/Dependency/ApplicabilityEvidence.tsx b/src/components/UI/InformationTabs/ApplicabilityEvidence.tsx similarity index 72% rename from src/components/Page/Dependency/ApplicabilityEvidence.tsx rename to src/components/UI/InformationTabs/ApplicabilityEvidence.tsx index 51b82b5a..7c4e16d5 100644 --- a/src/components/Page/Dependency/ApplicabilityEvidence.tsx +++ b/src/components/UI/InformationTabs/ApplicabilityEvidence.tsx @@ -16,12 +16,13 @@ export default function ApplicabilityEvidence(props: Props): JSX.Element { expanded header={

- Applicability Evidence + Contextual Analysis

} >
- {props.data.isApplicable && ( + {/* If CVE is applicable */} + {props.data.isApplicable ? ( <>
Why is this CVE applicable?
@@ -37,6 +38,21 @@ export default function ApplicabilityEvidence(props: Props): JSX.Element {
+ ) : ( + // If CVE is not applicable + <> +
Why is this CVE not applicable?
+
+
+ {props.data.evidence?.map((evidence, i) => ( +
+ +
+ ))} +
+
+ + )} {props.data.searchTarget && ( <> diff --git a/src/components/UI/InformationTabs/InformationTabs.module.css b/src/components/UI/InformationTabs/InformationTabs.module.css index a474f1a9..8a4d896c 100644 --- a/src/components/UI/InformationTabs/InformationTabs.module.css +++ b/src/components/UI/InformationTabs/InformationTabs.module.css @@ -1,7 +1,9 @@ .tabsContainer { display: flex; flex-direction: column; - gap: 16px; + justify-content: space-between; + gap: 8px; + flex-wrap: wrap; overflow: hidden; } @@ -9,8 +11,11 @@ display: flex; flex-direction: column; align-items: flex-start; + flex: 1; + text-align: center; gap: 16px; width: 100%; + cursor: pointer; } .alignCenterFlex { diff --git a/src/components/UI/InformationTabs/InformationTabs.tsx b/src/components/UI/InformationTabs/InformationTabs.tsx index 4ba171ac..bd6bb786 100644 --- a/src/components/UI/InformationTabs/InformationTabs.tsx +++ b/src/components/UI/InformationTabs/InformationTabs.tsx @@ -23,6 +23,7 @@ import { TreeNode } from '../../../model/treeNode' import { toTreeNode } from '../../../utils/utils' import WhatCanIDoTab from './WhatCanIDoTab' import Markdown from '../Markdown/Markdown' +import ApplicabilityEvidence from './ApplicabilityEvidence' export const TABS = { WHAT_CAN_I_DO: { @@ -40,6 +41,10 @@ export const TABS = { IMPACT_GRAPH: { label: 'Impact Graph', key: 'impact_graph' + }, + CONTEXTUAL_ANALYSIS: { + label: 'Contextual Analysis', + key: 'contextual_analysis' } } export const LABELS = { @@ -138,6 +143,12 @@ function InformationTabs(props: Props): JSX.Element { const showMoreInformationTab = props.tabs.includes(TABS.MORE_INFORMATION.key) && (props.data as ISastPage).description + const pageTypeDependency = props.data as IDependencyPage + const showApplicabilityEvidence = + pageTypeDependency.cve?.applicableData?.evidence ?? + pageTypeDependency.cve?.applicableData?.searchTarget + const showContextualAnalysisTab = + showApplicabilityEvidence && props.tabs.includes(TABS.CONTEXTUAL_ANALYSIS.key) return (
@@ -154,6 +165,13 @@ function InformationTabs(props: Props): JSX.Element { label={TABS.WHAT_CAN_I_DO.label} /> )} + {showContextualAnalysisTab && ( + + )} {showCveInformationTab && ( )} + {showContextualAnalysisTab && ( + + {pageTypeDependency.cve?.applicableData && showApplicabilityEvidence && ( + + )} + + )} {showMoreInformationTab && (