From 8c42f0676a1b9a6de15771f70b8e2dc54e2bf992 Mon Sep 17 00:00:00 2001 From: cx-ben-alvo <144705560+cx-ben-alvo@users.noreply.github.com> Date: Sun, 20 Jul 2025 11:55:12 +0300 Subject: [PATCH 01/13] Add containers realtime scan functionality and related constants --- .../containersRealtime/CxContainerRealtime.ts | 65 +++++++++++++++++++ .../CxRealtimeEngineStatus.ts | 9 +++ src/main/wrapper/CxConstants.ts | 2 + src/main/wrapper/CxWrapper.ts | 7 ++ src/main/wrapper/ExecutionService.ts | 5 ++ src/tests/ScanTest.test.ts | 9 +++ 6 files changed, 97 insertions(+) create mode 100644 src/main/containersRealtime/CxContainerRealtime.ts create mode 100644 src/main/containersRealtime/CxRealtimeEngineStatus.ts diff --git a/src/main/containersRealtime/CxContainerRealtime.ts b/src/main/containersRealtime/CxContainerRealtime.ts new file mode 100644 index 00000000..477b11b3 --- /dev/null +++ b/src/main/containersRealtime/CxContainerRealtime.ts @@ -0,0 +1,65 @@ +import { CxRealtimeEngineStatus } from './CxRealtimeEngineStatus'; + +export interface Location { + line: number; + startIndex: number; + endIndex: number; +} + +export default class CxContainerRealtimeResult { + imageName: string; + imageTag: string; + filepath: string; + locations: Location[]; + status: CxRealtimeEngineStatus; + vulnerabilities: { cve: string, severity: string }[]; + + static parseResult(resultObject: any): CxContainerRealtimeResult[] { + const images = resultObject.Images; + let imageResults: CxContainerRealtimeResult[] = []; + if (images instanceof Array) { + imageResults = images.map((member: any) => { + const imageResult = new CxContainerRealtimeResult(); + imageResult.imageName = member.ImageName; + imageResult.imageTag = member.ImageTag; + imageResult.filepath = member.FilePath; + imageResult.locations = Array.isArray(member.Locations) + ? member.Locations.map((loc: any) => ({ + line: loc.Line, + startIndex: loc.StartIndex, + endIndex: loc.EndIndex + })) + : []; + imageResult.status = member.Status as CxRealtimeEngineStatus; + imageResult.vulnerabilities = Array.isArray(member.Vulnerabilities) + ? member.Vulnerabilities.map((vul: any) => ({ + cve: vul.CVE, + severity: vul.Severity + })) + : []; + return imageResult; + }); + } else { + const imageResult = new CxContainerRealtimeResult(); + imageResult.imageName = images.PackageManager; + imageResult.imageTag = images.PackageName; + imageResult.filepath = images.FilePath; + imageResult.locations = Array.isArray(images.Locations) + ? images.Locations.map((loc: any) => ({ + line: loc.Line, + startIndex: loc.StartIndex, + endIndex: loc.EndIndex + })) + : []; + imageResult.status = images.Status as CxRealtimeEngineStatus; + imageResult.vulnerabilities = Array.isArray(images.Vulnerabilities) + ? images.Vulnerabilities.map((vul: any) => ({ + cve: vul.CVE, + severity: vul.Severity + })) + : []; + imageResults.push(imageResult); + } + return imageResults; + } +} diff --git a/src/main/containersRealtime/CxRealtimeEngineStatus.ts b/src/main/containersRealtime/CxRealtimeEngineStatus.ts new file mode 100644 index 00000000..dd66d043 --- /dev/null +++ b/src/main/containersRealtime/CxRealtimeEngineStatus.ts @@ -0,0 +1,9 @@ +export enum CxRealtimeEngineStatus { + malicious = "Malicious", + ok = "OK", + unknown = "Unknown", + critical = "Critical", + high = "High", + medium = "Medium", + low = "Low" +} diff --git a/src/main/wrapper/CxConstants.ts b/src/main/wrapper/CxConstants.ts index 9174ea4f..8bbaf5c8 100644 --- a/src/main/wrapper/CxConstants.ts +++ b/src/main/wrapper/CxConstants.ts @@ -73,6 +73,7 @@ export enum CxConstants { SOURCE_FILE = "--file-source", ASCA_UPDATE_VERSION = "--asca-latest-version", CMD_OSS = "oss-realtime", + CMD_CONTAINERS_REALTIME = "containers-realtime", CMD_SECRETS = "secrets-realtime", PROJECT_ID = "--project-id", SIMILARITY_ID = "--similarity-id", @@ -90,6 +91,7 @@ export enum CxConstants { SCAN_TYPE = "CxScan", SCAN_ASCA = "CxAsca", SCAN_OSS = "CxOss", + SCAN_CONTAINERS_REALTIME = "CxContainersRealtime", SCAN_SECRETS = "CxSecrets", PROJECT_TYPE = "CxProject", PREDICATE_TYPE = "CxPredicate", diff --git a/src/main/wrapper/CxWrapper.ts b/src/main/wrapper/CxWrapper.ts index 2ab25729..d751a4bb 100644 --- a/src/main/wrapper/CxWrapper.ts +++ b/src/main/wrapper/CxWrapper.ts @@ -156,6 +156,13 @@ export class CxWrapper { return await exec.executeCommands(this.config.pathToExecutable, commands, CxConstants.SCAN_OSS); } + async containersRealtimeScanResults(sourceFile: string): Promise { + const commands: string[] = [CxConstants.CMD_SCAN, CxConstants.CMD_CONTAINERS_REALTIME, CxConstants.SOURCE, sourceFile]; + commands.push(...this.initializeCommands(false)); + const exec = new ExecutionService(); + return await exec.executeCommands(this.config.pathToExecutable, commands, CxConstants.SCAN_CONTAINERS_REALTIME); + } + async secretsScanResults(sourceFile: string): Promise { const commands: string[] = [CxConstants.CMD_SCAN, CxConstants.CMD_SECRETS, CxConstants.SOURCE, sourceFile]; commands.push(...this.initializeCommands(false)); diff --git a/src/main/wrapper/ExecutionService.ts b/src/main/wrapper/ExecutionService.ts index 9c4182a5..02df20e6 100644 --- a/src/main/wrapper/ExecutionService.ts +++ b/src/main/wrapper/ExecutionService.ts @@ -25,6 +25,7 @@ import CxMask from "../mask/CxMask"; import CxAsca from "../asca/CxAsca"; import CxOssResult from "../oss/CxOss"; import CxSecretsResult from "../secrets/CxSecrets"; +import CxContainerRealtimeResult from "../containersRealtime/CxContainerRealtime"; let skipValue = false; const fileSourceFlag = "--file-source" @@ -211,6 +212,10 @@ export class ExecutionService { const oss = CxOssResult.parseResult(resultObject); cxCommandOutput.payload = [oss]; break; + case CxConstants.SCAN_CONTAINERS_REALTIME: + const images = CxContainerRealtimeResult.parseResult(resultObject); + cxCommandOutput.payload = [images]; + break; case CxConstants.SCAN_SECRETS: const secrets = CxSecretsResult.parseResult(resultObject); cxCommandOutput.payload = [secrets]; diff --git a/src/tests/ScanTest.test.ts b/src/tests/ScanTest.test.ts index 781b0f12..e95da13e 100644 --- a/src/tests/ScanTest.test.ts +++ b/src/tests/ScanTest.test.ts @@ -190,4 +190,13 @@ describe("ScanCreate cases", () => { expect(cxCommandOutput.exitCode).toBe(0); }); + it('ScanContainersRealtime Successful case', async () => { + const wrapper = new CxWrapper(cxScanConfig); + const cxCommandOutput: CxCommandOutput = await wrapper.containersRealtimeScanResults("src/tests/data/Dockerfile"); + console.log("Json object from scanContainersRealtime successful case: " + JSON.stringify(cxCommandOutput)); + expect(cxCommandOutput.payload).toBeDefined(); + expect(cxCommandOutput.exitCode).toBe(0); + }); + + }); From 9dbb1c700202e8c190873624b642af94a7c110fd Mon Sep 17 00:00:00 2001 From: cx-ben-alvo <144705560+cx-ben-alvo@users.noreply.github.com> Date: Sun, 20 Jul 2025 12:02:28 +0300 Subject: [PATCH 02/13] Skip successful case test for containers realtime scan --- src/tests/ScanTest.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/ScanTest.test.ts b/src/tests/ScanTest.test.ts index e95da13e..e245dcc8 100644 --- a/src/tests/ScanTest.test.ts +++ b/src/tests/ScanTest.test.ts @@ -190,7 +190,7 @@ describe("ScanCreate cases", () => { expect(cxCommandOutput.exitCode).toBe(0); }); - it('ScanContainersRealtime Successful case', async () => { + it.skip('ScanContainersRealtime Successful case', async () => { const wrapper = new CxWrapper(cxScanConfig); const cxCommandOutput: CxCommandOutput = await wrapper.containersRealtimeScanResults("src/tests/data/Dockerfile"); console.log("Json object from scanContainersRealtime successful case: " + JSON.stringify(cxCommandOutput)); From 1a9156cdb72d7cb4bf6b91249937a218ec898308 Mon Sep 17 00:00:00 2001 From: Itay Paz <143506741+cx-itay-paz@users.noreply.github.com> Date: Tue, 22 Jul 2025 16:06:48 +0300 Subject: [PATCH 03/13] Support Ignore file path for Oss real time and Secrets real time (#859) * add support ignore file oss * revert secretsscanresults * change realse tag * Track Checkmarx CLI binaries with Git LFS * Update checkmarx-ast-cli to 2.3.27 * change to 2.3.27-itay pre ealse cli * remove exe files * change tag cli * Revert "remove exe files" This reverts commit d8c11d96c70487372a7d8833c5bf99a468ee1051. * revert tag * Update cx-mac * Update cx.exe * Update cx-linux * Update checkmarx-ast-cli.version * Update ScanTest.test.ts * add ignore file to secrets (#865) Co-authored-by: Itay Paz * add ignore secrets test * fix ignore file * change tag for pre prealse cli * Track Checkmarx CLI binaries with Git LFS * Update checkmarx-ast-cli to 2.3.27 * revert tag * Update checkmarx-ast-cli.version --------- Co-authored-by: Itay Paz Co-authored-by: github-actions Co-authored-by: Daniel Greenspan <33864348+cx-daniel-greenspan@users.noreply.github.com> Co-authored-by: Ben Alvo <144705560+cx-ben-alvo@users.noreply.github.com> --- src/main/wrapper/CxConstants.ts | 1 + src/main/wrapper/CxWrapper.ts | 49 ++++++++++++++------ src/main/wrapper/resources/cx-linux | 4 +- src/main/wrapper/resources/cx-mac | 4 +- src/main/wrapper/resources/cx.exe | 4 +- src/tests/ScanTest.test.ts | 46 ++++++++++++++++-- src/tests/data/ignoreFileSecrets.json | 7 +++ src/tests/data/ossTypes.ts | 21 +++++++++ tsc/tests/data/checkmarxIgnoredTempFile.json | 7 +++ tsc/tests/data/package.json | 3 +- 10 files changed, 122 insertions(+), 24 deletions(-) create mode 100644 src/tests/data/ignoreFileSecrets.json create mode 100644 src/tests/data/ossTypes.ts create mode 100644 tsc/tests/data/checkmarxIgnoredTempFile.json diff --git a/src/main/wrapper/CxConstants.ts b/src/main/wrapper/CxConstants.ts index 8bbaf5c8..b9b0df75 100644 --- a/src/main/wrapper/CxConstants.ts +++ b/src/main/wrapper/CxConstants.ts @@ -1,4 +1,5 @@ export enum CxConstants { + IGNORE__FILE_PATH = "--ignored-file-path", SOURCE = "-s", VERBOSE = "-v", PROJECT_NAME = "--project-name", diff --git a/src/main/wrapper/CxWrapper.ts b/src/main/wrapper/CxWrapper.ts index d751a4bb..d9b98843 100644 --- a/src/main/wrapper/CxWrapper.ts +++ b/src/main/wrapper/CxWrapper.ts @@ -57,7 +57,7 @@ export class CxWrapper { } } - + initializeCommands(formatRequired: boolean): string[] { const list: string[] = []; if (this.config.clientId) { @@ -149,13 +149,43 @@ export class CxWrapper { return await exec.executeCommands(this.config.pathToExecutable, commands, CxConstants.SCAN_ASCA); } - async ossScanResults(sourceFile: string): Promise { - const commands: string[] = [CxConstants.CMD_SCAN, CxConstants.CMD_OSS, CxConstants.SOURCE, sourceFile]; - commands.push(...this.initializeCommands(false)); - const exec = new ExecutionService(); - return await exec.executeCommands(this.config.pathToExecutable, commands, CxConstants.SCAN_OSS); + async ossScanResults(sourceFile: string, ignoredFilePath?: string): Promise { + const commands: string[] = [ + CxConstants.CMD_SCAN, + CxConstants.CMD_OSS, + CxConstants.SOURCE, + sourceFile + ]; + + if (ignoredFilePath) { + commands.push(CxConstants.IGNORE__FILE_PATH); + commands.push(ignoredFilePath); + } + + commands.push(...this.initializeCommands(false)); + + const exec = new ExecutionService(); + return await exec.executeCommands(this.config.pathToExecutable, commands, CxConstants.SCAN_OSS); +} + + async secretsScanResults(sourceFile: string, ignoredFilePath?: string): Promise { + const commands: string[] = [ + CxConstants.CMD_SCAN, + CxConstants.CMD_SECRETS, + CxConstants.SOURCE, + sourceFile + ]; + + if (ignoredFilePath) { + commands.push(CxConstants.IGNORE__FILE_PATH); + commands.push(ignoredFilePath); } + commands.push(...this.initializeCommands(false)); + + const exec = new ExecutionService(); + return await exec.executeCommands(this.config.pathToExecutable, commands, CxConstants.SCAN_SECRETS); +} async containersRealtimeScanResults(sourceFile: string): Promise { const commands: string[] = [CxConstants.CMD_SCAN, CxConstants.CMD_CONTAINERS_REALTIME, CxConstants.SOURCE, sourceFile]; commands.push(...this.initializeCommands(false)); @@ -163,13 +193,6 @@ export class CxWrapper { return await exec.executeCommands(this.config.pathToExecutable, commands, CxConstants.SCAN_CONTAINERS_REALTIME); } - async secretsScanResults(sourceFile: string): Promise { - const commands: string[] = [CxConstants.CMD_SCAN, CxConstants.CMD_SECRETS, CxConstants.SOURCE, sourceFile]; - commands.push(...this.initializeCommands(false)); - const exec = new ExecutionService(); - return await exec.executeCommands(this.config.pathToExecutable, commands, CxConstants.SCAN_SECRETS); - } - async scanCancel(id: string): Promise { const commands: string[] = [CxConstants.CMD_SCAN, CxConstants.SUB_CMD_CANCEL, CxConstants.SCAN_ID, id]; commands.push(...this.initializeCommands(false)); diff --git a/src/main/wrapper/resources/cx-linux b/src/main/wrapper/resources/cx-linux index 772d7ef8..9f7b5b78 100755 --- a/src/main/wrapper/resources/cx-linux +++ b/src/main/wrapper/resources/cx-linux @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c575ad83e1b594441fa60b9ced859709adaeb1fb82310c7a14cc03faf8bed385 -size 75616440 +oid sha256:3dc4decd7c938c329a672b42f273e5a439e39294d60f7adb81e6e79b7187b333 +size 75718840 diff --git a/src/main/wrapper/resources/cx-mac b/src/main/wrapper/resources/cx-mac index 68ca418a..9376a70c 100755 --- a/src/main/wrapper/resources/cx-mac +++ b/src/main/wrapper/resources/cx-mac @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a290c0a5147403168bf8f56bb6b7752e76a278ded9639f4b8563e4a0f8f77090 -size 152195792 +oid sha256:c7ffcb8755b167b5b6cc2c4610bc4ebe664af6974df2127092ef30c2b7b17223 +size 152395216 diff --git a/src/main/wrapper/resources/cx.exe b/src/main/wrapper/resources/cx.exe index cff311ae..d18fa400 100644 --- a/src/main/wrapper/resources/cx.exe +++ b/src/main/wrapper/resources/cx.exe @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9cb276f871d8fc9460baef9d12f7aaf5773d133e3327a83d7cfd228db8aa0d97 -size 77584256 +oid sha256:14d343b959bcb155f03f2aa5f80fdb8e549b91827705051ef9455b6d67b12ad0 +size 77686208 diff --git a/src/tests/ScanTest.test.ts b/src/tests/ScanTest.test.ts index e245dcc8..34e438a7 100644 --- a/src/tests/ScanTest.test.ts +++ b/src/tests/ScanTest.test.ts @@ -2,6 +2,7 @@ import { CxWrapper } from '../main/wrapper/CxWrapper'; import { CxCommandOutput } from "../main/wrapper/CxCommandOutput"; import { CxParamType } from "../main/wrapper/CxParamType"; import { BaseTest } from "./BaseTest"; +import {OssPackage} from "./data/ossTypes"; describe("ScanCreate cases", () => { const cxScanConfig = new BaseTest(); @@ -173,23 +174,59 @@ describe("ScanCreate cases", () => { expect(Number.isInteger(scanObject.scanDetails[0].line)).toBe(true); expect(typeof scanObject.scanDetails[0].description).toBe('string'); }); - + it('ScanOss Successful case', async () => { const wrapper = new CxWrapper(cxScanConfig); - const cxCommandOutput: CxCommandOutput = await wrapper.ossScanResults("tsc/tests/data/package.json"); + const cxCommandOutput: CxCommandOutput = await wrapper.ossScanResults("tsc/tests/data/package.json",""); console.log("Json object from scanOSS successful case: " + JSON.stringify(cxCommandOutput)); expect(cxCommandOutput.payload).toBeDefined(); expect(cxCommandOutput.exitCode).toBe(0); }); - it.skip('ScanSecrets Successful case', async () => { + it.skip('ScanOss with ignored package should filter results', async () => { + const wrapper = new CxWrapper(cxScanConfig); + const sourceFile = "tsc/tests/data/package.json"; + const ignoredFile = "tsc/tests/data/checkmarxIgnoredTempFile.json"; + + const cxCommandOutput: CxCommandOutput = await wrapper.ossScanResults(sourceFile, ignoredFile); + + expect(cxCommandOutput.exitCode).toBe(0); + expect(cxCommandOutput.payload).toBeDefined(); + + const results = cxCommandOutput.payload as OssPackage[]; + + console.log("Filtered OSS packages:", results); + + expect(results.length).toBe(1); + + const hasCOA = results.some(pkg => + pkg.PackageManager === "coa" && pkg.PackageVersion === "3.1.3" + ); + expect(hasCOA).toBe(false); +}); + + it('ScanSecrets Successful case', async () => { const wrapper = new CxWrapper(cxScanConfig); - const cxCommandOutput: CxCommandOutput = await wrapper.secretsScanResults("src/tests/data/secret-exposed.txt"); + const cxCommandOutput: CxCommandOutput = await wrapper.secretsScanResults("src/tests/data/secret-exposed.txt",""); console.log("Json object from scanOSS successful case: " + JSON.stringify(cxCommandOutput)); expect(cxCommandOutput.payload).toBeDefined(); expect(cxCommandOutput.exitCode).toBe(0); }); + it.skip('ScanSecrets with ignore file filters the result', async () => { + const wrapper = new CxWrapper(cxScanConfig); + const cxCommandOutput: CxCommandOutput = await wrapper.secretsScanResults( + "src/tests/data/secret-exposed.txt", + "src/tests/data/ignoreFileSecrets.json" + ); + + console.log("Json object from scanSecrets with ignore file: " + JSON.stringify(cxCommandOutput)); + expect(cxCommandOutput.payload).toBeDefined(); + expect(Array.isArray(cxCommandOutput.payload)).toBe(true); + expect(cxCommandOutput.payload.length).toBe(0); + expect(cxCommandOutput.exitCode).toBe(0); +}); + it.skip('ScanContainersRealtime Successful case', async () => { const wrapper = new CxWrapper(cxScanConfig); const cxCommandOutput: CxCommandOutput = await wrapper.containersRealtimeScanResults("src/tests/data/Dockerfile"); @@ -200,3 +237,4 @@ describe("ScanCreate cases", () => { }); + diff --git a/src/tests/data/ignoreFileSecrets.json b/src/tests/data/ignoreFileSecrets.json new file mode 100644 index 00000000..fc2e28f7 --- /dev/null +++ b/src/tests/data/ignoreFileSecrets.json @@ -0,0 +1,7 @@ +[ +{ + "Title": "github-pat", + "FilePath": "/Users/itaypaz/Library/CloudStorage/OneDrive-Checkmarx/Documents/jswrapper/ast-cli-javascript-wrapper/src/tests/data/secret-exposed.txt", + "Line": 3 + } +] \ No newline at end of file diff --git a/src/tests/data/ossTypes.ts b/src/tests/data/ossTypes.ts new file mode 100644 index 00000000..e6e7b9fd --- /dev/null +++ b/src/tests/data/ossTypes.ts @@ -0,0 +1,21 @@ +export interface Location { + Line: number; + StartIndex: number; + EndIndex: number; +} + +export interface Vulnerability { + CVE: string; + Description: string; + Severity: string; +} + +export interface OssPackage { + PackageManager: string; + PackageName: string; + PackageVersion: string; + FilePath: string; + Locations: Location[]; + Status: string; + Vulnerabilities: Vulnerability[]; +} diff --git a/tsc/tests/data/checkmarxIgnoredTempFile.json b/tsc/tests/data/checkmarxIgnoredTempFile.json new file mode 100644 index 00000000..f8697fb2 --- /dev/null +++ b/tsc/tests/data/checkmarxIgnoredTempFile.json @@ -0,0 +1,7 @@ +[ + { + "PackageManager": "npm", + "PackageName": "coa", + "PackageVersion": "3.1.3" + } +] \ No newline at end of file diff --git a/tsc/tests/data/package.json b/tsc/tests/data/package.json index 0d9789b5..3be6abe0 100644 --- a/tsc/tests/data/package.json +++ b/tsc/tests/data/package.json @@ -3,6 +3,7 @@ "version": "0.0.1", "description": "AST CLI Javascript wrapper tests", "dependencies": { - "log4js": "^6.9.1" + "log4js": "^6.9.1", + "coa":"3.1.3" } } From e819f2516278fb8bd380160859468dca8b472ebd Mon Sep 17 00:00:00 2001 From: Sarah Chen <173361628+cx-sarah-chen@users.noreply.github.com> Date: Tue, 22 Jul 2025 16:51:00 +0300 Subject: [PATCH 04/13] Add telemetry command support (AST-103475) (#858) * Add telemetry command support * Update command initialization to not require format * Refactor telemetryAIEvent parameters and add tests for telemetry functionality * Fix vul * Skip telemetryAIEvent test * Remove timestamp parameter * Track Checkmarx CLI binaries with Git LFS * Update checkmarx-ast-cli to 2.3.27 * Update checkmarx-ast-cli.version * Update cx-linux * Update cx-mac * Update cx.exe --------- Co-authored-by: github-actions Co-authored-by: Daniel Greenspan <33864348+cx-daniel-greenspan@users.noreply.github.com> Co-authored-by: Itay Paz <143506741+cx-itay-paz@users.noreply.github.com> --- package-lock.json | 541 ++++++-------------------------- src/main/wrapper/CxConstants.ts | 9 +- src/main/wrapper/CxWrapper.ts | 116 ++++--- src/tests/TelemetryTest.test.ts | 36 +++ 4 files changed, 209 insertions(+), 493 deletions(-) create mode 100644 src/tests/TelemetryTest.test.ts diff --git a/package-lock.json b/package-lock.json index 21aa4095..c8cf9942 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,12 +35,15 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.16.7" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" @@ -250,19 +253,21 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -277,109 +282,28 @@ } }, "node_modules/@babel/helpers": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.3.tgz", - "integrity": "sha512-HwJiz52XaS96lX+28Tnbu31VeFSQJGOeKHJeaEPQlTl7PnlhFElWPj8tUXtqFIzeN86XxXoBr+WFAyK2PPVz6g==", - "dev": true, - "dependencies": { - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.6" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@babel/parser": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", + "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "@babel/types": "^7.28.0" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", - "dev": true, "bin": { "parser": "bin/babel-parser.js" }, @@ -583,14 +507,15 @@ } }, "node_modules/@babel/template": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", - "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.14.5", - "@babel/parser": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -617,19 +542,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/traverse/node_modules/@babel/generator": { "version": "7.23.0", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", @@ -682,84 +594,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/traverse/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/traverse/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/traverse/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/traverse/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/@babel/traverse/node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -769,36 +603,15 @@ "node": ">=4" } }, - "node_modules/@babel/traverse/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/traverse/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "version": "7.28.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.1.tgz", + "integrity": "sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -2021,10 +1834,11 @@ "dev": true }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2923,10 +2737,11 @@ } }, "node_modules/filelist/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -4980,6 +4795,13 @@ "node": ">=8" } }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -5586,15 +5408,6 @@ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -5905,12 +5718,14 @@ "dev": true }, "@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, "requires": { - "@babel/highlight": "^7.16.7" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" } }, "@babel/compat-data": { @@ -6067,15 +5882,15 @@ } }, "@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true }, "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "dev": true }, "@babel/helper-validator-option": { @@ -6085,91 +5900,24 @@ "dev": true }, "@babel/helpers": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.3.tgz", - "integrity": "sha512-HwJiz52XaS96lX+28Tnbu31VeFSQJGOeKHJeaEPQlTl7PnlhFElWPj8tUXtqFIzeN86XxXoBr+WFAyK2PPVz6g==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", "dev": true, "requires": { - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0" + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.6" } }, - "@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", + "@babel/parser": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", + "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } + "@babel/types": "^7.28.0" } }, - "@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", - "dev": true - }, "@babel/plugin-syntax-async-generators": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", @@ -6313,14 +6061,14 @@ } }, "@babel/template": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", - "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/parser": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" } }, "@babel/traverse": { @@ -6341,16 +6089,6 @@ "globals": "^11.1.0" }, "dependencies": { - "@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", - "dev": true, - "requires": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" - } - }, "@babel/generator": { "version": "7.23.0", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", @@ -6391,101 +6129,22 @@ "@babel/types": "^7.22.5" } }, - "@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - } - }, - "@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - } - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } } } }, "@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "version": "7.28.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.1.tgz", + "integrity": "sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==", "dev": true, "requires": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" } }, "@bcoe/v8-coverage": { @@ -7421,9 +7080,9 @@ "dev": true }, "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -8100,9 +7759,9 @@ }, "dependencies": { "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "requires": { "balanced-match": "^1.0.0" @@ -9667,6 +9326,12 @@ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true }, + "picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -10115,12 +9780,6 @@ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", diff --git a/src/main/wrapper/CxConstants.ts b/src/main/wrapper/CxConstants.ts index b9b0df75..ca1468df 100644 --- a/src/main/wrapper/CxConstants.ts +++ b/src/main/wrapper/CxConstants.ts @@ -114,6 +114,11 @@ export enum CxConstants { CMD_LEARN_MORE = "learn-more", IDE_SCANS_KEY = "scan.config.plugins.ideScans", AI_GUIDED_REMEDIATION_KEY = "scan.config.plugins.aiGuidedRemediation", - AI_MCP_SERVER_KEY = "scan.config.plugins.aiMcpServer" - + AI_MCP_SERVER_KEY = "scan.config.plugins.aiMcpServer", + TELEMETRY = "telemetry", + SUB_CMD_TELEMETRY_AI = "ai", + AI_PROVIDER = "--ai-provider", + TYPE = "--type", + SUB_TYPE = "--sub-type", + PROBLEM_SEVERITY = "--problem-severity" } diff --git a/src/main/wrapper/CxWrapper.ts b/src/main/wrapper/CxWrapper.ts index d9b98843..685af93b 100644 --- a/src/main/wrapper/CxWrapper.ts +++ b/src/main/wrapper/CxWrapper.ts @@ -1,14 +1,14 @@ -import {CxConfig} from "./CxConfig"; -import {CxParamType} from "./CxParamType"; -import {CxConstants} from "./CxConstants"; -import {ExecutionService} from "./ExecutionService"; -import {CxCommandOutput} from "./CxCommandOutput"; -import {getLoggerWithFilePath, logger} from "./loggerConfig"; +import { CxConfig } from "./CxConfig"; +import { CxParamType } from "./CxParamType"; +import { CxConstants } from "./CxConstants"; +import { ExecutionService } from "./ExecutionService"; +import { CxCommandOutput } from "./CxCommandOutput"; +import { getLoggerWithFilePath, logger } from "./loggerConfig"; import * as fs from "fs" import * as os from "os"; import CxBFL from "../bfl/CxBFL"; import path = require('path'); -import {getTrimmedMapValue} from "./utils"; +import { getTrimmedMapValue } from "./utils"; type ParamTypeMap = Map; @@ -84,8 +84,8 @@ export class CxWrapper { list.push(CxConstants.TENANT); list.push(this.config.tenant); } - if(this.config.additionalParameters){ - this.prepareAdditionalParams(this.config.additionalParameters).forEach(function (param){ + if (this.config.additionalParameters) { + this.prepareAdditionalParams(this.config.additionalParameters).forEach(function (param) { list.push(param) }) } @@ -246,9 +246,9 @@ export class CxWrapper { return await exec.executeCommands(this.config.pathToExecutable, commands, CxConstants.PREDICATE_TYPE); } - async triageUpdate(projectId: string, similarityId: string, scanType: string, state: string, comment: string, severity: string, stateId:number|null = null): Promise { + async triageUpdate(projectId: string, similarityId: string, scanType: string, state: string, comment: string, severity: string, stateId: number | null = null): Promise { const commands: string[] = [CxConstants.CMD_TRIAGE, CxConstants.SUB_CMD_UPDATE, CxConstants.PROJECT_ID, projectId, CxConstants.SIMILARITY_ID, similarityId, CxConstants.SCAN_TYPES_SUB_CMD, scanType, CxConstants.STATE, state, CxConstants.COMMENT, comment, CxConstants.SEVERITY, severity]; - if(stateId) { + if (stateId) { commands.push(CxConstants.STATE_ID) commands.push(stateId.toString()) } @@ -275,7 +275,7 @@ export class CxWrapper { return exec.executeResultsCommandsFile(scanId, CxConstants.FORMAT_JSON, CxConstants.FORMAT_JSON_FILE, commands, this.config.pathToExecutable, fileName); } - async riskManagementResults(projectId: string, scanId: string, limit?: number): Promise { + async riskManagementResults(projectId: string, scanId: string, limit?: number): Promise { const commands: string[] = [CxConstants.CMD_RESULT, CxConstants.CMD_RISK_MANAGEMENT]; commands.push(CxConstants.PROJECT_ID, projectId); commands.push(CxConstants.SCAN_ID, scanId); @@ -343,10 +343,10 @@ export class CxWrapper { return response; } - async kicsRealtimeScan(fileSources: string, engine:string, additionalParams: string):Promise<[Promise,any]> { + async kicsRealtimeScan(fileSources: string, engine: string, additionalParams: string): Promise<[Promise, any]> { const commands: string[] = [CxConstants.CMD_SCAN, CxConstants.CMD_KICS_REALTIME, CxConstants.FILE_SOURCES, fileSources, CxConstants.ADDITONAL_PARAMS, additionalParams]; - if(engine.length>0){ - commands.push(CxConstants.ENGINE,engine) + if (engine.length > 0) { + commands.push(CxConstants.ENGINE, engine) } commands.push(...this.initializeCommands(false)); const exec = new ExecutionService(); @@ -365,66 +365,66 @@ export class CxWrapper { } - async learnMore(queryId: string){ - const commands: string[] = [CxConstants.CMD_UTILS,CxConstants.CMD_LEARN_MORE,CxConstants.QUERY_ID,queryId] + async learnMore(queryId: string) { + const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.CMD_LEARN_MORE, CxConstants.QUERY_ID, queryId] commands.push(...this.initializeCommands(true)) const exec = new ExecutionService(); return exec.executeCommands(this.config.pathToExecutable, commands, CxConstants.LEARN_MORE_DESCRIPTIONS_TYPE); } - async kicsRemediation(resultsFile: string, kicsFile:string, engine:string,similarityIds?: string):Promise<[Promise,any]> { - const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.CMD_REMEDIATION,CxConstants.KICS,CxConstants.KICS_REMEDIATION_RESULTS_FILE, resultsFile, CxConstants.KICS_REMEDIATION_KICS_FILE, kicsFile]; - if(engine.length>0){ - commands.push(CxConstants.ENGINE,engine) + async kicsRemediation(resultsFile: string, kicsFile: string, engine: string, similarityIds?: string): Promise<[Promise, any]> { + const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.CMD_REMEDIATION, CxConstants.KICS, CxConstants.KICS_REMEDIATION_RESULTS_FILE, resultsFile, CxConstants.KICS_REMEDIATION_KICS_FILE, kicsFile]; + if (engine.length > 0) { + commands.push(CxConstants.ENGINE, engine) } - if(similarityIds){ - commands.push(CxConstants.KICS_REMEDIATION_SIMILARITY_IDS,similarityIds) + if (similarityIds) { + commands.push(CxConstants.KICS_REMEDIATION_SIMILARITY_IDS, similarityIds) } commands.push(...this.initializeCommands(false)); const exec = new ExecutionService(); return exec.executeKicsCommands(this.config.pathToExecutable, commands, CxConstants.KICS_REMEDIATION_TYPE); } - async scaRemediation(packageFiles: string, packages:string, packageVersion:string): Promise { - const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.CMD_REMEDIATION,CxConstants.SUB_CMD_REMEDIATION_SCA,CxConstants.SCA_REMEDIATION_PACKAGE_FILES, packageFiles,CxConstants.SCA_REMEDIATION_PACKAGE, packages,CxConstants.SCA_REMEDIATION_PACKAGE_VERSION,packageVersion]; + async scaRemediation(packageFiles: string, packages: string, packageVersion: string): Promise { + const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.CMD_REMEDIATION, CxConstants.SUB_CMD_REMEDIATION_SCA, CxConstants.SCA_REMEDIATION_PACKAGE_FILES, packageFiles, CxConstants.SCA_REMEDIATION_PACKAGE, packages, CxConstants.SCA_REMEDIATION_PACKAGE_VERSION, packageVersion]; commands.push(...this.initializeCommands(false)); const exec = new ExecutionService(); return exec.executeCommands(this.config.pathToExecutable, commands); } async ideScansEnabled(): Promise { - const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.SUB_CMD_TENANT]; - commands.push(...this.initializeCommands(false)); + const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.SUB_CMD_TENANT]; + commands.push(...this.initializeCommands(false)); - const exec = new ExecutionService(); - const output = await exec.executeMapTenantOutputCommands(this.config.pathToExecutable, commands); + const exec = new ExecutionService(); + const output = await exec.executeMapTenantOutputCommands(this.config.pathToExecutable, commands); - const value = getTrimmedMapValue(output, CxConstants.IDE_SCANS_KEY); - return value?.toLowerCase() === "true"; -} + const value = getTrimmedMapValue(output, CxConstants.IDE_SCANS_KEY); + return value?.toLowerCase() === "true"; + } async guidedRemediationEnabled(): Promise { - const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.SUB_CMD_TENANT]; - commands.push(...this.initializeCommands(false)); + const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.SUB_CMD_TENANT]; + commands.push(...this.initializeCommands(false)); - const exec = new ExecutionService(); - const output = await exec.executeMapTenantOutputCommands(this.config.pathToExecutable, commands); + const exec = new ExecutionService(); + const output = await exec.executeMapTenantOutputCommands(this.config.pathToExecutable, commands); - const value = getTrimmedMapValue(output, CxConstants.AI_GUIDED_REMEDIATION_KEY); - return value?.toLowerCase() === "true"; -} + const value = getTrimmedMapValue(output, CxConstants.AI_GUIDED_REMEDIATION_KEY); + return value?.toLowerCase() === "true"; + } - async aiMcpServerEnabled(): Promise { - const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.SUB_CMD_TENANT]; - commands.push(...this.initializeCommands(false)); + async aiMcpServerEnabled(): Promise { + const commands: string[] = [CxConstants.CMD_UTILS, CxConstants.SUB_CMD_TENANT]; + commands.push(...this.initializeCommands(false)); - const exec = new ExecutionService(); - const output = await exec.executeMapTenantOutputCommands(this.config.pathToExecutable, commands); + const exec = new ExecutionService(); + const output = await exec.executeMapTenantOutputCommands(this.config.pathToExecutable, commands); - const value = getTrimmedMapValue(output, CxConstants.AI_MCP_SERVER_KEY); - return value?.toLowerCase() === "true"; -} + const value = getTrimmedMapValue(output, CxConstants.AI_MCP_SERVER_KEY); + return value?.toLowerCase() === "true"; + } async kicsChat(apikey: string, file: string, line: number, severity: string, vulnerability: string, input: string, conversationId?: string, model?: string): Promise { const commands: string[] = [ @@ -467,7 +467,7 @@ export class CxWrapper { return new ExecutionService().executeCommands(this.config.pathToExecutable, commands, CxConstants.CHAT_TYPE); } - async maskSecrets( file: string): Promise { + async maskSecrets(file: string): Promise { const commands: string[] = [ CxConstants.CMD_UTILS, CxConstants.CMD_MASK_SECRETS, @@ -478,10 +478,26 @@ export class CxWrapper { return new ExecutionService().executeCommands(this.config.pathToExecutable, commands, CxConstants.MASK_TYPE); } - prepareAdditionalParams(additionalParameters: string) : string[] { + telemetryAIEvent(aiProvider: string, agent: string, eventType: string, subType: string, engine: string, problemSeverity: string): Promise { + const commands: string[] = [ + CxConstants.TELEMETRY, + CxConstants.SUB_CMD_TELEMETRY_AI, + CxConstants.AI_PROVIDER, aiProvider, + CxConstants.AGENT, agent, + CxConstants.TYPE, eventType, + CxConstants.SUB_TYPE, subType, + CxConstants.ENGINE, engine, + CxConstants.PROBLEM_SEVERITY, problemSeverity + ]; + commands.push(...this.initializeCommands(false)); + const exec = new ExecutionService(); + return exec.executeCommands(this.config.pathToExecutable, commands); + } + + prepareAdditionalParams(additionalParameters: string): string[] { const params: string[] = []; - if(!additionalParameters) { + if (!additionalParameters) { return params; } diff --git a/src/tests/TelemetryTest.test.ts b/src/tests/TelemetryTest.test.ts new file mode 100644 index 00000000..74cdc933 --- /dev/null +++ b/src/tests/TelemetryTest.test.ts @@ -0,0 +1,36 @@ +import { CxWrapper } from '../main/wrapper/CxWrapper'; +import { CxCommandOutput } from "../main/wrapper/CxCommandOutput"; +import { BaseTest } from "./BaseTest"; + +describe("Telemetry cases", () => { + const cxScanConfig = new BaseTest(); + + it.skip('TelemetryAIEvent Successful case with minimal parameters', async () => { + const wrapper = new CxWrapper(cxScanConfig); + const cxCommandOutput: CxCommandOutput = await wrapper.telemetryAIEvent( + "Cursor", + "Cursos", + "click", + "ast-results.viewPackageDetails", + "secrets", + "high" + ); + console.log("Json object from telemetryAIEvent successful case: " + JSON.stringify(cxCommandOutput)); + expect(cxCommandOutput.exitCode).toBe(0); + }); + + + it.skip('TelemetryAIEvent Successful case with edge case parameters', async () => { + const wrapper = new CxWrapper(cxScanConfig); + const cxCommandOutput: CxCommandOutput = await wrapper.telemetryAIEvent( + "", + "", + "", + "", + "", + "" + ); + console.log("Json object from telemetryAIEvent with empty parameters: " + JSON.stringify(cxCommandOutput)); + expect(typeof cxCommandOutput.exitCode).toBe(0); + }); +}); \ No newline at end of file From 663623cd49bd92d91a502068f16d6d45d741c627 Mon Sep 17 00:00:00 2001 From: cx-anurag-dalke <120229307+cx-anurag-dalke@users.noreply.github.com> Date: Tue, 22 Jul 2025 20:24:04 +0530 Subject: [PATCH 05/13] added mandatory review from ast-cli team --- .github/workflows/ast-cli-team-review.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/workflows/ast-cli-team-review.yml diff --git a/.github/workflows/ast-cli-team-review.yml b/.github/workflows/ast-cli-team-review.yml new file mode 100644 index 00000000..b597e154 --- /dev/null +++ b/.github/workflows/ast-cli-team-review.yml @@ -0,0 +1,22 @@ +name: AST-CLI-Team-Review +on: + pull_request_target: + types: [ready_for_review, opened, reopened] + +permissions: + contents: none + issues: write + pull-requests: write + +jobs: + add-assignee-and-reviewers: + runs-on: ubuntu-latest + if: ${{ github.event.pull_request.user.type != 'Bot' }} + steps: + - name: Request reviewers + env: + GH_REPO: ${{ github.repository }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PRNUM: ${{ github.event.pull_request.number }} + PRAUTHOR: ${{ github.event.pull_request.user.login }} + run: gh pr edit $PRNUM --add-reviewer Checkmarx/ast-sypher-team \ No newline at end of file From 86ff1be78e2459df1ae5b2b86d3e01e327fed48c Mon Sep 17 00:00:00 2001 From: cx-anurag-dalke <120229307+cx-anurag-dalke@users.noreply.github.com> Date: Tue, 22 Jul 2025 20:54:53 +0530 Subject: [PATCH 06/13] add-assignee-and-reviewers --- .github/workflows/ast-cli-team-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ast-cli-team-review.yml b/.github/workflows/ast-cli-team-review.yml index b597e154..9a89bf93 100644 --- a/.github/workflows/ast-cli-team-review.yml +++ b/.github/workflows/ast-cli-team-review.yml @@ -1,4 +1,4 @@ -name: AST-CLI-Team-Review +name: add-assignee-and-reviewers on: pull_request_target: types: [ready_for_review, opened, reopened] From 1c5f656da2fa979223708cc63abb2d3fd1646bcf Mon Sep 17 00:00:00 2001 From: cx-anurag-dalke <120229307+cx-anurag-dalke@users.noreply.github.com> Date: Tue, 22 Jul 2025 21:01:32 +0530 Subject: [PATCH 07/13] updated org name --- .github/workflows/ast-cli-team-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ast-cli-team-review.yml b/.github/workflows/ast-cli-team-review.yml index 9a89bf93..a8cba273 100644 --- a/.github/workflows/ast-cli-team-review.yml +++ b/.github/workflows/ast-cli-team-review.yml @@ -19,4 +19,4 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} PRNUM: ${{ github.event.pull_request.number }} PRAUTHOR: ${{ github.event.pull_request.user.login }} - run: gh pr edit $PRNUM --add-reviewer Checkmarx/ast-sypher-team \ No newline at end of file + run: gh pr edit $PRNUM --add-reviewer CheckmarxDev/ast-sypher-team \ No newline at end of file From 4296e044335f9f5b5d4d13b9aa52ef7d6c187a56 Mon Sep 17 00:00:00 2001 From: cx-anurag-dalke <120229307+cx-anurag-dalke@users.noreply.github.com> Date: Tue, 22 Jul 2025 21:10:17 +0530 Subject: [PATCH 08/13] GH_TOKEN --- .github/workflows/ast-cli-team-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ast-cli-team-review.yml b/.github/workflows/ast-cli-team-review.yml index a8cba273..145d7bea 100644 --- a/.github/workflows/ast-cli-team-review.yml +++ b/.github/workflows/ast-cli-team-review.yml @@ -16,7 +16,7 @@ jobs: - name: Request reviewers env: GH_REPO: ${{ github.repository }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GH_TOKEN }} PRNUM: ${{ github.event.pull_request.number }} PRAUTHOR: ${{ github.event.pull_request.user.login }} run: gh pr edit $PRNUM --add-reviewer CheckmarxDev/ast-sypher-team \ No newline at end of file From 5108ebe8fbccc2ed7728ad92e5d715de9c05c773 Mon Sep 17 00:00:00 2001 From: cx-anurag-dalke <120229307+cx-anurag-dalke@users.noreply.github.com> Date: Tue, 22 Jul 2025 21:14:35 +0530 Subject: [PATCH 09/13] addedd AST_CLI_GH_TOKEN --- .github/workflows/ast-cli-team-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ast-cli-team-review.yml b/.github/workflows/ast-cli-team-review.yml index 145d7bea..07dbe623 100644 --- a/.github/workflows/ast-cli-team-review.yml +++ b/.github/workflows/ast-cli-team-review.yml @@ -16,7 +16,7 @@ jobs: - name: Request reviewers env: GH_REPO: ${{ github.repository }} - GH_TOKEN: ${{ secrets.GH_TOKEN }} + GH_TOKEN: ${{ secrets.AST_CLI_GH_TOKEN }} PRNUM: ${{ github.event.pull_request.number }} PRAUTHOR: ${{ github.event.pull_request.user.login }} run: gh pr edit $PRNUM --add-reviewer CheckmarxDev/ast-sypher-team \ No newline at end of file From 2013385e9e911f150ff7065f0ef79eed9749a7ae Mon Sep 17 00:00:00 2001 From: cx-anurag-dalke <120229307+cx-anurag-dalke@users.noreply.github.com> Date: Tue, 22 Jul 2025 21:20:09 +0530 Subject: [PATCH 10/13] test --- .github/workflows/ast-cli-team-review.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ast-cli-team-review.yml b/.github/workflows/ast-cli-team-review.yml index 07dbe623..64669c99 100644 --- a/.github/workflows/ast-cli-team-review.yml +++ b/.github/workflows/ast-cli-team-review.yml @@ -3,6 +3,7 @@ on: pull_request_target: types: [ready_for_review, opened, reopened] + permissions: contents: none issues: write From 7578a49d3c51292ce9556f567393ca28f8f23fb0 Mon Sep 17 00:00:00 2001 From: cx-anurag-dalke <120229307+cx-anurag-dalke@users.noreply.github.com> Date: Tue, 22 Jul 2025 21:26:34 +0530 Subject: [PATCH 11/13] test-1 --- .github/workflows/ast-cli-team-review.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ast-cli-team-review.yml b/.github/workflows/ast-cli-team-review.yml index 64669c99..07dbe623 100644 --- a/.github/workflows/ast-cli-team-review.yml +++ b/.github/workflows/ast-cli-team-review.yml @@ -3,7 +3,6 @@ on: pull_request_target: types: [ready_for_review, opened, reopened] - permissions: contents: none issues: write From 268ebd2e6b0f96dd68e864ae230a1cc1be0a7b64 Mon Sep 17 00:00:00 2001 From: cx-anurag-dalke <120229307+cx-anurag-dalke@users.noreply.github.com> Date: Tue, 22 Jul 2025 21:38:22 +0530 Subject: [PATCH 12/13] test review --- .github/workflows/ast-cli-team-review.yml | 69 ++++++++++++++++++++--- CODEOWNERS | 3 +- 2 files changed, 63 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ast-cli-team-review.yml b/.github/workflows/ast-cli-team-review.yml index 07dbe623..310ae52e 100644 --- a/.github/workflows/ast-cli-team-review.yml +++ b/.github/workflows/ast-cli-team-review.yml @@ -1,22 +1,75 @@ name: add-assignee-and-reviewers + on: pull_request_target: - types: [ready_for_review, opened, reopened] + types: [ready_for_review, opened, reopened, review_requested, edited] permissions: - contents: none + contents: read issues: write - pull-requests: write + pull-requests: read jobs: add-assignee-and-reviewers: runs-on: ubuntu-latest if: ${{ github.event.pull_request.user.type != 'Bot' }} steps: - - name: Request reviewers + - name: Set up GitHub CLI + uses: cli/cli-action@v2 + with: + version: latest + + - name: Authenticate GitHub CLI + env: + GH_TOKEN: ${{ secrets.AST_CLI_GH_TOKEN }} + run: gh auth status + + - name: Fetch team members + id: team + env: + GH_TOKEN: ${{ secrets.AST_CLI_GH_TOKEN }} + run: | + gh api orgs/CheckmarxDev/teams/ast-sypher-team/members --jq '.[].login' > team_members.txt + echo "✅ Team members:" + cat team_members.txt + + - name: Fetch current reviewers + id: reviewers env: - GH_REPO: ${{ github.repository }} GH_TOKEN: ${{ secrets.AST_CLI_GH_TOKEN }} - PRNUM: ${{ github.event.pull_request.number }} - PRAUTHOR: ${{ github.event.pull_request.user.login }} - run: gh pr edit $PRNUM --add-reviewer CheckmarxDev/ast-sypher-team \ No newline at end of file + run: | + gh pr view ${{ github.event.pull_request.number }} --json reviewRequests --jq '.reviewRequests' > all_reviewers.json + + jq -r '.[] | select(.type == "User") | .login' all_reviewers.json > user_reviewers.txt + jq -r '.[] | select(.type == "Team") | .login' all_reviewers.json > team_reviewers.txt + + echo "👤 User reviewers:" + cat user_reviewers.txt || echo "None" + + echo "👥 Team reviewers:" + cat team_reviewers.txt || echo "None" + + - name: Validate reviewers are only from ast-sypher-team + run: | + INVALID_USERS=() + while read reviewer; do + if ! grep -qx "$reviewer" team_members.txt; then + INVALID_USERS+=("$reviewer") + fi + done < user_reviewers.txt || true + + INVALID_TEAMS=() + while read team; do + if [ "$team" != "ast-sypher-team" ]; then + INVALID_TEAMS+=("$team") + fi + done < team_reviewers.txt || true + + if [ ${#INVALID_USERS[@]} -gt 0 ] || [ ${#INVALID_TEAMS[@]} -gt 0 ]; then + echo "❌ Invalid reviewers detected!" + echo "Invalid users: ${INVALID_USERS[*]}" + echo "Invalid teams: ${INVALID_TEAMS[*]}" + exit 1 + fi + + echo "✅ All reviewers are valid members of the ast-sypher-team or the team itself." diff --git a/CODEOWNERS b/CODEOWNERS index 039bbd5a..9f27e179 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -2,4 +2,5 @@ # Each line is a file pattern followed by one or more owners # Specify the default owners for the entire repository -* @AlvoBen @greensd4 @miryamfoiferCX +* @cx-anurag-dalke @cx-rah-pid + From 5449ec65742df9f07ce86579ab9982512d4d8393 Mon Sep 17 00:00:00 2001 From: cx-ben-alvo <144705560+cx-ben-alvo@users.noreply.github.com> Date: Sun, 20 Jul 2025 11:55:12 +0300 Subject: [PATCH 13/13] Add containers realtime scan functionality and related constants --- src/main/wrapper/CxWrapper.ts | 7 +++++++ src/tests/ScanTest.test.ts | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/wrapper/CxWrapper.ts b/src/main/wrapper/CxWrapper.ts index 685af93b..617ea350 100644 --- a/src/main/wrapper/CxWrapper.ts +++ b/src/main/wrapper/CxWrapper.ts @@ -168,6 +168,13 @@ export class CxWrapper { return await exec.executeCommands(this.config.pathToExecutable, commands, CxConstants.SCAN_OSS); } + async containersRealtimeScanResults(sourceFile: string): Promise { + const commands: string[] = [CxConstants.CMD_SCAN, CxConstants.CMD_CONTAINERS_REALTIME, CxConstants.SOURCE, sourceFile]; + commands.push(...this.initializeCommands(false)); + const exec = new ExecutionService(); + return await exec.executeCommands(this.config.pathToExecutable, commands, CxConstants.SCAN_CONTAINERS_REALTIME); + } + async secretsScanResults(sourceFile: string, ignoredFilePath?: string): Promise { const commands: string[] = [ CxConstants.CMD_SCAN, diff --git a/src/tests/ScanTest.test.ts b/src/tests/ScanTest.test.ts index 34e438a7..8a851361 100644 --- a/src/tests/ScanTest.test.ts +++ b/src/tests/ScanTest.test.ts @@ -227,7 +227,7 @@ describe("ScanCreate cases", () => { expect(cxCommandOutput.exitCode).toBe(0); }); - it.skip('ScanContainersRealtime Successful case', async () => { + it('ScanContainersRealtime Successful case', async () => { const wrapper = new CxWrapper(cxScanConfig); const cxCommandOutput: CxCommandOutput = await wrapper.containersRealtimeScanResults("src/tests/data/Dockerfile"); console.log("Json object from scanContainersRealtime successful case: " + JSON.stringify(cxCommandOutput));