From f8b562b7ddcbadeab993039191e406ab5d15e670 Mon Sep 17 00:00:00 2001 From: Sam David Date: Thu, 26 Sep 2024 22:57:53 +0530 Subject: [PATCH] added vulnerable api finding cvss metrics --- .../file-compare/analysis-details/index.hbs | 8 +- .../file-compare/analysis-details/index.scss | 30 +- app/components/file-compare/index.scss | 2 +- .../vulnerability-details/index.scss | 2 +- .../findings/code-box/index.scss | 1 - .../findings/code-box/index.ts | 1 + .../findings/custom-vulnerabilities/index.hbs | 73 ++-- .../custom-vulnerabilities/index.scss | 113 +++-- .../findings/index.hbs | 1 + .../findings/index.scss | 44 +- .../findings/vulnerable-api/index.hbs | 200 ++++----- .../findings/vulnerable-api/index.ts | 114 ++++- .../vulnerability-analysis-details/index.hbs | 390 +++++++++--------- .../vulnerability-analysis-details/index.scss | 100 +++-- app/styles/_component-variables.scss | 5 + app/utils/parse-vulnerable-api-finding.ts | 10 + .../index-test.js | 280 +++++++++---- .../parse-vulnerable-api-finding-test.js | 58 +++ translations/en.json | 10 + translations/ja.json | 10 + 20 files changed, 946 insertions(+), 506 deletions(-) diff --git a/app/components/file-compare/analysis-details/index.hbs b/app/components/file-compare/analysis-details/index.hbs index 787c6d2673..e0266252c6 100644 --- a/app/components/file-compare/analysis-details/index.hbs +++ b/app/components/file-compare/analysis-details/index.hbs @@ -90,9 +90,11 @@ {{finding.title}} - -
{{finding.description}}
-
+
+
+              {{finding.description}}
+            
+
{{/each}} {{/if}} diff --git a/app/components/file-compare/analysis-details/index.scss b/app/components/file-compare/analysis-details/index.scss index 2a8494263e..97842db303 100644 --- a/app/components/file-compare/analysis-details/index.scss +++ b/app/components/file-compare/analysis-details/index.scss @@ -9,11 +9,11 @@ --file-compare-analysis-details-marked-passed-bg-color ); - :global(.scrollable-box), - :global(.scrollable-box) pre { + .vulnerability-finding-container { background-color: var( --file-compare-analysis-details-marked-passed-vuln-finding-bg-color ); + border: 1px solid var(--file-compare-analysis-details-border-color); } } @@ -22,10 +22,6 @@ flex-direction: column; gap: 0.75em; - code { - @extend .scrollable-box; - } - h1 { font-size: 1.75rem; margin: 0.4em 0 !important; @@ -64,4 +60,26 @@ .analysis-content-value { width: calc(100% - 185px); } + + .vulnerability-finding-container { + width: 100%; + max-width: 600px; + max-height: 300px; + overflow: auto; + text-overflow: clip; + margin: 1em 0; + background-color: var( + --file-compare-analysis-details-findings-code-background-color + ); + border-radius: var(--file-compare-analysis-details-findings-border-radius); + + .vulnerability-finding-description { + background-color: unset; + color: var(--file-compare-analysis-details-findings-color-primary); + white-space: pre-line; + width: max-content; + line-height: normal; + padding: 0.75em; + } + } } diff --git a/app/components/file-compare/index.scss b/app/components/file-compare/index.scss index 6d79aaa4fe..3ee08a2d74 100644 --- a/app/components/file-compare/index.scss +++ b/app/components/file-compare/index.scss @@ -1,7 +1,7 @@ .file-compare-tabs { position: sticky; margin-top: 1.4286em; - top: calc(200px - 0.5em); + top: calc(198px - 0.5em); z-index: 10; background: var(--file-compare-tabs-background-color); } diff --git a/app/components/file-compare/vulnerability-details/index.scss b/app/components/file-compare/vulnerability-details/index.scss index eace638949..affd38b383 100644 --- a/app/components/file-compare/vulnerability-details/index.scss +++ b/app/components/file-compare/vulnerability-details/index.scss @@ -3,7 +3,7 @@ --file-compare-vulnerability-details-header-wrapper-background-color ); position: sticky; - top: calc(200px - 0.5em); + top: calc(198px - 0.5em); z-index: 1; .file-compare-vulnerability-details-header { diff --git a/app/components/file-details/vulnerability-analysis-details/findings/code-box/index.scss b/app/components/file-details/vulnerability-analysis-details/findings/code-box/index.scss index 2522fa8089..c0fcf7dc02 100644 --- a/app/components/file-details/vulnerability-analysis-details/findings/code-box/index.scss +++ b/app/components/file-details/vulnerability-analysis-details/findings/code-box/index.scss @@ -15,7 +15,6 @@ .vulnerability-finding-container { width: 100%; - margin: 1em 0; background-color: var( --file-details-vulnerability-analysis-details-findings-code-box-code-background-color ); diff --git a/app/components/file-details/vulnerability-analysis-details/findings/code-box/index.ts b/app/components/file-details/vulnerability-analysis-details/findings/code-box/index.ts index ba3c0cc613..f7e4e43e81 100644 --- a/app/components/file-details/vulnerability-analysis-details/findings/code-box/index.ts +++ b/app/components/file-details/vulnerability-analysis-details/findings/code-box/index.ts @@ -40,5 +40,6 @@ export default class FileDetailsVulnerabilityAnalysisDetailsFindingsCodeBoxCompo declare module '@glint/environment-ember-loose/registry' { export default interface Registry { 'FileDetails::VulnerabilityAnalysisDetails::Findings::CodeBox': typeof FileDetailsVulnerabilityAnalysisDetailsFindingsCodeBoxComponent; + 'file-details/vulnerability-analysis-details/findings/code-box': typeof FileDetailsVulnerabilityAnalysisDetailsFindingsCodeBoxComponent; } } diff --git a/app/components/file-details/vulnerability-analysis-details/findings/custom-vulnerabilities/index.hbs b/app/components/file-details/vulnerability-analysis-details/findings/custom-vulnerabilities/index.hbs index 4e12407ff3..a1f6666fe5 100644 --- a/app/components/file-details/vulnerability-analysis-details/findings/custom-vulnerabilities/index.hbs +++ b/app/components/file-details/vulnerability-analysis-details/findings/custom-vulnerabilities/index.hbs @@ -1,46 +1,45 @@
- - - {{#if - (and @analysis.isRiskPassedBySystem (gt @analysis.findings.length 0)) - }} - {{t 'evidences'}} - {{else}} - {{t 'vulnerability'}} - {{/if}} - - + + + {{#if + (and @analysis.isRiskPassedBySystem (gt @analysis.findings.length 0)) + }} + {{t 'evidences'}} + {{else}} + {{t 'vulnerability'}} + {{/if}} + + -
- {{#each @customVulnerableFindings as |finding idx|}} - {{#if finding.title}} - - {{finding.title}} - - {{/if}} +
+ {{#each @customVulnerableFindings as |finding idx|}} + {{#if finding.title}} + + {{finding.title}} + + {{/if}} -
-
-            {{finding.description}}
-          
-
- {{/each}} -
+
+
+          {{finding.description}}
+        
+
+ {{/each}} +
\ No newline at end of file diff --git a/app/components/file-details/vulnerability-analysis-details/findings/custom-vulnerabilities/index.scss b/app/components/file-details/vulnerability-analysis-details/findings/custom-vulnerabilities/index.scss index 4f5161fd23..e612507722 100644 --- a/app/components/file-details/vulnerability-analysis-details/findings/custom-vulnerabilities/index.scss +++ b/app/components/file-details/vulnerability-analysis-details/findings/custom-vulnerabilities/index.scss @@ -1,47 +1,84 @@ .analysis-section { - width: 100%; - background-color: var(--file-details-vulnerability-analysis-details-findings-custom-vulnerabilities-background-main); - border: 1px solid var(--file-details-vulnerability-analysis-details-findings-custom-vulnerabilities-border-color); - - &.analysis-overridded-passed { - background-color: var(--file-details-vulnerability-analysis-details-findings-custom-vulnerabilities-marked-passed-background-color); - - .analysis-static-content pre code, - .vulnerability-finding-container { - background-color: var(--file-details-vulnerability-analysis-details-findings-custom-vulnerabilities-marked-passed-code-background-color); - border: 1px solid var(--file-details-vulnerability-analysis-details-findings-custom-vulnerabilities-border-color); - } - } + width: 100%; + background-color: var( + --file-details-vulnerability-analysis-details-findings-custom-vulnerabilities-background-main + ); + + &.analysis-overridded-passed { + background-color: var( + --file-details-vulnerability-analysis-details-findings-custom-vulnerabilities-marked-passed-background-color + ); .analysis-content-title { - padding: 0.75em 1.5em; - border-bottom: 1px solid var(--file-details-vulnerability-analysis-details-findings-custom-vulnerabilities-border-color); + background-color: var( + --file-details-vulnerability-analysis-details-findings-custom-vulnerabilities-marked-passed-background-color + ); + } - h6 { - margin-bottom: 0 !important; - } + .analysis-static-content pre code, + .vulnerability-finding-container { + background-color: var( + --file-details-vulnerability-analysis-details-findings-custom-vulnerabilities-marked-passed-code-background-color + ); + border: 1px solid + var( + --file-details-vulnerability-analysis-details-findings-custom-vulnerabilities-border-color + ); } + } + + .analysis-content-title { + position: sticky; + top: calc(172px + 1.5em); + z-index: 1; + padding: 1em; + border: 1px solid + var( + --file-details-vulnerability-analysis-details-findings-custom-vulnerabilities-border-color + ); + background-color: var( + --file-details-vulnerability-analysis-details-findings-custom-vulnerabilities-background-main + ); - .analysis-content-value { - max-width: 460px; + h6 { + margin-bottom: 0 !important; } + } - .vulnerability-finding-container { - max-width: 600px; - max-height: 300px; - overflow: auto; - text-overflow: clip; - margin: 1em 0; - background-color: var(--file-details-vulnerability-analysis-details-findings-custom-vulnerabilities-code-background-color); - border-radius: var(--file-details-vulnerability-analysis-details-findings-custom-vulnerabilities-border-radius); - - .vulnerability-finding-description { - background-color: unset; - color: var(--file-details-vulnerability-analysis-details-findings-custom-vulnerabilities-color-primary); - white-space: pre-line; - width: max-content; - line-height: normal; - padding: 0.75em; - } + .analysis-content-container { + border-width: 0 1px 1px; + border-style: solid; + border-color: var( + --file-details-vulnerability-analysis-details-findings-custom-vulnerabilities-border-color + ); + } + + .analysis-content-value { + max-width: 460px; + } + + .vulnerability-finding-container { + max-width: 600px; + max-height: 300px; + overflow: auto; + text-overflow: clip; + margin: 1em 0; + background-color: var( + --file-details-vulnerability-analysis-details-findings-custom-vulnerabilities-code-background-color + ); + border-radius: var( + --file-details-vulnerability-analysis-details-findings-custom-vulnerabilities-border-radius + ); + + .vulnerability-finding-description { + background-color: unset; + color: var( + --file-details-vulnerability-analysis-details-findings-custom-vulnerabilities-color-primary + ); + white-space: pre-line; + width: max-content; + line-height: normal; + padding: 0.75em; } -} \ No newline at end of file + } +} diff --git a/app/components/file-details/vulnerability-analysis-details/findings/index.hbs b/app/components/file-details/vulnerability-analysis-details/findings/index.hbs index 74dd044c1d..d71f14e03e 100644 --- a/app/components/file-details/vulnerability-analysis-details/findings/index.hbs +++ b/app/components/file-details/vulnerability-analysis-details/findings/index.hbs @@ -94,6 +94,7 @@ diff --git a/app/components/file-details/vulnerability-analysis-details/findings/index.scss b/app/components/file-details/vulnerability-analysis-details/findings/index.scss index a1a44ba095..d10a5cf164 100644 --- a/app/components/file-details/vulnerability-analysis-details/findings/index.scss +++ b/app/components/file-details/vulnerability-analysis-details/findings/index.scss @@ -3,40 +3,55 @@ background-color: var( --file-details-vulnerability-analysis-details-background-main ); - border: 1px solid var(--file-details-vulnerability-analysis-details-border-color); &.analysis-overridded-passed { background-color: var( --file-details-vulnerability-analysis-details-marked-passed-background-color ); + .analysis-content-title { + background-color: var( + --file-details-vulnerability-analysis-details-marked-passed-background-color + ); + } + .vulnerability-finding-container { background-color: var( --file-details-vulnerability-analysis-details-marked-passed-code-background-color ); - + border: 1px solid var(--file-details-vulnerability-analysis-details-border-color); } } - &:not(:last-child) { - border-bottom: 1px solid - var(--file-details-vulnerability-analysis-details-divider-color); - } - .analysis-content-value { max-width: 460px; } .analysis-content-title { - padding: 0.75em 1.5em; - border-bottom: 1px solid var(--file-details-vulnerability-analysis-details-border-color); + position: sticky; + top: calc(172px + 1.5em); + z-index: 1; + padding: 1em; + background-color: var( + --file-details-vulnerability-analysis-details-background-main + ); + border: 1px solid + var(--file-details-vulnerability-analysis-details-border-color); h6 { margin-bottom: 0em !important; } } + + .analysis-content-container { + border-width: 0 1px 1px; + border-style: solid; + border-color: var( + --file-details-vulnerability-analysis-details-border-color + ); + } } .ak-pagination-button-prev-icon { @@ -54,7 +69,9 @@ .ak-pagination-prev-button, .ak-pagination-next-button { height: 30px; - background-color: var(--file-details-vulnerability-analysis-details-pagination-button-background-color); + background-color: var( + --file-details-vulnerability-analysis-details-pagination-button-background-color + ); min-width: unset; padding-left: 0.143em; padding-right: 0.857em; @@ -68,7 +85,10 @@ .counter-container { padding: 0.3em 0.75em; - border: 1px solid var(--file-details-vulnerability-analysis-details-border-color); - background-color: var(--file-details-vulnerability-analysis-details-code-background-color); + border: 1px solid + var(--file-details-vulnerability-analysis-details-border-color); + background-color: var( + --file-details-vulnerability-analysis-details-code-background-color + ); margin-right: 1em; } diff --git a/app/components/file-details/vulnerability-analysis-details/findings/vulnerable-api/index.hbs b/app/components/file-details/vulnerability-analysis-details/findings/vulnerable-api/index.hbs index ae7ca7d29e..6a5934d4a2 100644 --- a/app/components/file-details/vulnerability-analysis-details/findings/vulnerable-api/index.hbs +++ b/app/components/file-details/vulnerability-analysis-details/findings/vulnerable-api/index.hbs @@ -1,108 +1,114 @@ -
- - {{#each this.currentVulnerabilityDetails as |item|}} - {{#if item.value}} - - - - {{item.label}} - - +
+ {{#each this.currentVulnerabilityDetails as |item|}} + {{#if item.value}} + + + {{item.label}} + - - - {{item.value}} - - - - {{/if}} - {{/each}} + + {{item.value}} + + + {{/if}} + {{/each}} - {{#unless this.isRequestBodyEmpty}} - {{@currentVulnerability.request.body}} - - {{/unless}} + {{#if this.cvssScore}} + - {{#unless this.isRequestHeadersEmpty}} - {{#each-in @currentVulnerability.request.headers as |key value|}}{{key}}: {{value}} - {{/each-in}} - - {{/unless}} + + + {{t 'cvssV3'}} + - {{#unless this.isRequestParamsEmpty}} - {{#each-in @currentVulnerability.request.params as |key value|}}{{key}}: {{value}} - {{/each-in}} - - {{/unless}} + + {{this.cvssScore}} + + + {{/if}} - {{#unless this.isRequestCookiesEmpty}} - {{#each-in @currentVulnerability.response.cookies as |key value|}}{{key}}: {{value}} - {{/each-in}} - - {{/unless}} + {{#if this.hasCvssMetrics}} + - {{#if @currentVulnerability.response.status_code}} - {{this.responseStatusCode}}
{{this.responseMessage}} -
- {{/if}} + + {{t 'cvssMetrics'}} + - {{#unless this.isResponseHeadersEmpty}} - {{#each-in @currentVulnerability.response.headers as |key value|}}{{key}}: {{value}} - {{/each-in}} - - {{/unless}} + - {{#unless this.isResponseCookiesEmpty}} - {{#each-in @currentVulnerability.response.cookies as |key value|}}{{key}}: {{value}} - {{/each-in}} - - {{/unless}} + {{#each this.cvssMetrics as |metric|}} + + + {{metric.label}} + + + + {{metric.value}} + + + {{/each}} + {{/if}} + + {{#each this.vulnerabilityDetails as |detail idx|}} + {{#unless detail.isEmpty}} + {{#if (eq idx 0)}} + + {{/if}} - {{#unless this.isResponseBodyEmpty}} - {{@currentVulnerability.response.text}} - +
+ {{#let + (component + 'file-details/vulnerability-analysis-details/findings/code-box' + title=detail.title + copyIcon=detail.copyIcon + markedAsPassed=@analysis.isOverriddenAsPassed + ) + as |CodeBox| + }} + {{#if detail.isKeyValuePair}} + {{!-- Note: formating will add a new line for each key value pair --}} + {{#each-in detail.value as |key value|}}{{key}}: {{value}} + {{/each-in}} + + {{else}} + {{detail.value}} + {{/if}} + {{/let}} +
{{/unless}} - + {{/each}}
\ No newline at end of file diff --git a/app/components/file-details/vulnerability-analysis-details/findings/vulnerable-api/index.ts b/app/components/file-details/vulnerability-analysis-details/findings/vulnerable-api/index.ts index c1cc070b61..e0bb435510 100644 --- a/app/components/file-details/vulnerability-analysis-details/findings/vulnerable-api/index.ts +++ b/app/components/file-details/vulnerability-analysis-details/findings/vulnerable-api/index.ts @@ -6,13 +6,11 @@ import type AnalysisModel from 'irene/models/analysis'; import type { VulnerableApiFinding } from 'irene/utils/parse-vulnerable-api-finding'; export interface FileDetailsVulnerabilityAnalysisDetailsFindingsVulnerableApiSignature { + Element: HTMLDivElement; Args: { analysis: AnalysisModel; currentVulnerability?: VulnerableApiFinding; }; - Blocks: { - default: []; - }; } export default class FileDetailsVulnerabilityAnalysisDetailsFindingsVulnerableApiComponent extends Component { @@ -114,6 +112,116 @@ export default class FileDetailsVulnerabilityAnalysisDetailsFindingsVulnerableAp return this.args.currentVulnerability?.url; } } + + get cvssScore() { + return this.args.currentVulnerability?.cvssScore; + } + + get cvssMetrics(): Record<'label' | 'value', string | number>[] { + const cvssMetrics = this.args.currentVulnerability?.cvssMetrics; + + if (!cvssMetrics) { + return []; + } + + try { + const metrics = JSON.parse(cvssMetrics.slice(1, -1)); + + return this.cvssMetricsKeyLabel.map(([key, label]) => ({ + label, + value: metrics[key], + })); + } catch (error) { + return []; + } + } + + get cvssMetricsKeyLabel(): [string, string][] { + return [ + ['attackVector', this.intl.t('cvssMetricsLabel.attackVector')], + ['attackComplexity', this.intl.t('cvssMetricsLabel.attackComplexity')], + [ + 'privilegesRequired', + this.intl.t('cvssMetricsLabel.privilegesRequired'), + ], + ['userInteraction', this.intl.t('cvssMetricsLabel.userInteraction')], + ['scope', this.intl.t('cvssMetricsLabel.scope')], + [ + 'confidentialityImpact', + this.intl.t('cvssMetricsLabel.confidentialityImpact'), + ], + ['integrityImpact', this.intl.t('cvssMetricsLabel.integrityImpact')], + [ + 'availabilityImpact', + this.intl.t('cvssMetricsLabel.availabilityImpact'), + ], + ]; + } + + get hasCvssMetrics() { + return this.cvssMetrics.length > 0; + } + + get vulnerabilityDetails() { + const request = this.args.currentVulnerability?.request; + const response = this.args.currentVulnerability?.response; + + return [ + { + title: this.intl.t('requestBody'), + value: request?.body, + isEmpty: this.isRequestBodyEmpty, + copyIcon: true, + }, + { + title: this.intl.t('requestHeaders'), + value: request?.headers, + isEmpty: this.isRequestHeadersEmpty, + copyIcon: true, + isKeyValuePair: true, + }, + { + title: this.intl.t('requestParameters'), + value: request?.params, + isEmpty: this.isRequestParamsEmpty, + copyIcon: true, + isKeyValuePair: true, + }, + { + title: this.intl.t('requestCookies'), + value: request?.cookies, + isEmpty: this.isRequestCookiesEmpty, + copyIcon: true, + isKeyValuePair: true, + }, + { + title: this.intl.t('response'), + value: `${this.responseStatusCode}\n${this.responseMessage}`, + isEmpty: !response?.status_code, + copyIcon: false, + }, + { + title: this.intl.t('responseHeaders'), + value: response?.headers, + isEmpty: this.isResponseHeadersEmpty, + copyIcon: true, + isKeyValuePair: true, + }, + { + title: this.intl.t('responseCookies'), + value: response?.cookies, + isEmpty: this.isResponseCookiesEmpty, + copyIcon: true, + isKeyValuePair: true, + }, + { + title: this.intl.t('responseBody'), + value: response?.text, + isEmpty: this.isResponseBodyEmpty, + copyIcon: true, + }, + ]; + } } declare module '@glint/environment-ember-loose/registry' { diff --git a/app/components/file-details/vulnerability-analysis-details/index.hbs b/app/components/file-details/vulnerability-analysis-details/index.hbs index faa052104f..5862fc2ec0 100644 --- a/app/components/file-details/vulnerability-analysis-details/index.hbs +++ b/app/components/file-details/vulnerability-analysis-details/index.hbs @@ -4,80 +4,82 @@ data-test-analysisDetails-header local-class='analysis-details-header' > -
- - {{#each this.breadcrumbItems as |item|}} - - {{/each}} - +
+
+ + {{#each this.breadcrumbItems as |item|}} + + {{/each}} + - - - - + + - {{t 'testCase'}} - + + {{t 'testCase'}} + - - {{@analysis.vulnerability.name}} - - + + {{@analysis.vulnerability.name}} + + - - - {{t 'typeOfScan'}} - + + {{t 'typeOfScan'}} + - + + - - - - -
- + -
+ +
+ +
+
- +
@@ -90,16 +92,16 @@ @direction='column' class='mb-2' > - +
{{t 'description'}} - +
- + @@ -149,30 +152,32 @@ }}' data-test-analysisDetails-regulatory='cvssv3metrics' > - - {{t 'cvssMetrics'}} - +
+ + {{t 'cvssMetrics'}} + +
- - <:label as |metric|> - - {{metric.key}} - - +
+ + <:label as |metric|> + + {{metric.key}} + + - <:value as |metric|> - - {{metric.value}} - - - + <:value as |metric|> + + {{metric.value}} + + + +
{{/if}} @@ -187,23 +192,25 @@ "analysis-overridded-passed" }}' @direction='column' - @spacing='1.5' > - - {{t 'compliantSolution'}} - +
+ + {{t 'compliantSolution'}} + +
- - {{this.compliantSolution}} - +
+ + {{this.compliantSolution}} + +
{{/if}} @@ -214,23 +221,25 @@ "analysis-overridded-passed" }}' @direction='column' - @spacing='1.5' > - - {{t 'nonCompliantCodeExample'}} - +
+ + {{t 'nonCompliantCodeExample'}} + +
- - {{this.nonCompliantCodeExample}} - +
+ + {{this.nonCompliantCodeExample}} + +
{{/if}} @@ -241,98 +250,103 @@ "analysis-overridded-passed" }}' @direction='column' - @spacing='2' @width='full' > - - {{t 'regulatory'}} - +
+ + {{t 'regulatory'}} + +
- {{#each this.regulatoryContent as |rc|}} - {{#if rc.hasContent}} -
- + {{#each this.regulatoryContent as |rc|}} + {{#if rc.hasContent}} +
- {{rc.heading}} - + + {{rc.heading}} + - {{#if rc.component}} - {{#let (component rc.component) as |Component|}} - - {{/let}} - {{else}} - - {{/if}} -
- {{/if}} - {{/each}} + {{#if rc.component}} + {{#let (component rc.component) as |Component|}} + + {{/let}} + {{else}} + + {{/if}} +
+ {{/if}} + {{/each}} +
{{/if}} {{#if @analysis.vulnerability.businessImplication}} - - {{t 'businessImplication'}} - +
+ + {{t 'businessImplication'}} + +
- - {{this.businessImplication}} - +
+ + {{this.businessImplication}} + +
{{/if}} {{/if}} {{#if @analysis.attachments}} - - {{t 'attachments'}} - +
+ + {{t 'attachments'}} + +
- {{#each @analysis.attachments as |attachment|}} - - {{/each}} +
+ {{#each @analysis.attachments as |attachment|}} + + {{/each}} +
{{/if}} diff --git a/app/components/file-details/vulnerability-analysis-details/index.scss b/app/components/file-details/vulnerability-analysis-details/index.scss index c01977ca9d..32f8f42f70 100644 --- a/app/components/file-details/vulnerability-analysis-details/index.scss +++ b/app/components/file-details/vulnerability-analysis-details/index.scss @@ -6,22 +6,28 @@ ); .analysis-details-header { + padding-bottom: 1.5em; background-color: var( - --file-details-vulnerability-analysis-details-background-main - ); - - box-shadow: var( - --file-details-vulnerability-analysis-details-header-box-shadow + --file-details-vulnerability-analysis-details-background-light ); - - padding: 1.75em 1.5em; - box-sizing: border-box; position: sticky; top: -0.5em; - z-index: calc( var(--file-details-vulnerability-analysis-details-zIndex) - 1 ); + + .analysis-details-header-root { + background-color: var( + --file-details-vulnerability-analysis-details-background-main + ); + + box-shadow: var( + --file-details-vulnerability-analysis-details-header-box-shadow + ); + + padding: 1.75em 1.5em; + box-sizing: border-box; + } } .analysis-details-header-container, @@ -31,15 +37,15 @@ margin: 0 auto; } - .analysis-details-body-container { - margin: 1.5em auto; + .analysis-details-header-container { + display: flex; + flex-direction: column; + height: 130px; + justify-content: space-between; } - .analysis-content-regulatory-title { - width: 100%; - padding: 1em; - border-bottom: 1px solid - var(--file-details-vulnerability-analysis-details-divider-color); + .analysis-details-body-container { + margin: 0 auto; } .analysis-section { @@ -54,6 +60,12 @@ --file-details-vulnerability-analysis-details-marked-passed-background-color ); + .analysis-content-title-container { + background-color: var( + --file-details-vulnerability-analysis-details-marked-passed-background-color + ); + } + .analysis-static-content { pre code { background-color: var( @@ -66,26 +78,8 @@ } } - &.business-implication-section { - border: 1px solid var(--file-details-vulnerability-analysis-details-divider-color); - } - - .analysis-content-description-title { - width: 100%; - padding: 1em; - border-bottom: 1px solid - var(--file-details-vulnerability-analysis-details-divider-color); - } - - &:not(:last-child) { - border: 1px solid - var(--file-details-vulnerability-analysis-details-divider-color); - } - &.analysis-regulatory-section { padding: 0em; - border: 1px solid - var(--file-details-vulnerability-analysis-details-divider-color); .analysis-regulatory-content { width: 100%; @@ -99,6 +93,33 @@ } } + .analysis-section-container { + border: 1px solid + var(--file-details-vulnerability-analysis-details-divider-color); + } + + .analysis-content-title-container { + width: 100%; + padding: 1em; + position: sticky; + top: calc(172px + 1.5em); + z-index: 1; + background-color: var( + --file-details-vulnerability-analysis-details-background-main + ); + border: 1px solid + var(--file-details-vulnerability-analysis-details-divider-color); + } + + .analysis-content-container { + width: 100%; + border-width: 0 1px 1px; + border-style: solid; + border-color: var( + --file-details-vulnerability-analysis-details-divider-color + ); + } + .analysis-static-content { display: flex; flex-direction: column; @@ -127,14 +148,23 @@ } } + code { + color: var(--file-details-vulnerability-analysis-details-color-primary); + font-size: 0.857rem; + font-weight: 400; + padding: 1px 2px 2px; + } + pre { background-color: unset; code { + display: block; width: 600px; max-height: 400px; overflow: auto; margin: 0.5em 0; + padding: 1em; font-size: 1rem; background-color: var( --file-details-vulnerability-analysis-details-code-background-color @@ -149,7 +179,7 @@ } } - .analysis-content-title { + .analysis-content-label { min-width: 250px; max-width: 250px; } diff --git a/app/styles/_component-variables.scss b/app/styles/_component-variables.scss index 10f3664184..8e58d190f2 100644 --- a/app/styles/_component-variables.scss +++ b/app/styles/_component-variables.scss @@ -1163,6 +1163,11 @@ body { --file-compare-analysis-details-marked-passed-vuln-finding-bg-color: var( --neutral-grey-50 ); + --file-compare-analysis-details-findings-code-background-color: var( + --neutral-grey-100 + ); + --file-compare-analysis-details-findings-border-radius: var(--border-radius); + --file-compare-analysis-details-findings-color-primary: var(--primary-main); // variables for file-compare/compare-list --file-compare-compare-list-wrapper-background-color: var(--background-main); diff --git a/app/utils/parse-vulnerable-api-finding.ts b/app/utils/parse-vulnerable-api-finding.ts index 83fc624a88..aa98573ff4 100644 --- a/app/utils/parse-vulnerable-api-finding.ts +++ b/app/utils/parse-vulnerable-api-finding.ts @@ -30,6 +30,8 @@ export interface VulnerableApiResponse { export interface VulnerableApiFinding { severity: string; confidence: string; + cvssScore: number | null; + cvssMetrics: string | null; description: string; url: string; request: VulnerableApiRequest; @@ -64,6 +66,8 @@ function initializeVulnerableApiFinding(): VulnerableApiFinding { confidence: '', url: '', description: '', + cvssScore: null, + cvssMetrics: null, }; } @@ -279,6 +283,8 @@ function updateSection( cookies: currentSection.startsWith('response') ? 'response.cookies' : 'request.cookies', + cvss_base: 'cvssScore', + cvss_metrics_humanized: 'cvssMetrics', }; return sectionMap[key] || currentSection; @@ -321,6 +327,10 @@ function updateFindingField( finding.severity = value; } else if (key === 'confidence') { finding.confidence = value; + } else if (key === 'cvss_base') { + finding.cvssScore = Number(value); + } else if (key === 'cvss_metrics_humanized') { + finding.cvssMetrics = value; } } diff --git a/tests/integration/components/file-details/vulnerability-analysis-details/index-test.js b/tests/integration/components/file-details/vulnerability-analysis-details/index-test.js index 7f51abcd64..c5a47884f6 100644 --- a/tests/integration/components/file-details/vulnerability-analysis-details/index-test.js +++ b/tests/integration/components/file-details/vulnerability-analysis-details/index-test.js @@ -37,6 +37,9 @@ const reqResFormatVulnerability1 = const reqResFormatVulnerability2 = 'https://token.safebrowsing.apple:443/api/v1/google.json: TRACE is enabled in the webserver configuration\nseverity: LOW\n\n\n'; +const reqResFormatVulnerability3 = + 'catalog.api.speechify.com:443/subscriptions/plans/default: CORS header vulnerability found.. Make sure that the header is not assigned a wildcard character.\nconfidence: HIGH\ncvss: CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:L/A:N\ncvss_base: 7.6\ncvss_metrics_humanized: \'{"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:L/A:N", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "REQUIRED", "scope": "CHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "LOW", "availabilityImpact": "NONE", "exploitCodeMaturity": "NOT_DEFINED", "remediationLevel": "NOT_DEFINED", "reportConfidence": "NOT_DEFINED", "confidentialityRequirement": "NOT_DEFINED", "integrityRequirement": "NOT_DEFINED", "availabilityRequirement": "NOT_DEFINED", "modifiedAttackVector": "NETWORK", "modifiedAttackComplexity": "LOW", "modifiedPrivilegesRequired": "LOW", "modifiedUserInteraction": "REQUIRED", "modifiedScope": "NOT_DEFINED", "modifiedConfidentialityImpact": "HIGH", "modifiedIntegrityImpact": "LOW", "modifiedAvailabilityImpact": "NONE", "baseScore": 7.6, "environmentalScore": 7.6, "temporalScore": 7.6, "baseSeverity": "HIGH", "environmentalSeverity": "HIGH", "temporalSeverity": "HIGH"}\'\nrequest:\n body: \'["", ""]\'\n headers:\n Accept: \'*/*\'\n Accept-Encoding: gzip, deflate, br\n Connection: keep-alive\n Content-Length: \'23\'\n Content-Type: application/json\n Host: catalog.api.speechify.com:443\n User-Agent: python-requests/2.32.3\n method: PATCH\n params: {}\n url: https://catalog.api.speechify.com:443/subscriptions/plans/default\nresponse:\n cookies: {}\n headers:\n Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000\n Content-Length: \'74\'\n Date: Fri, 20 Sep 2024 09:11:49 GMT\n Server: Google Frontend\n Via: 1.1 google\n X-Cloud-Trace-Context: 17c083891d6ea81b4f7bf90d60e75c88\n access-control-allow-origin: \'*\'\n content-type: application/json; charset=utf-8\n reason: Unauthorized\n status_code: 401\n text: \'{"message":"Missing auth token","detail":{"message":"Missing auth token"}}\'\n url: https://catalog.api.speechify.com:443/subscriptions/plans/default\n version: 11\nseverity: HIGH\n\n\n'; + class WindowStub extends Service { url = null; target = null; @@ -158,8 +161,9 @@ module( ); }; - // eslint-disable-next-line qunit/require-expect test('it renders analysis details header', async function (assert) { + assert.expect(5); + this.set('analysis', this.file.analyses.toArray()[0]); this.server.get('/organizations/:id/me', (schema, req) => @@ -670,9 +674,6 @@ module( assert.dom('[data-test-analysisDetails-header]').exists(); - const isSystemPassedAndHasFindings = - analysis.isRiskPassedBySystem && analysis.findings.length; - const labels = [ 't:url:()', 't:method:()', @@ -681,115 +682,226 @@ module( 't:issueDetails:()', ]; - if ( - analysis.isRisky || - analysis.isOverriddenAsPassed || - isSystemPassedAndHasFindings - ) { + assert + .dom('[data-test-analysisDetails-vulnerabilityTitle]') + .hasText('t:vulnerableApis:()'); + + if (analysis.findings?.[0].description) { + labels.forEach((label) => { + assert + .dom(`[data-test-analysisDetails-vulFindingLabel="${label}"]`) + .exists(); + }); + assert - .dom('[data-test-analysisDetails-vulnerabilityTitle]') - .hasText('t:vulnerableApis:()'); + .dom('[data-test-analysisDetails-vulFinding-codeTitle]') + .exists({ count: 3 }); - if (analysis.findings?.[0].description) { - labels.forEach((label) => { - assert - .dom(`[data-test-analysisDetails-vulFindingLabel="${label}"]`) - .exists(); - }); + assert + .dom('[data-test-analysisDetails-vulFinding-code]') + .exists({ count: 3 }); - assert - .dom('[data-test-analysisDetails-vulFinding-codeTitle]') - .exists({ count: 3 }); + assert.dom('[data-test-analysisDetails-vulFindingValue]').exists({ + count: 5, + }); - assert - .dom('[data-test-analysisDetails-vulFinding-codeTitle]') - .exists({ count: 3 }); + const values = findAll('[data-test-analysisDetails-vulFindingValue]'); - assert - .dom('[data-test-analysisDetails-vulFinding-code]') - .exists({ count: 3 }); + assert + .dom(values[0]) + .containsText( + 'https://connectivitycheck.gstatic.com:443/generate_204' + ); - assert.dom('[data-test-analysisDetails-vulFindingValue]').exists({ - count: 5, - }); + assert.dom(values[1]).containsText('GET'); - const values = findAll('[data-test-analysisDetails-vulFindingValue]'); + assert.dom(values[2]).containsText('LOW'); - assert - .dom(values[0]) - .containsText( - 'https://connectivitycheck.gstatic.com:443/generate_204' - ); + assert.dom(values[3]).containsText('LOW'); - assert.dom(values[1]).containsText('GET'); + assert + .dom(values[4]) + .containsText( + 'The difference in length between the response to the baseline request and the request returned when sending an attack string exceeds 1000.0 percent' + ); + } - assert.dom(values[2]).containsText('LOW'); + assert + .dom('[data-test-analysisDetails-vulFinding-pagination-prevBtn]') + .isDisabled(); + assert + .dom('[data-test-analysisDetails-vulFinding-pagination-nextBtn]') + .isNotDisabled(); - assert.dom(values[3]).containsText('LOW'); + // Simulate Next Click: Move to the next item + await click('[data-test-analysisDetails-vulFinding-pagination-nextBtn]'); - assert - .dom(values[4]) - .containsText( - 'The difference in length between the response to the baseline request and the request returned when sending an attack string exceeds 1000.0 percent' - ); - } + assert + .dom('[data-test-analysisDetails-vulFinding-pagination-prevBtn]') + .isNotDisabled(); - assert - .dom('[data-test-analysisDetails-vulFinding-pagination-prevBtn]') - .isDisabled(); - assert - .dom('[data-test-analysisDetails-vulFinding-pagination-nextBtn]') - .isNotDisabled(); + assert + .dom('[data-test-analysisDetails-vulFinding-pagination-nextBtn]') + .isDisabled(); - // Simulate Next Click: Move to the next item - await click( - '[data-test-analysisDetails-vulFinding-pagination-nextBtn]' + assert + .dom('[data-test-analysisDetails-vulFinding-codeTitle]') + .doesNotExist(); + + assert + .dom(`[data-test-analysisDetails-vulFindingLabel="t:severity:()"]`) + .exists(); + + assert + .dom(`[data-test-analysisDetails-vulFindingLabel="t:issueDetails:()"]`) + .exists(); + + assert.dom('[data-test-analysisDetails-vulFindingValue]').exists({ + count: 3, + }); + + const values = findAll('[data-test-analysisDetails-vulFindingValue]'); + + assert + .dom(values[0]) + .containsText( + 'https://token.safebrowsing.apple:443/api/v1/google.json' ); - assert - .dom('[data-test-analysisDetails-vulFinding-pagination-prevBtn]') - .isNotDisabled(); + assert.dom(values[1]).containsText('LOW'); - assert - .dom('[data-test-analysisDetails-vulFinding-pagination-nextBtn]') - .isDisabled(); + assert + .dom(values[2]) + .containsText('TRACE is enabled in the webserver configuration'); + }); - assert - .dom('[data-test-analysisDetails-vulFinding-codeTitle]') - .doesNotExist(); + test('it renders analysis details vulnerable api findings with cvss metrics', async function (assert) { + const analysis = this.file.analyses.lastObject; + analysis.risk = ENUMS.RISK.MEDIUM; + analysis.computedRisk = ENUMS.RISK.MEDIUM; + analysis.overriddenRisk = null; - assert - .dom(`[data-test-analysisDetails-vulFindingLabel="t:severity:()"]`) - .exists(); + analysis.findings = [ + { title: null, description: reqResFormatVulnerability3 }, + ]; + + this.set('analysis', analysis); + this.server.get('/organizations/:id/me', (schema, req) => + schema.organizationMes.find(`${req.params.id}`)?.toJSON() + ); + + this.server.get('/profiles/:id', (schema, req) => + schema.profiles.find(`${req.params.id}`)?.toJSON() + ); + + await render( + hbs`` + ); + + assert.dom('[data-test-analysisDetails-header]').exists(); + + const labels = [ + 't:url:()', + 't:method:()', + 't:severity:()', + 't:confidence:()', + 't:issueDetails:()', + ]; + + assert + .dom('[data-test-analysisDetails-vulnerabilityTitle]') + .hasText('t:vulnerableApis:()'); + + // assert labels + labels.forEach((label) => { assert - .dom( - `[data-test-analysisDetails-vulFindingLabel="t:issueDetails:()"]` - ) + .dom(`[data-test-analysisDetails-vulFindingLabel="${label}"]`) .exists(); + }); - assert.dom('[data-test-analysisDetails-vulFindingValue]').exists({ - count: 3, - }); + assert + .dom('[data-test-analysisDetails-vulFinding-codeTitle]') + .exists({ count: 5 }); - const values = findAll('[data-test-analysisDetails-vulFindingValue]'); + assert + .dom('[data-test-analysisDetails-vulFinding-code]') + .exists({ count: 5 }); - assert - .dom(values[0]) - .containsText( - 'https://token.safebrowsing.apple:443/api/v1/google.json' - ); + assert.dom('[data-test-analysisDetails-vulFindingValue]').exists({ + count: 5, + }); + + const values = findAll('[data-test-analysisDetails-vulFindingValue]'); + + assert + .dom(values[0]) + .containsText( + 'https://catalog.api.speechify.com:443/subscriptions/plans/default' + ); + + assert.dom(values[1]).containsText('PATCH'); + + assert.dom(values[2]).containsText('HIGH'); + + assert.dom(values[3]).containsText('HIGH'); - assert.dom(values[1]).containsText('LOW'); + assert + .dom(values[4]) + .containsText( + 'CORS header vulnerability found.. Make sure that the header is not assigned a wildcard character.' + ); + + assert + .dom('[data-test-analysisDetails-vulFinding-pagination-prevBtn]') + .isDisabled(); + + assert + .dom('[data-test-analysisDetails-vulFinding-pagination-nextBtn]') + .isDisabled(); + + assert + .dom('[data-test-analysisDetails-vulFindingCvssLabel]') + .hasText('t:cvssV3:()'); + + assert + .dom('[data-test-analysisDetails-vulFindingCvssValue]') + .hasText('7.6'); + + assert + .dom('[data-test-analysisDetails-vulFindingCvssMetricsLabel]') + .hasText('t:cvssMetrics:()'); + + const metricsLabelValues = [ + { label: 't:cvssMetricsLabel.attackComplexity:()', value: 'LOW' }, + { label: 't:cvssMetricsLabel.attackVector:()', value: 'NETWORK' }, + { label: 't:cvssMetricsLabel.availabilityImpact:()', value: 'NONE' }, + { label: 't:cvssMetricsLabel.confidentialityImpact:()', value: 'HIGH' }, + { label: 't:cvssMetricsLabel.integrityImpact:()', value: 'LOW' }, + { label: 't:cvssMetricsLabel.privilegesRequired:()', value: 'LOW' }, + { label: 't:cvssMetricsLabel.scope:()', value: 'CHANGED' }, + { label: 't:cvssMetricsLabel.userInteraction:()', value: 'REQUIRED' }, + ]; + + metricsLabelValues.forEach((metric) => { + const container = find( + `[data-test-analysisDetails-vulFindingCvssMetric="${metric.label}"]` + ); assert - .dom(values[2]) - .containsText('TRACE is enabled in the webserver configuration'); - } else { + .dom( + '[data-test-analysisDetails-vulFindingCvssMetricLabel]', + container + ) + .hasText(metric.label); + assert - .dom('[data-test-analysisDetails-vulnerabilityContainer]') - .doesNotExist(); - } + .dom( + '[data-test-analysisDetails-vulFindingCvssMetricValue]', + container + ) + .hasText(metric.value); + }); }); test('it renders analysis details with attachments', async function (assert) { diff --git a/tests/unit/utils/parse-vulnerable-api-finding-test.js b/tests/unit/utils/parse-vulnerable-api-finding-test.js index 4538bb8d0f..d8a71fe642 100644 --- a/tests/unit/utils/parse-vulnerable-api-finding-test.js +++ b/tests/unit/utils/parse-vulnerable-api-finding-test.js @@ -75,6 +75,8 @@ module('Unit | Utility | parse-vulnerable-api-finding', function (hooks) { url: 'p157-contacts.icloud.com:443/mm/sub', description: 'A response to one of our payload requests has taken too long compared to the baseline request. This could indicate a vulnerability to time-based Regex DoS attacks', + cvssMetrics: null, + cvssScore: null, }, ]; @@ -103,6 +105,8 @@ module('Unit | Utility | parse-vulnerable-api-finding', function (hooks) { confidence: '', url: 'https://token.safebrowsing.apple:443/api/v1/google.json', description: 'TRACE is enabled in the webserver configuration', + cvssMetrics: null, + cvssScore: null, }, ]; @@ -166,6 +170,8 @@ module('Unit | Utility | parse-vulnerable-api-finding', function (hooks) { url: 'p157-contacts.icloud.com:443/mm/sub', description: 'A response to one of our payload requests has taken too long compared to the baseline request. This could indicate a vulnerability to time-based SQL injection attacks', + cvssMetrics: null, + cvssScore: null, }, { request: { @@ -219,6 +225,57 @@ module('Unit | Utility | parse-vulnerable-api-finding', function (hooks) { confidence: 'LOW', url: '', description: '', + cvssMetrics: null, + cvssScore: null, + }, + ]; + + const content4 = + 'catalog.api.speechify.com:443/subscriptions/plans/default: CORS header vulnerability found.. Make sure that the header is not assigned a wildcard character.\nconfidence: HIGH\ncvss: CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:L/A:N\ncvss_base: 7.6\ncvss_metrics_humanized: \'{"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:L/A:N", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "REQUIRED", "scope": "CHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "LOW", "availabilityImpact": "NONE", "exploitCodeMaturity": "NOT_DEFINED", "remediationLevel": "NOT_DEFINED", "reportConfidence": "NOT_DEFINED", "confidentialityRequirement": "NOT_DEFINED", "integrityRequirement": "NOT_DEFINED", "availabilityRequirement": "NOT_DEFINED", "modifiedAttackVector": "NETWORK", "modifiedAttackComplexity": "LOW", "modifiedPrivilegesRequired": "LOW", "modifiedUserInteraction": "REQUIRED", "modifiedScope": "NOT_DEFINED", "modifiedConfidentialityImpact": "HIGH", "modifiedIntegrityImpact": "LOW", "modifiedAvailabilityImpact": "NONE", "baseScore": 7.6, "environmentalScore": 7.6, "temporalScore": 7.6, "baseSeverity": "HIGH", "environmentalSeverity": "HIGH", "temporalSeverity": "HIGH"}\'\nrequest:\n body: \'["", ""]\'\n headers:\n Accept: \'*/*\'\n Accept-Encoding: gzip, deflate, br\n Connection: keep-alive\n Content-Length: \'23\'\n Content-Type: application/json\n Host: catalog.api.speechify.com:443\n User-Agent: python-requests/2.32.3\n method: PATCH\n params: {}\n url: https://catalog.api.speechify.com:443/subscriptions/plans/default\nresponse:\n cookies: {}\n headers:\n Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000\n Content-Length: \'74\'\n Date: Fri, 20 Sep 2024 09:11:49 GMT\n Server: Google Frontend\n Via: 1.1 google\n X-Cloud-Trace-Context: 17c083891d6ea81b4f7bf90d60e75c88\n access-control-allow-origin: \'*\'\n content-type: application/json; charset=utf-8\n reason: Unauthorized\n status_code: 401\n text: \'{"message":"Missing auth token","detail":{"message":"Missing auth token"}}\'\n url: https://catalog.api.speechify.com:443/subscriptions/plans/default\n version: 11\nseverity: HIGH\n\n\n'; + + const expectedObject4 = [ + { + request: { + body: '\'["", ""]\'', + headers: { + accept: "'*/*'", + 'accept-encoding': 'gzip, deflate, br', + connection: 'keep-alive', + 'content-length': "'23'", + 'content-type': 'application/json', + host: 'catalog.api.speechify.com:443', + 'user-agent': 'python-requests/2.32.3', + }, + cookies: {}, + method: 'PATCH', + params: {}, + url: 'https://catalog.api.speechify.com:443/subscriptions/plans/default', + }, + response: { + headers: { + 'access-control-allow-origin': "'*'", + 'alt-svc': 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000', + 'content-length': "'74'", + 'content-type': 'application/json; charset=utf-8', + date: 'Fri, 20 Sep 2024 09:11:49 GMT', + server: 'Google Frontend', + via: '1.1 google', + 'x-cloud-trace-context': '17c083891d6ea81b4f7bf90d60e75c88', + }, + cookies: {}, + reason: 'Unauthorized', + status_code: 401, + text: '\'{"message":"Missing auth token","detail":{"message":"Missing auth token"}}\'', + url: 'https://catalog.api.speechify.com:443/subscriptions/plans/default', + }, + severity: 'HIGH', + confidence: 'HIGH', + url: 'catalog.api.speechify.com:443/subscriptions/plans/default', + description: + 'CORS header vulnerability found.. Make sure that the header is not assigned a wildcard character.', + cvssMetrics: + '\'{"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:L/A:N", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "REQUIRED", "scope": "CHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "LOW", "availabilityImpact": "NONE", "exploitCodeMaturity": "NOT_DEFINED", "remediationLevel": "NOT_DEFINED", "reportConfidence": "NOT_DEFINED", "confidentialityRequirement": "NOT_DEFINED", "integrityRequirement": "NOT_DEFINED", "availabilityRequirement": "NOT_DEFINED", "modifiedAttackVector": "NETWORK", "modifiedAttackComplexity": "LOW", "modifiedPrivilegesRequired": "LOW", "modifiedUserInteraction": "REQUIRED", "modifiedScope": "NOT_DEFINED", "modifiedConfidentialityImpact": "HIGH", "modifiedIntegrityImpact": "LOW", "modifiedAvailabilityImpact": "NONE", "baseScore": 7.6, "environmentalScore": 7.6, "temporalScore": 7.6, "baseSeverity": "HIGH", "environmentalSeverity": "HIGH", "temporalSeverity": "HIGH"}\'', + cvssScore: 7.6, }, ]; @@ -226,6 +283,7 @@ module('Unit | Utility | parse-vulnerable-api-finding', function (hooks) { { content: content1, expectedObject: expectedObject1 }, { content: content2, expectedObject: expectedObject2 }, { content: content3, expectedObject: expectedObject3 }, + { content: content4, expectedObject: expectedObject4 }, ]; test.each( diff --git a/translations/en.json b/translations/en.json index bcfa11776b..c656cc7fc4 100644 --- a/translations/en.json +++ b/translations/en.json @@ -284,6 +284,16 @@ "cvssV3": "CVSSv3", "cvssExpansion": "Common Vulnerability Scoring System", "cvssMetrics": "CVSS Metrics", + "cvssMetricsLabel": { + "attackVector": "Attack Vector", + "attackComplexity": "Attack Complexity", + "privilegesRequired": "Privileges Required", + "userInteraction": "User Interaction", + "scope": "Scope", + "confidentialityImpact": "Confidentiality Impact", + "integrityImpact": "Integrity Impact", + "availabilityImpact": "Availability Impact" + }, "cwe": "CWE", "cweExpansion": "Common Weakness Enumeration", "dast": "DAST", diff --git a/translations/ja.json b/translations/ja.json index 4af3649dae..2a28a85f70 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -284,6 +284,16 @@ "cvssV3": "CVSSv3", "cvssExpansion": "Common Vulnerability Scoring System", "cvssMetrics": "CVSS Metrics", + "cvssMetricsLabel": { + "attackVector": "Attack Vector", + "attackComplexity": "Attack Complexity", + "privilegesRequired": "Privileges Required", + "userInteraction": "User Interaction", + "scope": "Scope", + "confidentialityImpact": "Confidentiality Impact", + "integrityImpact": "Integrity Impact", + "availabilityImpact": "Availability Impact" + }, "cwe": "CWE", "cweExpansion": "Common Weakness Enumeration", "dast": "DAST",