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)
);