From d9f56d8009afd795347294affe8882e9ae2546b2 Mon Sep 17 00:00:00 2001 From: tiagobcx Date: Thu, 2 Nov 2023 13:36:50 +0000 Subject: [PATCH 01/11] adding support for critical severity in the tree and triage --- media/details.css | 15 ++++++++++ media/icons/critical_toggle.svg | 1 + media/icons/critical_untoggle.svg | 1 + package.json | 49 +++++++++++++++++++++++++------ src/commands/filterCommand.ts | 47 +++++++++++++++++++++++++++++ src/models/results.ts | 8 ++++- src/utils/common/commands.ts | 4 +++ src/utils/common/constants.ts | 3 ++ src/utils/triage.ts | 4 +-- src/utils/utils.ts | 2 +- src/views/resultsProviders.ts | 1 + 11 files changed, 122 insertions(+), 13 deletions(-) create mode 100644 media/icons/critical_toggle.svg create mode 100644 media/icons/critical_untoggle.svg diff --git a/media/details.css b/media/details.css index da25bb57..f3cae243 100644 --- a/media/details.css +++ b/media/details.css @@ -74,6 +74,20 @@ width: 100%; } +.select-critical { + margin: 0.4em; + border-color: transparent; + border-radius: 4px; + padding: 0.2em 0.5em 0.2em 1.5em; + background-color: var(--vscode-input-background); + background-image: url("./icons/critical_untoggle.svg"); + background-repeat: no-repeat; + background-size: 0.8em auto; + background-position: 0.4em center; + color: var(--vscode-foreground); + cursor: pointer; +} + .select-high { margin: 0.4em; border-color: transparent; @@ -87,6 +101,7 @@ color: var(--vscode-foreground); cursor: pointer; } + .select-medium { margin: 0.4em; border-color: transparent; diff --git a/media/icons/critical_toggle.svg b/media/icons/critical_toggle.svg new file mode 100644 index 00000000..3ec46f91 --- /dev/null +++ b/media/icons/critical_toggle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/media/icons/critical_untoggle.svg b/media/icons/critical_untoggle.svg new file mode 100644 index 00000000..4d4c9aa7 --- /dev/null +++ b/media/icons/critical_untoggle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/package.json b/package.json index ebfd4c95..2de4025e 100644 --- a/package.json +++ b/package.json @@ -200,6 +200,20 @@ "title": "Clear SCA results tree", "icon": "$(refresh)" }, + { + "command": "ast-results.filterCritical_untoggle", + "category": "ast-results", + "title": "CRITICAL", + "icon": "media/icons/critical_untoggle.svg", + "enablement": "ast-results.isValidCredentials && view == astResults" + }, + { + "command": "ast-results.filterCritical_toggle", + "category": "ast-results", + "title": "CRITICAL", + "icon": "media/icons/critical_toggle.svg", + "enablement": "ast-results.isValidCredentials && view == astResults" + }, { "command": "ast-results.filterHigh_toggle", "category": "ast-results", @@ -256,6 +270,13 @@ "icon": "media/icons/info_untoggle.svg", "enablement": "ast-results.isValidCredentials && view == astResults" }, + { + "command": "ast-results.filterCritical", + "category": "ast-results", + "title": "Filter severity: Critical", + "icon": "media/icons/high_untoggle.svg", + "enablement": "ast-results.isValidCredentials" + }, { "command": "ast-results.filterHigh", "category": "ast-results", @@ -605,43 +626,53 @@ "when": "view == astResults && ast-results.cancelScanButton || view == astResults && !ast-results.createScanButton && ast-results.cancelScanButton" }, { - "command": "ast-results.filterHigh_untoggle", + "command": "ast-results.filterCritical_untoggle", "group": "navigation@1", + "when": "view == astResults && ast-results-critical" + }, + { + "command": "ast-results.filterCritical_toggle", + "group": "navigation@1", + "when": "view == astResults && !ast-results-critical" + }, + { + "command": "ast-results.filterHigh_untoggle", + "group": "navigation@2", "when": "view == astResults && ast-results-high" }, { "command": "ast-results.filterHigh_toggle", - "group": "navigation@1", + "group": "navigation@2", "when": "view == astResults && !ast-results-high" }, { "command": "ast-results.filterMedium_untoggle", - "group": "navigation@2", + "group": "navigation@3", "when": "view == astResults && ast-results-medium" }, { "command": "ast-results.filterMedium_toggle", - "group": "navigation@2", + "group": "navigation@3", "when": "view == astResults && !ast-results-medium" }, { "command": "ast-results.filterLow_untoggle", - "group": "navigation@3", + "group": "navigation@4", "when": "view == astResults && ast-results-low" }, { "command": "ast-results.filterLow_toggle", - "group": "navigation@3", + "group": "navigation@4", "when": "view == astResults && !ast-results-low" }, { "command": "ast-results.filterInfo_untoggle", - "group": "navigation@4", + "group": "navigation@5", "when": "view == astResults && ast-results-info" }, { "command": "ast-results.filterInfo_toggle", - "group": "navigation@4", + "group": "navigation@5", "when": "view == astResults && !ast-results-info" }, { @@ -900,4 +931,4 @@ "pre-commit": "lint-staged" } } -} +} \ No newline at end of file diff --git a/src/commands/filterCommand.ts b/src/commands/filterCommand.ts index 717fc6d2..b8973bfa 100644 --- a/src/commands/filterCommand.ts +++ b/src/commands/filterCommand.ts @@ -15,6 +15,7 @@ export class FilterCommand { context: vscode.ExtensionContext; logs: Logs; private activeSeverities: SeverityLevel[] = [ + SeverityLevel.critical, SeverityLevel.high, SeverityLevel.medium, ]; @@ -38,6 +39,7 @@ export class FilterCommand { } public registerFilters() { + this.registerFilterCriticalCommand(); this.registerFilterHighCommand(); this.registerFilterMediumCommand(); this.registerFilterLowCommand(); @@ -53,6 +55,11 @@ export class FilterCommand { public async initializeFilters() { this.logs.info(messages.initilizeSeverities); + + const critical = this.context.globalState.get(constants.criticalFilter) ?? true; + this.updateSeverities(SeverityLevel.critical, critical); + await updateStateFilter(this.context, constants.criticalFilter, critical); + const high = this.context.globalState.get(constants.highFilter) ?? true; this.updateSeverities(SeverityLevel.high, high); await updateStateFilter(this.context, constants.highFilter, high); @@ -106,6 +113,46 @@ export class FilterCommand { await vscode.commands.executeCommand(commands.refreshTree); } + + private registerFilterCriticalCommand() { + this.context.subscriptions.push( + vscode.commands.registerCommand( + commands.filterCriticalToggle, + async () => + await this.filter( + this.logs, + this.context, + SeverityLevel.critical, + constants.criticalFilter + ) + ) + ); + this.context.subscriptions.push( + vscode.commands.registerCommand( + commands.filterCriticalUntoggle, + async () => + await this.filter( + this.logs, + this.context, + SeverityLevel.critical, + constants.criticalFilter + ) + ) + ); + this.context.subscriptions.push( + vscode.commands.registerCommand( + commands.filterCritical, + async () => + await this.filter( + this.logs, + this.context, + SeverityLevel.critical, + constants.criticalFilter + ) + ) + ); + } + private registerFilterHighCommand() { this.context.subscriptions.push( vscode.commands.registerCommand( diff --git a/src/models/results.ts b/src/models/results.ts index d8dc6bbf..a6518021 100644 --- a/src/models/results.ts +++ b/src/models/results.ts @@ -114,6 +114,8 @@ export class AstResult extends CxResult { getIcon() { switch (this.severity) { + case "CRITICAL": + return path.join("media", "icons", "critical_untoggle.svg"); case "HIGH": return path.join("media", "icons", "high_untoggle.svg"); case "MEDIUM": @@ -175,6 +177,8 @@ export class AstResult extends CxResult { getSeverityCode() { switch (this.severity) { + case "CRITICAL": + return vscode.DiagnosticSeverity.Error; case "HIGH": return vscode.DiagnosticSeverity.Error; case "MEDIUM": @@ -189,6 +193,8 @@ export class AstResult extends CxResult { getSeverity() { switch (this.severity) { + case "CRITICAL": + return SeverityLevel.critical; case "HIGH": return SeverityLevel.high; case "MEDIUM": @@ -705,7 +711,7 @@ export class AstResult extends CxResult { Score

- ${result.vulnerabilityDetails.cvssScore.toFixed(1)} + ${result.vulnerabilityDetails && result.vulnerabilityDetails.cvssScore ? result.vulnerabilityDetails.cvssScore.toFixed(1) : ""}

diff --git a/src/utils/common/commands.ts b/src/utils/common/commands.ts index 37b3f363..1225cd77 100644 --- a/src/utils/common/commands.ts +++ b/src/utils/common/commands.ts @@ -12,6 +12,10 @@ export const commands = { isScanEnabled: `${constants.extensionName}.isScanEnabled`, isScaScanEnabled: `${constants.extensionName}.isSCAScanEnabled`, + filterCriticalToggle: `${constants.extensionName}.filterCritical_toggle`, + filterCriticalUntoggle: `${constants.extensionName}.filterCritical_untoggle`, + filterCritical: `${constants.extensionName}.filterCritical`, + filterHighToggle: `${constants.extensionName}.filterHigh_toggle`, filterHighUntoggle: `${constants.extensionName}.filterHigh_untoggle`, filterHigh: `${constants.extensionName}.filterHigh`, diff --git a/src/utils/common/constants.ts b/src/utils/common/constants.ts index 1d5041ea..5dd797a0 100644 --- a/src/utils/common/constants.ts +++ b/src/utils/common/constants.ts @@ -4,6 +4,7 @@ export const constants = { scanIdKey: "ast-results-scan-id", scanCreateIdKey: "ast-results-scan-create-id", scanCreatePrepKey: "ast-results-scan-prep-id", + criticalFilter: "ast-results-critical", highFilter: "ast-results-high", mediumFilter: "ast-results-medium", lowFilter: "ast-results-low", @@ -47,6 +48,7 @@ export const constants = { resultsFileName: "ast-results", resultsFileExtension: "json", status: [ + { class: "select-critical", value: "CRITICAL" }, { class: "select-high", value: "HIGH" }, { class: "select-medium", value: "MEDIUM" }, { class: "select-low", value: "LOW" }, @@ -152,6 +154,7 @@ export enum GroupBy { } export enum SeverityLevel { + critical = "CRITICAL", high = "HIGH", medium = "MEDIUM", low = "LOW", diff --git a/src/utils/triage.ts b/src/utils/triage.ts index 9535260e..f5eb48de 100644 --- a/src/utils/triage.ts +++ b/src/utils/triage.ts @@ -65,7 +65,7 @@ export async function triageSubmit( } // Case there is feedback on the severity if (data.severitySelection.length > 0) { - logs.log("INFO", messages.triageUpdateSeverity(data.severitySelection)); + logs.info(messages.triageUpdateSeverity(data.severitySelection)); // Update severity of the result result.setSeverity(data.severitySelection); // Update webview title @@ -77,7 +77,7 @@ export async function triageSubmit( // Case there is feedback on the state if (data.stateSelection.length > 0) { - logs.log("INFO", messages.triageUpdateState(data.stateSelection)); + logs.info(messages.triageUpdateState(data.stateSelection)); // Update severity of the result result.setState(data.stateSelection.replaceAll(" ", "_").toUpperCase()); } diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 7c0f54c5..16948e96 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -148,7 +148,7 @@ export function readResultsFromFile(resultJsonPath: string, scan: string): CxRes } export function orderResults(list: CxResult[]): CxResult[] { - const order = ["HIGH", "MEDIUM", "LOW", "INFO"]; + const order = ["CRITICAL", "HIGH", "MEDIUM", "LOW", "INFO"]; return list.sort( (a, b) => order.indexOf(a.severity) - order.indexOf(b.severity) ); diff --git a/src/views/resultsProviders.ts b/src/views/resultsProviders.ts index e803eab5..bc3b1661 100644 --- a/src/views/resultsProviders.ts +++ b/src/views/resultsProviders.ts @@ -60,6 +60,7 @@ export class ResultsProvider implements vscode.TreeDataProvider { scan: string | undefined, diagnosticCollection: vscode.DiagnosticCollection, issueLevel: string[] = [ + SeverityLevel.critical, SeverityLevel.high, SeverityLevel.medium, SeverityLevel.low, From 756fa2762b23fa79f4ab77b0769a2d3d12a0c3d5 Mon Sep 17 00:00:00 2001 From: tiagobcx Date: Thu, 2 Nov 2023 14:51:37 +0000 Subject: [PATCH 02/11] fixing tests --- src/test/0.welcome.test.ts | 1 + src/test/1.settings.test.ts | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/0.welcome.test.ts b/src/test/0.welcome.test.ts index 921fd05b..5073dd23 100644 --- a/src/test/0.welcome.test.ts +++ b/src/test/0.welcome.test.ts @@ -9,6 +9,7 @@ describe("Welcome view test", () => { before(async function () { this.timeout(8000); bench = new Workbench(); + await initialize(); }); after(async () => { diff --git a/src/test/1.settings.test.ts b/src/test/1.settings.test.ts index 11c6f040..480f6668 100644 --- a/src/test/1.settings.test.ts +++ b/src/test/1.settings.test.ts @@ -35,7 +35,8 @@ describe("Extension settings tests", () => { const settings = (await settingsEditor.findSetting( CX_API_KEY_SETTINGS )) as LinkSetting; - expect(settings).to.be.undefined; + const apiKey = await settings.getValue(); + expect(apiKey).to.be.empty; }); it("should set the settings and check if values are populated", async function () { From c1351c2e4b3987222bf5dd4b26bed632bf7d570b Mon Sep 17 00:00:00 2001 From: tiagobcx Date: Thu, 2 Nov 2023 17:21:52 +0000 Subject: [PATCH 03/11] fixing triage refresh --- src/utils/common/constants.ts | 5 ++++- src/utils/triage.ts | 9 ++++++--- src/views/resultsView/astResultsProvider.ts | 21 +++++++++++++++------ 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/utils/common/constants.ts b/src/utils/common/constants.ts index 5dd797a0..29a70087 100644 --- a/src/utils/common/constants.ts +++ b/src/utils/common/constants.ts @@ -137,7 +137,10 @@ export const constants = { gptEngineKey: "model", // Documentation & Feedback feedback: "Send us enhancement request or report a bug", - documentation: "Documentation" + documentation: "Documentation", + + // TRIAGE + triageUpdate: "ast-result-triage" }; export enum GroupBy { diff --git a/src/utils/triage.ts b/src/utils/triage.ts index f5eb48de..cfd0ef4d 100644 --- a/src/utils/triage.ts +++ b/src/utils/triage.ts @@ -3,7 +3,7 @@ import * as fs from "fs"; import { AstResult } from "../models/results"; import { getResultsFilePath } from "./utils"; import { cx } from "../cx"; -import { getFromState } from "./common/globalState"; +import { getFromState, updateState } from "./common/globalState"; import { constants } from "./common/constants"; import { Logs } from "../models/logs"; import { AstDetailsDetached } from "../views/resultsView/astDetailsView"; @@ -29,7 +29,9 @@ export async function updateResults( resultsProvider.loadedResults.forEach((element: AstResult, index: number) => { // Update the result in the array if (element.data.resultHash === resultHash || element.id === resultHash) { - resultsProvider.loadedResults[index] = result; + resultsProvider.loadedResults[index].severity = result.severity; + resultsProvider.loadedResults[index].state = result.state; + resultsProvider.loadedResults[index].status = result.status; return; } }); @@ -100,7 +102,8 @@ export async function triageSubmit( // Change the results locally try { await updateResults(result, context, data.comment, resultsProvider); - vscode.commands.executeCommand(commands.refreshTree); + updateState(context, constants.triageUpdate, { id: true, name: constants.triageUpdate }); + await vscode.commands.executeCommand(commands.refreshTree); if (result.type === "sast" || result.type === "kics") { await getChanges(logs, context, result, detailsPanel); } diff --git a/src/views/resultsView/astResultsProvider.ts b/src/views/resultsView/astResultsProvider.ts index f4d4d25c..284e2ace 100644 --- a/src/views/resultsView/astResultsProvider.ts +++ b/src/views/resultsView/astResultsProvider.ts @@ -76,16 +76,25 @@ export class AstResultsProvider extends ResultsProvider { this.diagnosticCollection.clear(); // createBaseItems let treeItems = this.createRootItems(); - // get para getFromState + // get scanID from state this.scan = getFromState(this.context, constants.scanIdKey)?.id; - // in case we scanId, it is needed to load them from the json file - if (this.scan) { - this.loadedResults = readResultsFromFile(resultJsonPath, this.scan); + const fromTriage = getFromState(this.context, constants.triageUpdate)?.id; + // Case we come from triage we want to use the loaded results wich were modified in triage + if (fromTriage === undefined || !fromTriage) { + // in case we scanId, it is needed to load them from the json file + if (this.scan) { + this.loadedResults = readResultsFromFile(resultJsonPath, this.scan); + } + // otherwise the results must be cleared + else { + this.loadedResults = undefined; + } } - // otherwise the results must be cleared + // Case we come from triage we must update the state to load results from the correct place else { - this.loadedResults = undefined; + updateState(this.context, "ast-result-triage", { id: false, name: "ast-result-triage" }); } + // if there are results loaded, the tree needs to be recreated if (this.loadedResults !== undefined) { treeItems = treeItems.concat(this.createSummaryItem(this.loadedResults)); From 520754f9ee33bb537eca8f087351f2c88fb0afbe Mon Sep 17 00:00:00 2001 From: tiagobcx Date: Tue, 7 Nov 2023 16:02:47 +0000 Subject: [PATCH 04/11] smal fix --- src/utils/common/messages.ts | 2 +- src/utils/triage.ts | 58 ++++++++++----------- src/views/resultsView/astResultsProvider.ts | 2 +- 3 files changed, 29 insertions(+), 33 deletions(-) diff --git a/src/utils/common/messages.ts b/src/utils/common/messages.ts index 68d902d0..9ba70397 100644 --- a/src/utils/common/messages.ts +++ b/src/utils/common/messages.ts @@ -67,7 +67,7 @@ export const messages = { loadingResults: "Loading results", triageNotAvailableSca: "Triage not available for SCA.", triageSubmitedSuccess: "Feedback submited successfully! Results refreshed.", - triageError: (error) => `Triage Error | ${error}`, + triageError: (error) => `Triage ${error}`, triageNoChange: "Make a change before submiting", triageUpdateState: (state) => `Updating state to ${state}`, triageUpdateSeverity: (severity) => `Updating severity to ${severity}`, diff --git a/src/utils/triage.ts b/src/utils/triage.ts index cfd0ef4d..a0e6dfe3 100644 --- a/src/utils/triage.ts +++ b/src/utils/triage.ts @@ -24,31 +24,27 @@ export async function updateResults( throw new Error(messages.fileNotFound); } - try { - const resultHash = result.getResultHash(); - resultsProvider.loadedResults.forEach((element: AstResult, index: number) => { - // Update the result in the array - if (element.data.resultHash === resultHash || element.id === resultHash) { - resultsProvider.loadedResults[index].severity = result.severity; - resultsProvider.loadedResults[index].state = result.state; - resultsProvider.loadedResults[index].status = result.status; - return; - } - }); - - // Update - const projectId = getFromState(context, constants.projectIdKey).id; - await cx.triageUpdate( - projectId, - result.similarityId, - result.type, - result.state, - comment, - result.severity - ); - } catch (error) { - throw new Error(error); - } + // Update on cxOne + const projectId = getFromState(context, constants.projectIdKey).id; + await cx.triageUpdate( + projectId, + result.similarityId, + result.type, + result.state, + comment, + result.severity + ); + // Update local results + const resultHash = result.getResultHash(); + resultsProvider.loadedResults.forEach((element: AstResult, index: number) => { + // Update the result in the array + if (element.data.resultHash === resultHash || element.id === resultHash) { + resultsProvider.loadedResults[index].severity = result.severity; + resultsProvider.loadedResults[index].state = result.state; + resultsProvider.loadedResults[index].status = result.status; + return; + } + }); } export async function triageSubmit( @@ -93,12 +89,6 @@ export async function triageSubmit( vscode.window.showErrorMessage(messages.triageNoChange); return; } - - detailsDetachedView?.setResult(result); - detailsDetachedView.setLoad(false); - // Update webview html - detailsPanel.webview.html = - await detailsDetachedView.getDetailsWebviewContent(detailsPanel?.webview); // Change the results locally try { await updateResults(result, context, data.comment, resultsProvider); @@ -115,7 +105,13 @@ export async function triageSubmit( ); } catch (error) { vscode.window.showErrorMessage(messages.triageError(error)); + return; } + detailsDetachedView?.setResult(result); + detailsDetachedView.setLoad(false); + // Update webview html + detailsPanel.webview.html = + await detailsDetachedView.getDetailsWebviewContent(detailsPanel?.webview); } export async function getChanges( diff --git a/src/views/resultsView/astResultsProvider.ts b/src/views/resultsView/astResultsProvider.ts index 284e2ace..d04c2660 100644 --- a/src/views/resultsView/astResultsProvider.ts +++ b/src/views/resultsView/astResultsProvider.ts @@ -92,7 +92,7 @@ export class AstResultsProvider extends ResultsProvider { } // Case we come from triage we must update the state to load results from the correct place else { - updateState(this.context, "ast-result-triage", { id: false, name: "ast-result-triage" }); + updateState(this.context, constants.triageUpdate, { id: false, name: constants.triageUpdate }); } // if there are results loaded, the tree needs to be recreated From 1d3cb9dbb571571e3121547246b62411fdc53f0d Mon Sep 17 00:00:00 2001 From: Pedro Lopes Date: Fri, 9 Aug 2024 22:42:53 +0100 Subject: [PATCH 05/11] fix tests --- src/utils/triage.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/utils/triage.ts b/src/utils/triage.ts index a0e6dfe3..fdeb6312 100644 --- a/src/utils/triage.ts +++ b/src/utils/triage.ts @@ -92,7 +92,11 @@ export async function triageSubmit( // Change the results locally try { await updateResults(result, context, data.comment, resultsProvider); - updateState(context, constants.triageUpdate, { id: true, name: constants.triageUpdate }); + updateState(context, constants.triageUpdate, { + id: true, name: constants.triageUpdate, + scanDatetime: "", + displayScanId: "" + }); await vscode.commands.executeCommand(commands.refreshTree); if (result.type === "sast" || result.type === "kics") { await getChanges(logs, context, result, detailsPanel); From 9c8608cdb8d079c646cc634d12fc8b3a79a685f2 Mon Sep 17 00:00:00 2001 From: Pedro Lopes Date: Fri, 9 Aug 2024 22:45:43 +0100 Subject: [PATCH 06/11] Update AstResultsProvider to include scanDatetime and displayScanId --- src/views/resultsView/astResultsProvider.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/views/resultsView/astResultsProvider.ts b/src/views/resultsView/astResultsProvider.ts index 241fb2b7..e0ecee21 100644 --- a/src/views/resultsView/astResultsProvider.ts +++ b/src/views/resultsView/astResultsProvider.ts @@ -92,7 +92,11 @@ export class AstResultsProvider extends ResultsProvider { } // Case we come from triage we must update the state to load results from the correct place else { - updateState(this.context, constants.triageUpdate, { id: false, name: constants.triageUpdate }); + updateState(this.context, constants.triageUpdate, { + id: false, name: constants.triageUpdate, + scanDatetime: "", + displayScanId: "" + }); } // if there are results loaded, the tree needs to be recreated @@ -117,7 +121,7 @@ export class AstResultsProvider extends ResultsProvider { if (treeItem.children.length === 0) { treeItem.children.push(new TreeItem(constants.scaNoVulnerabilities, undefined)); } - + treeItem.collapsibleState = vscode.TreeItemCollapsibleState.Expanded; treeItems = treeItems.concat(treeItem); } From 91389885b3a695f57a5d69a0adbea4f78e335c8b Mon Sep 17 00:00:00 2001 From: hmmachadocx Date: Fri, 23 Aug 2024 16:52:54 +0100 Subject: [PATCH 07/11] fix missing comma in constants --- src/utils/common/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/common/constants.ts b/src/utils/common/constants.ts index ea4c7eac..6eb38615 100644 --- a/src/utils/common/constants.ts +++ b/src/utils/common/constants.ts @@ -143,7 +143,7 @@ export const constants = { documentation: "Documentation", // TRIAGE - triageUpdate: "ast-result-triage" + triageUpdate: "ast-result-triage", // Vorpal engine errorInstallation: "Failed to run vorpal engine", From 5acaae8469f567379226fe12ec2970f5436a4553 Mon Sep 17 00:00:00 2001 From: hmmachadocx Date: Fri, 23 Aug 2024 17:28:46 +0100 Subject: [PATCH 08/11] Fix order in severities icons --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 99c93f1d..8d1d6672 100644 --- a/package.json +++ b/package.json @@ -767,7 +767,7 @@ }, { "submenu": "ast-results.filterBy", - "group": "navigation@5", + "group": "navigation@6", "when": "view == astResults" } ] From 7b9c4fbae8f623c4567f7192b00b76c50ca1c73d Mon Sep 17 00:00:00 2001 From: tiagobcx Date: Mon, 26 Aug 2024 16:11:56 +0100 Subject: [PATCH 09/11] fixing settings test --- src/test/1.settings.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/1.settings.test.ts b/src/test/1.settings.test.ts index 4ac90610..be5e5362 100644 --- a/src/test/1.settings.test.ts +++ b/src/test/1.settings.test.ts @@ -41,8 +41,7 @@ describe("Extension settings tests", () => { const settings = (await settingsEditor.findSetting( "fake setting" )) as LinkSetting; - const apiKey = await settings.getValue(); - expect(apiKey).to.be.empty; + expect(settings).to.be.undefined; }); it("should set the settings and check if values are populated", async function () { From b92c0a11f25a3510b3383c95d04f7a1ff939fbf2 Mon Sep 17 00:00:00 2001 From: tiagobcx Date: Mon, 26 Aug 2024 16:58:33 +0100 Subject: [PATCH 10/11] adding tests for critical severity --- src/cx/cxMock.ts | 143 ++++++++++++++++++++++++++++--- src/test/5.customActions.test.ts | 2 +- 2 files changed, 130 insertions(+), 15 deletions(-) diff --git a/src/cx/cxMock.ts b/src/cx/cxMock.ts index f480a2e7..fb9555f6 100644 --- a/src/cx/cxMock.ts +++ b/src/cx/cxMock.ts @@ -12,7 +12,7 @@ import { EMPTY_RESULTS_SCAN_ID } from "../test/utils/envs"; export class CxMock implements CxPlatform { - + // eslint-disable-next-line @typescript-eslint/no-explicit-any async scaScanCreate(): Promise { return [ @@ -96,14 +96,14 @@ export class CxMock implements CxPlatform { async getResults(scanId: string) { let results; - - if (scanId === "2"||scanId === EMPTY_RESULTS_SCAN_ID) { + + if (scanId === "2" || scanId === EMPTY_RESULTS_SCAN_ID) { results = { "results": [] }; } - else{ - results = { + else { + results = { "results": [ { "type": "kics", @@ -279,6 +279,120 @@ export class CxMock implements CxPlatform { ] } }, + { + "type": "sast", + "label": "sast", + "id": "255181", + "similarityId": "-1792929011", + "status": "NEW", + "state": "TO_VERIFY", + "severity": "CRITICAL", + "created": "2022-09-02T10:45:54Z", + "firstFoundAt": "2022-08-26T10:28:57Z", + "foundAt": "2022-09-02T10:45:54Z", + "firstScanId": "cb834dcd-aaec-4e1f-a099-089d5fbe503e", + "description": "The method $PageLoad embeds untrusted data in generated output with echo, at line 11 of /insecure.php. This untrusted data is embedded into the output without proper sanitization or encoding, enabling an attacker to inject malicious code into the generated web-page.\n\nThe attacker would be able to alter the returned web page by simply providing modified data in the user input _POST, which is read by the $PageLoad method at line 10 of /insecure.php. This input then flows through the code straight to the output web page, without sanitization. \r\n\r\nThis can enable a Reflected Cross-Site Scripting (XSS) attack.\n\n", + "descriptionHTML": "\u003cp\u003eThe method $PageLoad embeds untrusted data in generated output with echo, at line 11 of /insecure.php. This untrusted data is embedded into the output without proper sanitization or encoding, enabling an attacker to inject malicious code into the generated web-page.\u003c/p\u003e\n\n\u003cp\u003eThe attacker would be able to alter the returned web page by simply providing modified data in the user input _POST, which is read by the $PageLoad method at line 10 of /insecure.php. This input then flows through the code straight to the output web page, without sanitization. \r\n\r\nThis can enable a Reflected Cross-Site Scripting (XSS) attack.\u003c/p\u003e\n", + "data": { + // eslint-disable-next-line @typescript-eslint/no-loss-of-precision + "queryId": 5157925289005576664, + "queryName": "Reflected_XSS_All_Clients", + "group": "PHP_High_Risk", + "resultHash": "ZGJRP6tLG66K4GwKarVTE8GDL/M=", + "languageName": "PHP", + "nodes": [ + { + "id": "6BkcV9Pylb1Kk14z/xZHkWcP9hk=", + "line": 10, + "name": "_POST", + "column": 8, + "length": 6, + "method": "$PageLoad", + "nodeID": 164, + "domType": "UnknownReference", + "fileName": "/insecure.php", + "fullName": "$NS_insecure_a3ce4a23.$Cls_insecure_a3ce4a23._POST", + "typeName": "CxDefaultObject", + "methodLine": 1, + "definitions": "1" + }, + { + "id": "o8XLDcRzoLEzVVdI3yyHchg/JH0=", + "line": 10, + "name": "var", + "column": 1, + "length": 4, + "method": "$PageLoad", + "nodeID": 168, + "domType": "UnknownReference", + "fileName": "/insecure.php", + "fullName": "$NS_insecure_a3ce4a23.$Cls_insecure_a3ce4a23.var", + "typeName": "CxDefaultObject", + "methodLine": 1, + "definitions": "1" + }, + { + "id": "yis1SnpLBtDSuxZBPhw76TaDjY4=", + "line": 11, + "name": "var", + "column": 12, + "length": 4, + "method": "$PageLoad", + "nodeID": 184, + "domType": "UnknownReference", + "fileName": "/insecure.php", + "fullName": "$NS_insecure_a3ce4a23.$Cls_insecure_a3ce4a23.var", + "typeName": "CxDefaultObject", + "methodLine": 1, + "definitions": "1" + }, + { + "id": "kZuPO2VpUX+yVNtYvSP3FVHVJBQ=", + "line": 11, + "name": "$_DoubleQuotedString", + "column": 0, + "length": 20, + "method": "$PageLoad", + "nodeID": 177, + "domType": "MethodInvokeExpr", + "fileName": "/insecure.php", + "fullName": "$_DoubleQuotedString", + "typeName": "$_DoubleQuotedString", + "methodLine": 1, + "definitions": "0" + }, + { + "id": "fO7BgAMUgzMTXcmTFe9v8TGpYPg=", + "line": 11, + "name": "echo", + "column": 1, + "length": 4, + "method": "$PageLoad", + "nodeID": 171, + "domType": "MethodInvokeExpr", + "fileName": "/insecure.php", + "fullName": "echo", + "typeName": "echo", + "methodLine": 1, + "definitions": "0" + } + ] + }, + "comments": {}, + "vulnerabilityDetails": { + "cweId": 79, + "cvss": {}, + "compliances": [ + "PCI DSS v3.2.1", + "ASD STIG 4.10", + "FISMA 2014", + "NIST SP 800-53", + "OWASP Top 10 2013", + "OWASP Top 10 2017", + "OWASP Top 10 2021" + ] + } + }, { "type": "sca", "scaType": "Vulnerability", @@ -317,9 +431,9 @@ export class CxMock implements CxPlatform { } async getScan(scanId: string): Promise { - - if (scanId===(EMPTY_RESULTS_SCAN_ID)) { - return{ + + if (scanId === (EMPTY_RESULTS_SCAN_ID)) { + return { tags: { }, groups: undefined, @@ -331,7 +445,8 @@ export class CxMock implements CxPlatform { origin: "grpc-java-netty 1.35.0", initiator: "tester", branch: "main", - }} + }; + } return { tags: { }, @@ -348,9 +463,9 @@ export class CxMock implements CxPlatform { } async getProject(projectId: string): Promise { - - if(projectId==="EmptyResultsProjectId"){ - return{ + + if (projectId === "EmptyResultsProjectId") { + return { tags: { }, groups: [ @@ -359,7 +474,7 @@ export class CxMock implements CxPlatform { name: "EmptyResultsProjectName", createdAt: "2023-04-19T09:07:36.846145Z", updatedAt: "2023-04-19T09:07:36.846145Z", - } + }; } return { tags: { @@ -555,7 +670,7 @@ export class CxMock implements CxPlatform { await this.sleep(1000); return [{ conversationId: '0', response: ["Mock message response from gpt"] }]; } - + sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } diff --git a/src/test/5.customActions.test.ts b/src/test/5.customActions.test.ts index e6319a76..03050bab 100644 --- a/src/test/5.customActions.test.ts +++ b/src/test/5.customActions.test.ts @@ -29,7 +29,7 @@ describe("filter and groups actions tests", () => { SCAN_ID ); await input.confirm(); - const commands = [{ command: CX_FILTER_INFO, text: "INFO" }, { command: CX_FILTER_LOW, text: "LOW" }, { command: CX_FILTER_MEDIUM, text: "MEDIUM" }, { command: CX_FILTER_HIGH, text: "HIGH" }]; + const commands = [{ command: CX_FILTER_INFO, text: "INFO" }, { command: CX_FILTER_LOW, text: "LOW" }, { command: CX_FILTER_MEDIUM, text: "MEDIUM" }, { command: CX_FILTER_HIGH, text: "HIGH" }, { command: CX_FILTER_HIGH, text: "CRITICAL" }]; for (var index in commands) { await bench.executeCommand(commands[index].command); treeScans = await initialize(); From 3f6356603f7801b04b3a1f4eb88c93f21cb1b3e5 Mon Sep 17 00:00:00 2001 From: tiagobcx Date: Thu, 29 Aug 2024 11:37:00 +0100 Subject: [PATCH 11/11] applying code review suggestions --- src/models/results.ts | 30 +++++++++++++++--------------- src/utils/common/constants.ts | 10 ++++++++-- src/utils/utils.ts | 16 ++++++++-------- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/src/models/results.ts b/src/models/results.ts index 6c4e2b22..c9887f2a 100644 --- a/src/models/results.ts +++ b/src/models/results.ts @@ -115,15 +115,15 @@ export class AstResult extends CxResult { getIcon() { switch (this.severity) { - case "CRITICAL": + case constants.criticalSeverity: return path.join("media", "icons", "critical_untoggle.svg"); - case "HIGH": + case constants.highSeverity: return path.join("media", "icons", "high_untoggle.svg"); - case "MEDIUM": + case constants.mediumSeverity: return path.join("media", "icons", "medium_untoggle.svg"); - case "INFO": + case constants.infoSeverity: return path.join("media", "icons", "info_untoggle.svg"); - case "LOW": + case constants.lowSeverity: return path.join("media", "icons", "low_untoggle.svg"); } return ""; @@ -178,15 +178,15 @@ export class AstResult extends CxResult { getSeverityCode() { switch (this.severity) { - case "CRITICAL": + case constants.criticalSeverity: return vscode.DiagnosticSeverity.Error; - case "HIGH": + case constants.highSeverity: return vscode.DiagnosticSeverity.Error; - case "MEDIUM": + case constants.mediumSeverity: return vscode.DiagnosticSeverity.Warning; - case "INFO": + case constants.infoSeverity: return vscode.DiagnosticSeverity.Information; - case "LOW": + case constants.infoSeverity: return vscode.DiagnosticSeverity.Information; } return vscode.DiagnosticSeverity.Information; @@ -194,15 +194,15 @@ export class AstResult extends CxResult { getSeverity() { switch (this.severity) { - case "CRITICAL": + case constants.criticalSeverity: return SeverityLevel.critical; - case "HIGH": + case constants.highSeverity: return SeverityLevel.high; - case "MEDIUM": + case constants.mediumSeverity: return SeverityLevel.medium; - case "INFO": + case constants.infoSeverity: return SeverityLevel.info; - case "LOW": + case constants.lowSeverity: return SeverityLevel.low; } return SeverityLevel.empty; diff --git a/src/utils/common/constants.ts b/src/utils/common/constants.ts index 6eb38615..3e4ee7f2 100644 --- a/src/utils/common/constants.ts +++ b/src/utils/common/constants.ts @@ -151,8 +151,14 @@ export const constants = { vorpalStart: "Vorpal engine started", vorpalDisabled: "Vorpal Real-time Scanning is disabled now.", vorpalEngineName: "Vorpal", - ActivateVorpalAutoScanning:"Activate Vorpal Real-time Scanning", - CheckmarxVorpal:"CheckmarxVorpal", + ActivateVorpalAutoScanning: "Activate Vorpal Real-time Scanning", + CheckmarxVorpal: "CheckmarxVorpal", + + criticalSeverity: "CRITICAL", + highSeverity: "HIGH", + mediumSeverity: "MEDIUM", + lowSeverity: "LOW", + infoSeverity: "INFO", }; export enum GroupBy { diff --git a/src/utils/utils.ts b/src/utils/utils.ts index c5f5caef..5702b059 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -113,19 +113,19 @@ export function getFormattedDateTime(createdAt: string) { } export function getFormattedId(label: CxScan, scanList: CxScan[]) { - if (scanList === null || scanList === undefined || scanList.length === 0){ + if (scanList === null || scanList === undefined || scanList.length === 0) { return ""; - } + } return label === scanList[0] - ? label.id + " (latest)" - : label.id; + ? label.id + " (latest)" + : label.id; } export function formatLabel(label: CxScan, scanList: CxScan[]) { return label === scanList[0] - ? getScanLabel(label.createdAt, label.id) + " (latest)" - : getScanLabel(label.createdAt, label.id); + ? getScanLabel(label.createdAt, label.id) + " (latest)" + : getScanLabel(label.createdAt, label.id); } export async function enableButton(button: string) { @@ -162,7 +162,7 @@ export function readResultsFromFile(resultJsonPath: string, scan: string): CxRes .readFileSync(resultJsonPath, "utf-8") .replace(/:([0-9]{15,}),/g, ':"$1",') ); - if(jsonResults.results){ + if (jsonResults.results) { results = orderResults(jsonResults.results); } else { @@ -173,7 +173,7 @@ export function readResultsFromFile(resultJsonPath: string, scan: string): CxRes } export function orderResults(list: CxResult[]): CxResult[] { - const order = ["CRITICAL", "HIGH", "MEDIUM", "LOW", "INFO"]; + const order = [constants.criticalSeverity, constants.highSeverity, constants.mediumSeverity, constants.lowSeverity, constants.infoSeverity]; return list.sort( (a, b) => order.indexOf(a.severity) - order.indexOf(b.severity) );