diff --git a/src/main/wrapper/CxWrapper.ts b/src/main/wrapper/CxWrapper.ts index d8b77df2..e31bf788 100644 --- a/src/main/wrapper/CxWrapper.ts +++ b/src/main/wrapper/CxWrapper.ts @@ -407,23 +407,62 @@ export class CxWrapper { return new ExecutionService().executeCommands(this.config.pathToExecutable, commands, CxConstants.MASK_TYPE); } - prepareAdditionalParams(additionalParameters: string): string[] { - const params: string[] = []; + /** + * Splits additional CLI parameters into an array of tokens, + * correctly handling quoted values and key=value pairs. + * + * @param additionalParameters - A single string containing extra parameters + * @returns Array of cleaned tokens ready to pass to the CLI + */ + private prepareAdditionalParams(additionalParameters: string): string[] { if (!additionalParameters) { - return params; - } + return []; + } + + // Trim whitespace and remove surrounding quotes if present + let trimmed = additionalParameters.trim(); + if ( + (trimmed.startsWith('"') && trimmed.endsWith('"')) || + (trimmed.startsWith("'") && trimmed.endsWith("'")) + ) { + trimmed = trimmed.slice(1, -1); + } + + // Regex matches sequences without whitespace or quoted segments + const regex = /(?:[^\s'"]+|'[^']*'|"[^"]*")+/g; + const rawTokens = trimmed.match(regex) || []; + + // Process tokens: remove quotes and handle key=value syntax + return rawTokens.map(token => { + // Remove surrounding quotes + if ( + (token.startsWith('"') && token.endsWith('"')) || + (token.startsWith("'") && token.endsWith("'")) + ) { + token = token.slice(1, -1); + } - const paramList = additionalParameters.match(/(?:[^\s"]+|"[^"]*")+/g); - logger.info("Additional parameters refined: " + paramList) - if (paramList) { - paramList.forEach((element) => { - params.push(element); - }); - } - return params; + // If token contains '=', split and clean value + const eqIndex = token.indexOf('='); + if (eqIndex !== -1) { + const key = token.substring(0, eqIndex); + let value = token.substring(eqIndex + 1); + if ( + (value.startsWith('"') && value.endsWith('"')) || + (value.startsWith("'") && value.endsWith("'")) + ) { + value = value.slice(1, -1); + } + return `${key}=${value}`; + } + + return token; + }); } + + getIndexOfBflNode(bflNodes: CxBFL[], resultNodes: any[]): number { const bflNodeNotFound = -1; diff --git a/src/tests/ScanTest.test.ts b/src/tests/ScanTest.test.ts index 6a4a73bd..9a719b72 100644 --- a/src/tests/ScanTest.test.ts +++ b/src/tests/ScanTest.test.ts @@ -61,6 +61,27 @@ describe("ScanCreate cases", () => { }) + it('prepareAdditionalParams splits complex parameters correctly', async () => { + // Create a wrapper instance to access the method + const wrapper: any = await cxWrapperFactory.createWrapper(cxScanConfig); + + // The raw string exactly as it will be passed from YAML + const raw = "--gradle-parameters='-Prepository.proxy.url=123 -Prepository.proxy.username=123 -Prepository.proxy.password=123' --log-level Debug"; + + // Invoke the method under test + const tokens: string[] = wrapper.prepareAdditionalParams(raw); + + // Verify that the output matches the expected tokens after the fix + expect(tokens).toEqual([ + "--gradle-parameters=-Prepository.proxy.url=123 -Prepository.proxy.username=123 -Prepository.proxy.password=123", + "--log-level", + "Debug" + ]); + }); + + + + it('ScanCreate Successful case no wait mode', async () => { const params = new Map(); params.set(CxParamType.PROJECT_NAME, "ast-cli-javascript-integration-nowait");