diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0bcda629..a35971f9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,10 +30,9 @@ jobs: - name: Checkmarx AST CLI Action uses: checkmarxDev/ast-github-action@main with: - project_name: ast-cli-javascript-wrapper - branch: master + project_name: ${{ github.repository }} base_uri: ${{ secrets.BASE_URI }} cx_tenant: ${{ secrets.TENANT }} cx_client_id: ${{ secrets.CLIENT_ID }} cx_client_secret: ${{ secrets.CLIENT_SECRET }} - additional_params: --tags galactica-team + additional_params: --tags "Galactica" diff --git a/src/main/bfl/CxBFL.ts b/src/main/bfl/CxBFL.ts new file mode 100644 index 00000000..d6f13b3e --- /dev/null +++ b/src/main/bfl/CxBFL.ts @@ -0,0 +1,30 @@ +export default class CxBFL { + column: number; + fileName: string = ""; + fullName: string = ""; + length: number; + line: number; + methodLine: number; + method: string = ""; + name: string = ""; + domType: string = ""; + + +static parseBFLResponse(resultObject: any[]): CxBFL[] { + let bflNode: CxBFL[] = []; + bflNode = resultObject.map((member: any) => { + let bflNode = new CxBFL(); + bflNode.column = member.column; + bflNode.fileName = member.fileName; + bflNode.fullName = member.fullName; + bflNode.length = member.length; + bflNode.line = member.line; + bflNode.methodLine = member.methodLine; + bflNode.method = member.method; + bflNode.name = member.name; + bflNode.domType = member.domType; + return bflNode; + }); + return bflNode; + } +} \ No newline at end of file diff --git a/src/main/wrapper/CxConstants.ts b/src/main/wrapper/CxConstants.ts index 2fb907ff..cc97ff30 100644 --- a/src/main/wrapper/CxConstants.ts +++ b/src/main/wrapper/CxConstants.ts @@ -26,6 +26,7 @@ export enum CxConstants { CMD_TRIAGE = "triage", SUB_CMD_UPDATE = "update", CMD_RESULT = "results", + SUB_CMD_BFL = "bfl", CMD_CODE_BASHING = "codebashing", SCAN_INFO_FORMAT = "--scan-info-format", FORMAT = "--format", @@ -38,6 +39,7 @@ export enum CxConstants { SCAN_ID = "--scan-id", PROJECT_ID = "--project-id", SIMILARITY_ID = "--similarity-id", + QUERY_ID = "--query-id", STATE = "--state", COMMENT = "--comment", SEVERITY = "--severity", @@ -48,6 +50,7 @@ export enum CxConstants { PROJECT_TYPE = "CxProject", PREDICATE_TYPE = "CxPredicate", CODE_BASHING_TYPE = "CxCodeBashing", + BFL_TYPE = "CxBFL", SAST = "sast", LANGUAGE = "--language", VULNERABILITY_TYPE = "--vulnerabity-type", diff --git a/src/main/wrapper/CxWrapper.ts b/src/main/wrapper/CxWrapper.ts index 668fc4c3..e29ff4d3 100644 --- a/src/main/wrapper/CxWrapper.ts +++ b/src/main/wrapper/CxWrapper.ts @@ -6,6 +6,7 @@ import {CxCommandOutput} from "./CxCommandOutput"; import { logger } from "./loggerConfig"; import * as fs from "fs" import * as os from "os"; +import CxBFL from "../bfl/CxBFL"; type ParamTypeMap = Map; @@ -216,6 +217,46 @@ export class CxWrapper { return commands; } + async getResultsBfl(scanId: string, queryId: string, resultNodes: any[]) { + const commands: string[] = [CxConstants.CMD_RESULT, CxConstants.SUB_CMD_BFL, CxConstants.SCAN_ID, scanId, CxConstants.QUERY_ID, queryId]; + commands.push(...this.initializeCommands(true)); + const exec = new ExecutionService(); + const response = await exec.executeCommands(this.config.pathToExecutable, commands, CxConstants.BFL_TYPE); + const bflNodeIndex = this.getIndexOfBflNode(response.payload, resultNodes) + response.payload[0] = bflNodeIndex; + return response; + } + + getIndexOfBflNode(bflNodes: CxBFL[], resultNodes: any[]): number { + + let bflNodeNotFound = -1; + for (const bflNode of bflNodes) { + for (const resultNode of resultNodes) { + + if(this.compareNodes(bflNode,resultNode)) + { + return resultNodes.indexOf(resultNode); + } + } + + } + return bflNodeNotFound; + + } + + compareNodes(bflNode: CxBFL, resultNode : any): boolean{ + + return bflNode.line == resultNode.line && + bflNode.column == resultNode.column && + bflNode.length == resultNode.length && + bflNode.name == resultNode.name && + bflNode.method == resultNode.method && + bflNode.domType == resultNode.domType && + bflNode.fileName == resultNode.fileName && + bflNode.fullName == resultNode.fullName && + bflNode.methodLine == resultNode.methodLine; + } + filterArguments(filters:string):string[]{ let r = []; if(filters.length>0){ diff --git a/src/main/wrapper/ExecutionService.ts b/src/main/wrapper/ExecutionService.ts index 3e0ed437..d64dafaa 100644 --- a/src/main/wrapper/ExecutionService.ts +++ b/src/main/wrapper/ExecutionService.ts @@ -7,6 +7,7 @@ import * as path from "path"; import CxResult from "../results/CxResult"; import CxProject from "../project/CxProject"; import CxCodeBashing from "../codebashing/CxCodeBashing"; +import CxBFL from "../bfl/CxBFL"; const spawn = require('child_process').spawn; @@ -83,6 +84,10 @@ export class ExecutionService { let codeBashing = CxCodeBashing.parseCodeBashing(resultObject); cxCommandOutput.payload = codeBashing; break; + case "CxBFL": + let bflNode = CxBFL.parseBFLResponse(resultObject); + cxCommandOutput.payload = bflNode; + break; default: cxCommandOutput.payload = resultObject; } @@ -121,7 +126,7 @@ export class ExecutionService { let cxCommandOutput = new CxCommandOutput(); // Need to check if file output is json or html if(fileExtension.includes("json")){ - let read_json = JSON.parse(read); + let read_json = JSON.parse(read.replace(/:([0-9]{15,}),/g, ':"$1",')); if (read_json.results){ let r : CxResult[] = read_json.results.map((member:any)=>{return Object.assign( new CxResult(),member);}); cxCommandOutput.payload = r; diff --git a/src/tests/ResultTest.test.ts b/src/tests/ResultTest.test.ts index 94b3ecf6..3daa9587 100644 --- a/src/tests/ResultTest.test.ts +++ b/src/tests/ResultTest.test.ts @@ -2,6 +2,8 @@ import {CxWrapper} from '../main/wrapper/CxWrapper'; import {CxCommandOutput} from "../main/wrapper/CxCommandOutput"; import {BaseTest} from "./BaseTest"; import * as fs from "fs"; +import { CxConstants } from '../main/wrapper/CxConstants'; +import CxResult from '../main/results/CxResult'; describe("Results cases",() => { let cxScanConfig = new BaseTest(); @@ -46,6 +48,17 @@ describe("Results cases",() => { expect(cxCommandOutput.payload.length).toBeGreaterThan(0); }); + it('Result bfl successful case', async () => { + const auth = new CxWrapper(cxScanConfig); + console.log("ScanID : " + cxScanConfig.scanId) + const results = await auth.getResultsList(cxScanConfig.scanId) + const result: CxResult = results.payload.find(res => res.type == CxConstants.SAST) + const data = result.data + const queryId = data.queryId + console.log("QueryID :" + result.data.queryId) + const cxCommandOutput: CxCommandOutput = await auth.getResultsBfl(cxScanConfig.scanId, queryId, data.nodes); + expect(cxCommandOutput.payload.length).toBeGreaterThanOrEqual(-1); + }); }); const fileExists = (file:any) => {