From d637137986d77322564facb09d53972564baedcd Mon Sep 17 00:00:00 2001 From: Anjali Deore <200181980+cx-anjali-deore@users.noreply.github.com> Date: Wed, 21 Jan 2026 19:05:10 +0530 Subject: [PATCH 1/4] Changes related to ignore/revive functionality (AST-109612) (#457) * aimcp server changes * oss-realtime scanner changes * Create OssRealtimeVulnerability.java * Unify realtime scan wrappers; consolidate Secrets/IaC models; deprecate and stub obsolete result classes * Add ContainersRealtimeVulnerability model for containers realtime scan parsing * Add @JsonCreator constructor to OssRealtimeVulnerability for reliable Jackson deserialization * Refactoring package name and adding test for oss and mcp flag * Add integration tests for OSS, Container, and Secrets realtime scanners * Replaced Id to CVE in oss vulnerability * Changed variable from id to CVE as per OSS response * aimcp server changes * oss-realtime scanner changes * Create OssRealtimeVulnerability.java * Unify realtime scan wrappers; consolidate Secrets/IaC models; deprecate and stub obsolete result classes * Add ContainersRealtimeVulnerability model for containers realtime scan parsing * Add @JsonCreator constructor to OssRealtimeVulnerability for reliable Jackson deserialization * Refactoring package name and adding test for oss and mcp flag * Add integration tests for OSS, Container, and Secrets realtime scanners * Changed variable from id to CVE as per OSS response * Add maskedResult for secret remediation and change log level from INFO to DEBUG * Remove masked secrets functionality from codebase * Implemented mask cmd in java wrapper * Added fix for containerTool for IAC * Add telemetry AI command with full parameter support and tests * Add ignoredFilePath parameter to ScanAsca method * Removing ASCA ignore file path changes * Add ignoredFilePath parameter to ScanAsca realtime * - Changed ast cli version * added-isdev-isoneassist-function * - Adding engine check * - Added check for engine verification in path * - Added checks message for exception * - Added checks message for exception * passing-agent-name-jb-in-all-cmd * merge-fix * placed-cli-exe * Revert "Merge branch 'main' into feature/ASCA_IgnoreFile" This reverts commit 7a6d22942a68521452cc27428cd1711ebead0cd3, reversing changes made to 8b47577209497e9e8edb4af514d9ae12255e9438. * Update checkmarx-ast-cli.version * - Added fallback for macOS engine detection * - Refactored code as per review comments --------- Co-authored-by: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Co-authored-by: cx-anand-nandeshwar <73646287+cx-anand-nandeshwar@users.noreply.github.com> Co-authored-by: Hitesh Madgulkar <212497904+cx-hitesh-madgulkar@users.noreply.github.com> --- .../com/checkmarx/ast/wrapper/CxConfig.java | 6 +- .../checkmarx/ast/wrapper/CxConstants.java | 6 + .../com/checkmarx/ast/wrapper/CxWrapper.java | 131 +++++++++++++++--- .../com/checkmarx/ast/wrapper/Execution.java | 10 +- src/main/resources/cx-linux | 4 +- src/main/resources/cx-linux-arm | 2 +- src/main/resources/cx-mac | 4 +- src/main/resources/cx.exe | 4 +- src/test/java/com/checkmarx/ast/ScanTest.java | 19 ++- .../java/com/checkmarx/ast/TenantTest.java | 10 ++ 10 files changed, 158 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/checkmarx/ast/wrapper/CxConfig.java b/src/main/java/com/checkmarx/ast/wrapper/CxConfig.java index f23a5ea8..ab0a7329 100644 --- a/src/main/java/com/checkmarx/ast/wrapper/CxConfig.java +++ b/src/main/java/com/checkmarx/ast/wrapper/CxConfig.java @@ -16,7 +16,7 @@ public class CxConfig { private static final Pattern pattern = Pattern.compile("([^\"]\\S*|\".+?\")\\s*"); - + private String agentName; //JETBRAINS private String baseUri; private String baseAuthUri; private String tenant; @@ -66,6 +66,10 @@ List toArguments() { commands.add(CxConstants.BASE_AUTH_URI); commands.add(getBaseAuthUri()); } + if (getAgentName() != null && !getAgentName().isEmpty()) { + commands.add("--agent"); + commands.add(getAgentName()); + } if (getAdditionalParameters() != null) commands.addAll(getAdditionalParameters()); diff --git a/src/main/java/com/checkmarx/ast/wrapper/CxConstants.java b/src/main/java/com/checkmarx/ast/wrapper/CxConstants.java index 79f171c2..26a11dd6 100644 --- a/src/main/java/com/checkmarx/ast/wrapper/CxConstants.java +++ b/src/main/java/com/checkmarx/ast/wrapper/CxConstants.java @@ -75,6 +75,8 @@ public final class CxConstants { static final String SUB_CMD_TENANT = "tenant"; static final String IDE_SCANS_KEY = "scan.config.plugins.ideScans"; static final String AI_MCP_SERVER_KEY = "scan.config.plugins.aiMcpServer"; + static final String DEV_ASSIST_LICENSE_KEY = "scan.config.plugins.cxdevassist"; + static final String ONE_ASSIST_LICENSE_KEY = "scan.config.plugins.cxoneassist"; static final String IGNORED_FILE_PATH = "--ignored-file-path"; static final String SUB_CMD_OSS_REALTIME = "oss-realtime"; static final String SUB_CMD_IAC_REALTIME = "iac-realtime"; @@ -91,4 +93,8 @@ public final class CxConstants { static final String SCAN_TYPE_FLAG = "--scan-type"; static final String STATUS = "--status"; static final String TOTAL_COUNT = "--total-count"; + static final String DOCKER = "docker"; + static final String PODMAN = "podman"; + static final String PODMAN_FALLBACK_PATH = "/usr/local/bin/podman"; + static final String DOCKER_FALLBACK_PATH = "/usr/local/bin/docker"; } diff --git a/src/main/java/com/checkmarx/ast/wrapper/CxWrapper.java b/src/main/java/com/checkmarx/ast/wrapper/CxWrapper.java index 386133ad..1526d2b8 100644 --- a/src/main/java/com/checkmarx/ast/wrapper/CxWrapper.java +++ b/src/main/java/com/checkmarx/ast/wrapper/CxWrapper.java @@ -29,17 +29,22 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.File; import java.io.IOException; import java.nio.file.Files; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.UUID; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; + +import static com.checkmarx.ast.wrapper.Execution.*; public class CxWrapper { private static final CollectionType BRANCHES_TYPE = TypeFactory.defaultInstance() .constructCollectionType(List.class, String.class); + private static final String OS_LINUX = "linux"; + private static final String OS_WINDOWS = "windows"; + private static final String OS_MAC = "mac"; @NonNull private final CxConfig cxConfig; @@ -248,7 +253,7 @@ public List projectList(String filter) throws IOException, InterruptedE return Execution.executeCommand(withConfigArguments(arguments), logger, Project::listFromLine); } - public ScanResult ScanAsca(String fileSource, boolean ascaLatestVersion, String agent) throws IOException, InterruptedException, CxException { + public ScanResult ScanAsca(String fileSource, boolean ascaLatestVersion, String agent, String ignoredFilePath) throws IOException, InterruptedException, CxException { this.logger.info("Fetching ASCA scanResult"); List arguments = new ArrayList<>(); @@ -259,23 +264,27 @@ public ScanResult ScanAsca(String fileSource, boolean ascaLatestVersion, String if (ascaLatestVersion) { arguments.add(CxConstants.ASCA_LATEST_VERSION); } + if (StringUtils.isNotBlank(ignoredFilePath)) { + arguments.add(CxConstants.IGNORED_FILE_PATH); + arguments.add(ignoredFilePath); + } + - appendAgentToArguments(agent, arguments); return Execution.executeCommand(withConfigArguments(arguments), logger, ScanResult::fromLine, (args, ignored) -> (args.size() >= 3 && args.get(1).equals(CxConstants.CMD_SCAN) && args.get(2).equals(CxConstants.SUB_CMD_ASCA))); } - private static void appendAgentToArguments(String agent, List arguments) { - arguments.add(CxConstants.AGENT); - if (agent != null && !agent.isEmpty()){ - arguments.add(agent); - } - else{ - arguments.add("CLI-Java-Wrapper"); - } - } + // private static void appendAgentToArguments(String agent, List arguments) { + // arguments.add(CxConstants.AGENT); + // if (agent != null && !agent.isEmpty()){ + // arguments.add(agent); + // } + // else{ + // arguments.add("CLI-Java-Wrapper"); + // } + // } public List projectBranches(@NonNull UUID projectId, String filter) throws CxException, IOException, InterruptedException { @@ -345,10 +354,6 @@ public String results(@NonNull UUID scanId, ReportFormat reportFormat, String ag arguments.add(fileName); arguments.add(CxConstants.OUTPUT_PATH); arguments.add(tempDir); - if (agent != null) { - arguments.add(CxConstants.AGENT); - arguments.add(agent); - } return Execution.executeCommand(arguments, logger, tempDir, fileName + reportFormat.getExtension()); @@ -409,6 +414,68 @@ public KicsRealtimeResults kicsRealtimeScan(@NonNull String fileSources, String return Execution.executeCommand(withConfigArguments(arguments), logger, KicsRealtimeResults::fromLine); } + public String checkEngineExist(@NonNull String engineName) throws CxException, IOException, InterruptedException { + String osName = System.getProperty("os.name").toLowerCase(Locale.ENGLISH); + String osType=Execution.getOperatingSystemType(osName); + return this.checkEngine(engineName,osType); + } + + private String verifyEngineOnMAC(String engineName,Listarguments) throws CxException, IOException, InterruptedException { + Exception lastException = null; + String enginePath; + try{ + enginePath= Execution.executeCommand((arguments), logger, line->line); + return enginePath; + } catch (CxException | IOException e) { + lastException = e; + } + Path dockerPath = Paths.get(CxConstants.DOCKER_FALLBACK_PATH); + Path podmanPath = Paths.get(CxConstants.PODMAN_FALLBACK_PATH); + if (CxConstants.DOCKER.equalsIgnoreCase(engineName)) { + if (Files.isSymbolicLink(dockerPath)) { + return Files.readSymbolicLink(dockerPath).toAbsolutePath().toString(); + } + else { return dockerPath.toAbsolutePath().toString(); } + } + else if (CxConstants.PODMAN.equalsIgnoreCase(engineName)) { + if (Files.exists(podmanPath)) { + if (Files.isSymbolicLink(podmanPath)) { + return Files.readSymbolicLink(podmanPath).toAbsolutePath().toString(); + } + else{ + return podmanPath.toAbsolutePath().toString(); + } + } + } + throw new CxException( 1, "Engine '" + engineName + "' is not installed or not symlinked to /usr/local/bin." ); + } + + private String checkEngine(String engineName, String osType ) throws CxException, IOException, InterruptedException { + List arguments = new ArrayList<>(); + switch (osType){ + case OS_MAC: + arguments.add("/bin/sh"); + arguments.add("-c"); + arguments.add("command -v " + engineName); + return verifyEngineOnMAC(engineName,arguments); + case OS_WINDOWS: + case OS_LINUX: + arguments.add(engineName); + arguments.add("--version"); + try { + Execution.executeCommand(arguments, logger, line -> line); + return engineName; + } catch (CxException | IOException e) { + throw new CxException( + 1,engineName+" is not installed or is not accessible from the system PATH." + ); + } + default: + throw new IllegalArgumentException("Unsupported OS: " + osType); + } + + } + public T realtimeScan(@NonNull String subCommand, @NonNull String sourcePath, String containerTool, String ignoredFilePath, java.util.function.Function resultParser) throws IOException, InterruptedException, CxException { this.logger.info("Executing 'scan {}' command using the CLI.", subCommand); @@ -495,7 +562,7 @@ public List learnMore(String queryId) throws CxException, IOException public boolean ideScansEnabled() throws CxException, IOException, InterruptedException { List tenantSettings = tenantSettings(); - if (tenantSettings == null) { + if (tenantSettings == null || tenantSettings.isEmpty()) { throw new CxException(1, "Unable to parse tenant settings"); } return tenantSettings.stream() @@ -526,6 +593,28 @@ public List tenantSettings() throws CxException, IOException, Int return Execution.executeCommand(withConfigArguments(arguments), logger, TenantSetting::listFromLine); } + + + public boolean getTenantSetting(String key) throws CxException, IOException, InterruptedException { + List tenantSettings = tenantSettings(); + if (tenantSettings == null) { + throw new CxException(1, "Unable to parse tenant settings"); + } + return tenantSettings.stream() + .filter(t -> t.getKey().equals(key)) + .findFirst() + .map(t -> Boolean.parseBoolean(t.getValue())) + .orElse(false); + } + public boolean devAssistEnabled() throws CxException, IOException, InterruptedException { + return getTenantSetting(CxConstants.DEV_ASSIST_LICENSE_KEY); + + } + + public boolean oneAssistEnabled() throws CxException, IOException, InterruptedException { + return getTenantSetting(CxConstants.ONE_ASSIST_LICENSE_KEY); + } + public MaskResult maskSecrets(@NonNull String filePath) throws CxException, IOException, InterruptedException { List arguments = new ArrayList<>(); @@ -565,8 +654,6 @@ public String telemetryAIEvent(String aiProvider, String agent, String eventType arguments.add(CxConstants.SUB_CMD_TELEMETRY_AI); arguments.add(CxConstants.AI_PROVIDER); arguments.add(aiProvider); - arguments.add(CxConstants.AGENT); - arguments.add(agent); arguments.add(CxConstants.TYPE); arguments.add(eventType); arguments.add(CxConstants.SUB_TYPE); diff --git a/src/main/java/com/checkmarx/ast/wrapper/Execution.java b/src/main/java/com/checkmarx/ast/wrapper/Execution.java index c233ff2d..0a888ec0 100644 --- a/src/main/java/com/checkmarx/ast/wrapper/Execution.java +++ b/src/main/java/com/checkmarx/ast/wrapper/Execution.java @@ -1,5 +1,6 @@ package com.checkmarx.ast.wrapper; +import com.checkmarx.ast.kicsRealtimeResults.KicsRealtimeResults; import lombok.NonNull; import org.slf4j.Logger; @@ -12,10 +13,7 @@ import java.nio.file.Paths; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; -import java.util.Objects; +import java.util.*; import java.util.function.BiFunction; import java.util.function.Function; @@ -171,7 +169,7 @@ private static String detectBinaryName(@NonNull Logger logger) { return fileName; } - private static String getOperatingSystemType(String osName) { + public static String getOperatingSystemType(String osName) { if (osName.contains(OS_LINUX)) { return OS_LINUX; } else if (osName.contains(OS_WINDOWS)) { @@ -217,4 +215,6 @@ private static String md5(InputStream a) { } return md5; } + + } diff --git a/src/main/resources/cx-linux b/src/main/resources/cx-linux index 5bd22e20..f9909fd8 100755 --- a/src/main/resources/cx-linux +++ b/src/main/resources/cx-linux @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a2ec1fcc76f04596c976b5039ff8d755f3e6534f06ecf442cb8d22c4f3e8f9c8 -size 81055928 +oid sha256:2972512d55630f04f494fdf3543a3edf37906b970f5e29f58127ad27c40b652c +size 81023160 diff --git a/src/main/resources/cx-linux-arm b/src/main/resources/cx-linux-arm index fe820c8d..f17f02d5 100755 --- a/src/main/resources/cx-linux-arm +++ b/src/main/resources/cx-linux-arm @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:23dbe8b789c4c358023a98c15fdc57a468fff934804bbbfbb3ec5fa90d803c11 +oid sha256:ba3e45134be18e2093521df1f5e337c749e231fc926d5928815be4bbc68c4dd0 size 77332664 diff --git a/src/main/resources/cx-mac b/src/main/resources/cx-mac index 5423173f..52f3f40f 100755 --- a/src/main/resources/cx-mac +++ b/src/main/resources/cx-mac @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0a89e14ad8516e093625d3eff5713c83696d12494664c338839731f8dd8a79e -size 163042800 +oid sha256:7da05ed86e02142c414ebfa2ed335b71357f7d407291b9952bf5860c7bf78dab +size 162975392 diff --git a/src/main/resources/cx.exe b/src/main/resources/cx.exe index a71d0477..0341df07 100644 --- a/src/main/resources/cx.exe +++ b/src/main/resources/cx.exe @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f73d920a720bd8c3a6f4f234a77589e51611f07645c53baf1650396f77ed4f3 -size 83032512 +oid sha256:5fb41bc7c8d5b3db18f4626d9523fc626fd19c6f88e1bb078184e7b6e2532fed +size 82995136 diff --git a/src/test/java/com/checkmarx/ast/ScanTest.java b/src/test/java/com/checkmarx/ast/ScanTest.java index 5e31b337..a414281e 100644 --- a/src/test/java/com/checkmarx/ast/ScanTest.java +++ b/src/test/java/com/checkmarx/ast/ScanTest.java @@ -25,7 +25,7 @@ void testScanShow() throws Exception { @Test void testScanAsca_WhenFileWithVulnerabilitiesIsSentWithAgent_ReturnSuccessfulResponseWithCorrectValues() throws Exception { - ScanResult scanResult = wrapper.ScanAsca("src/test/resources/python-vul-file.py", true, "vscode"); + ScanResult scanResult = wrapper.ScanAsca("src/test/resources/python-vul-file.py", true, "vscode", null); // Assertions for the scan result Assertions.assertNotNull(scanResult.getRequestId(), "Request ID should not be null"); @@ -46,7 +46,7 @@ void testScanAsca_WhenFileWithVulnerabilitiesIsSentWithAgent_ReturnSuccessfulRes @Test void testScanAsca_WhenFileWithoutVulnerabilitiesIsSent_ReturnSuccessfulResponseWithCorrectValues() throws Exception { - ScanResult scanResult = wrapper.ScanAsca("src/test/resources/csharp-no-vul.cs", true, null); + ScanResult scanResult = wrapper.ScanAsca("src/test/resources/csharp-no-vul.cs", true, null, null); Assertions.assertNotNull(scanResult.getRequestId()); Assertions.assertTrue(scanResult.isStatus()); Assertions.assertNull(scanResult.getError()); @@ -55,12 +55,25 @@ void testScanAsca_WhenFileWithoutVulnerabilitiesIsSent_ReturnSuccessfulResponseW @Test void testScanAsca_WhenMissingFileExtension_ReturnFileExtensionIsRequiredFailure() throws Exception { - ScanResult scanResult = wrapper.ScanAsca("CODEOWNERS", true, null); + ScanResult scanResult = wrapper.ScanAsca("CODEOWNERS", true, null, null); Assertions.assertNotNull(scanResult.getRequestId()); Assertions.assertNotNull(scanResult.getError()); Assertions.assertEquals("The file name must have an extension.", scanResult.getError().getDescription()); } + @Test + void testScanAsca_WithIgnoreFilePath_ShouldWorkCorrectly() throws Exception { + String ignoreFile = "src/test/resources/ignored-packages.json"; + + // Test with ignore file - should not break the scanning process + ScanResult scanResult = wrapper.ScanAsca("src/test/resources/python-vul-file.py", true, "test-agent", ignoreFile); + + // Verify the scan completes successfully + Assertions.assertNotNull(scanResult.getRequestId(), "Request ID should not be null"); + Assertions.assertTrue(scanResult.isStatus(), "Status should be true"); + Assertions.assertNull(scanResult.getError(), "Error should be null when scan is successful"); + } + @Test void testScanList() throws Exception { List cxOutput = wrapper.scanList("limit=10"); diff --git a/src/test/java/com/checkmarx/ast/TenantTest.java b/src/test/java/com/checkmarx/ast/TenantTest.java index 7f49da16..91824f4e 100644 --- a/src/test/java/com/checkmarx/ast/TenantTest.java +++ b/src/test/java/com/checkmarx/ast/TenantTest.java @@ -24,4 +24,14 @@ void testAiMcpServerEnabled() throws Exception { boolean enabled = Assertions.assertDoesNotThrow(() -> wrapper.aiMcpServerEnabled()); Assertions.assertTrue(enabled, "AI MCP Server flag expected to be true"); } + + @Test + void testDevAssistEnabled() { + Assertions.assertDoesNotThrow(() -> wrapper.devAssistEnabled()); + } + + @Test + void testOneAssistEnabled() { + Assertions.assertDoesNotThrow(() -> wrapper.oneAssistEnabled()); + } } From d03675de1783da7551222129c0cd6a29c2157638 Mon Sep 17 00:00:00 2001 From: Anurag Dalke Date: Wed, 21 Jan 2026 19:37:25 +0530 Subject: [PATCH 2/4] updated latest CLI version artifact. (#458) --- README.md | 2 +- src/main/resources/cx-linux | 4 ++-- src/main/resources/cx-linux-arm | 2 +- src/main/resources/cx-mac | 4 ++-- src/main/resources/cx.exe | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 695249a3..d302f996 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@

- Logo + Logo

AST-CLI-JAVA-WRAPPER

diff --git a/src/main/resources/cx-linux b/src/main/resources/cx-linux index f9909fd8..5bd22e20 100755 --- a/src/main/resources/cx-linux +++ b/src/main/resources/cx-linux @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2972512d55630f04f494fdf3543a3edf37906b970f5e29f58127ad27c40b652c -size 81023160 +oid sha256:a2ec1fcc76f04596c976b5039ff8d755f3e6534f06ecf442cb8d22c4f3e8f9c8 +size 81055928 diff --git a/src/main/resources/cx-linux-arm b/src/main/resources/cx-linux-arm index f17f02d5..fe820c8d 100755 --- a/src/main/resources/cx-linux-arm +++ b/src/main/resources/cx-linux-arm @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba3e45134be18e2093521df1f5e337c749e231fc926d5928815be4bbc68c4dd0 +oid sha256:23dbe8b789c4c358023a98c15fdc57a468fff934804bbbfbb3ec5fa90d803c11 size 77332664 diff --git a/src/main/resources/cx-mac b/src/main/resources/cx-mac index 52f3f40f..5423173f 100755 --- a/src/main/resources/cx-mac +++ b/src/main/resources/cx-mac @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7da05ed86e02142c414ebfa2ed335b71357f7d407291b9952bf5860c7bf78dab -size 162975392 +oid sha256:a0a89e14ad8516e093625d3eff5713c83696d12494664c338839731f8dd8a79e +size 163042800 diff --git a/src/main/resources/cx.exe b/src/main/resources/cx.exe index 0341df07..a71d0477 100644 --- a/src/main/resources/cx.exe +++ b/src/main/resources/cx.exe @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5fb41bc7c8d5b3db18f4626d9523fc626fd19c6f88e1bb078184e7b6e2532fed -size 82995136 +oid sha256:3f73d920a720bd8c3a6f4f234a77589e51611f07645c53baf1650396f77ed4f3 +size 83032512 From edf04ef4e36eff0c89089c87dfd8228a830a01e1 Mon Sep 17 00:00:00 2001 From: Anurag Dalke Date: Thu, 5 Feb 2026 14:00:52 +0530 Subject: [PATCH 3/4] Update checkmarx-ast-cli binaries with 2.3.44 (#461) * Track Checkmarx CLI binaries with Git LFS * Update checkmarx-ast-cli to 2.3.44 --------- Co-authored-by: github-actions --- checkmarx-ast-cli.version | 2 +- src/main/resources/cx-linux | 4 ++-- src/main/resources/cx-linux-arm | 4 ++-- src/main/resources/cx-mac | 4 ++-- src/main/resources/cx.exe | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/checkmarx-ast-cli.version b/checkmarx-ast-cli.version index fcf4e515..9f56377c 100644 --- a/checkmarx-ast-cli.version +++ b/checkmarx-ast-cli.version @@ -1 +1 @@ -2.3.43 +2.3.44 diff --git a/src/main/resources/cx-linux b/src/main/resources/cx-linux index 5bd22e20..45b5e94a 100755 --- a/src/main/resources/cx-linux +++ b/src/main/resources/cx-linux @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a2ec1fcc76f04596c976b5039ff8d755f3e6534f06ecf442cb8d22c4f3e8f9c8 -size 81055928 +oid sha256:0d4fb757538955c9f03b442698f5d0eb8bf2c1e2929c80a390ee8b4d8b50b1a7 +size 81084600 diff --git a/src/main/resources/cx-linux-arm b/src/main/resources/cx-linux-arm index fe820c8d..5caaf774 100755 --- a/src/main/resources/cx-linux-arm +++ b/src/main/resources/cx-linux-arm @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:23dbe8b789c4c358023a98c15fdc57a468fff934804bbbfbb3ec5fa90d803c11 -size 77332664 +oid sha256:21e6f82b4ff43975385902eec3f37bd724316a96cef4354b7a397667698f4fa3 +size 77398200 diff --git a/src/main/resources/cx-mac b/src/main/resources/cx-mac index 5423173f..0201cf8d 100755 --- a/src/main/resources/cx-mac +++ b/src/main/resources/cx-mac @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a0a89e14ad8516e093625d3eff5713c83696d12494664c338839731f8dd8a79e -size 163042800 +oid sha256:1f2c1ddf46dbdd2df9c8ecb4ef89e737ea5037379cdb18862bbdbbe365eed1f8 +size 163091056 diff --git a/src/main/resources/cx.exe b/src/main/resources/cx.exe index a71d0477..10b897b4 100644 --- a/src/main/resources/cx.exe +++ b/src/main/resources/cx.exe @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3f73d920a720bd8c3a6f4f234a77589e51611f07645c53baf1650396f77ed4f3 -size 83032512 +oid sha256:d1bed011ccbb22466be3b6747f3fb2e4005be197718e8b9d9489c686645fecbc +size 83044800 From 14ef3adcaeb7f609c28db707c8033793de5440f5 Mon Sep 17 00:00:00 2001 From: Amol Mane <22643905+cx-amol-mane@users.noreply.github.com> Date: Fri, 6 Feb 2026 14:26:39 +0530 Subject: [PATCH 4/4] Add macOS Docker and Podman fallback paths to CxWrapper (#459) * Add macOS Docker and Podman fallback paths to CxWrapper * Refactor error handling for container engine accessibility in CxWrapper --- .../checkmarx/ast/wrapper/CxConstants.java | 10 ++ .../com/checkmarx/ast/wrapper/CxWrapper.java | 113 +++++++++++++++--- 2 files changed, 106 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/checkmarx/ast/wrapper/CxConstants.java b/src/main/java/com/checkmarx/ast/wrapper/CxConstants.java index 26a11dd6..ea2205ba 100644 --- a/src/main/java/com/checkmarx/ast/wrapper/CxConstants.java +++ b/src/main/java/com/checkmarx/ast/wrapper/CxConstants.java @@ -97,4 +97,14 @@ public final class CxConstants { static final String PODMAN = "podman"; static final String PODMAN_FALLBACK_PATH = "/usr/local/bin/podman"; static final String DOCKER_FALLBACK_PATH = "/usr/local/bin/docker"; + + // Additional Docker fallback paths for macOS + // These paths cover various Docker installation methods on macOS: + // - Homebrew on Apple Silicon: /opt/homebrew/bin/docker + // - Docker Desktop CLI tools: ~/.docker/bin/docker (resolved at runtime) + // - Docker.app bundle: /Applications/Docker.app/Contents/Resources/bin/docker + // - Rancher Desktop: ~/.rd/bin/docker (resolved at runtime) + static final String DOCKER_HOMEBREW_PATH = "/opt/homebrew/bin/docker"; + static final String DOCKER_APP_PATH = "/Applications/Docker.app/Contents/Resources/bin/docker"; + static final String PODMAN_HOMEBREW_PATH = "/opt/homebrew/bin/podman"; } diff --git a/src/main/java/com/checkmarx/ast/wrapper/CxWrapper.java b/src/main/java/com/checkmarx/ast/wrapper/CxWrapper.java index 1526d2b8..9e3c05f1 100644 --- a/src/main/java/com/checkmarx/ast/wrapper/CxWrapper.java +++ b/src/main/java/com/checkmarx/ast/wrapper/CxWrapper.java @@ -421,33 +421,112 @@ public String checkEngineExist(@NonNull String engineName) throws CxException, I } private String verifyEngineOnMAC(String engineName,Listarguments) throws CxException, IOException, InterruptedException { - Exception lastException = null; - String enginePath; + this.logger.debug("Verifying container engine '{}' on macOS", engineName); + + // First, try to find the engine via shell command (works when launched from terminal) try{ - enginePath= Execution.executeCommand((arguments), logger, line->line); - return enginePath; + String enginePath = Execution.executeCommand((arguments), logger, line->line); + if (enginePath != null && !enginePath.isEmpty()) { + this.logger.debug("Found engine '{}' via shell command: {}", engineName, enginePath); + return enginePath; + } } catch (CxException | IOException e) { - lastException = e; + this.logger.debug("Shell command lookup failed for '{}': {}", engineName, e.getMessage()); } - Path dockerPath = Paths.get(CxConstants.DOCKER_FALLBACK_PATH); - Path podmanPath = Paths.get(CxConstants.PODMAN_FALLBACK_PATH); + + // Build list of fallback paths based on engine type + // This handles the case when IntelliJ is launched via GUI (double-click) and doesn't inherit shell PATH + List fallbackPaths = new ArrayList<>(); if (CxConstants.DOCKER.equalsIgnoreCase(engineName)) { - if (Files.isSymbolicLink(dockerPath)) { - return Files.readSymbolicLink(dockerPath).toAbsolutePath().toString(); + fallbackPaths.add(CxConstants.DOCKER_FALLBACK_PATH); // /usr/local/bin/docker + fallbackPaths.add(CxConstants.DOCKER_HOMEBREW_PATH); // /opt/homebrew/bin/docker (Apple Silicon) + fallbackPaths.add(CxConstants.DOCKER_APP_PATH); // /Applications/Docker.app/Contents/Resources/bin/docker + // Add user home-based paths + String userHome = System.getProperty("user.home"); + if (userHome != null) { + fallbackPaths.add(userHome + "/.docker/bin/docker"); // Docker Desktop CLI + fallbackPaths.add(userHome + "/.rd/bin/docker"); // Rancher Desktop + } + } else if (CxConstants.PODMAN.equalsIgnoreCase(engineName)) { + fallbackPaths.add(CxConstants.PODMAN_FALLBACK_PATH); // /usr/local/bin/podman + fallbackPaths.add(CxConstants.PODMAN_HOMEBREW_PATH); // /opt/homebrew/bin/podman (Apple Silicon) + // Add user home-based paths + String userHome = System.getProperty("user.home"); + if (userHome != null) { + fallbackPaths.add(userHome + "/.local/bin/podman"); } - else { return dockerPath.toAbsolutePath().toString(); } } - else if (CxConstants.PODMAN.equalsIgnoreCase(engineName)) { - if (Files.exists(podmanPath)) { - if (Files.isSymbolicLink(podmanPath)) { - return Files.readSymbolicLink(podmanPath).toAbsolutePath().toString(); + + this.logger.debug("Checking {} fallback paths for engine '{}'", fallbackPaths.size(), engineName); + + // Try each fallback path + for (String pathStr : fallbackPaths) { + Path path = Paths.get(pathStr); + this.logger.debug("Checking fallback path: {}", pathStr); + + if (Files.exists(path)) { + String resolvedPath; + try { + if (Files.isSymbolicLink(path)) { + resolvedPath = Files.readSymbolicLink(path).toAbsolutePath().toString(); + this.logger.debug("Resolved symlink {} -> {}", pathStr, resolvedPath); + } else { + resolvedPath = path.toAbsolutePath().toString(); + } + + // Verify the engine is executable and works + if (verifyEngineExecutable(resolvedPath)) { + this.logger.info("Found working container engine '{}' at: {}", engineName, resolvedPath); + return resolvedPath; + } + } catch (IOException e) { + this.logger.debug("Failed to resolve path {}: {}", pathStr, e.getMessage()); } - else{ - return podmanPath.toAbsolutePath().toString(); + } else { + this.logger.debug("Path does not exist: {}", pathStr); + } + } + + throw new CxException( + 1, engineName + " is not installed or is not accessible from the system PATH." + ); + } + + /** + * Verifies that the engine at the given path is executable and responds to --version. + * + * @param enginePath the absolute path to the container engine executable + * @return true if the engine is working, false otherwise + */ + private boolean verifyEngineExecutable(String enginePath) { + try { + Path path = Paths.get(enginePath); + if (!Files.exists(path) || !Files.isExecutable(path)) { + this.logger.debug("Engine path '{}' is not executable", enginePath); + return false; + } + + // Run a quick version check to verify the engine works + ProcessBuilder pb = new ProcessBuilder(enginePath, "--version"); + pb.redirectErrorStream(true); + Process process = pb.start(); + boolean completed = process.waitFor(5, java.util.concurrent.TimeUnit.SECONDS); + + if (completed && process.exitValue() == 0) { + this.logger.debug("Engine at '{}' verified successfully", enginePath); + return true; + } else { + this.logger.debug("Engine at '{}' failed verification (exit code: {}, completed: {})", + enginePath, process.exitValue(), completed); + if (!completed) { + process.destroyForcibly(); } + return false; } + } catch (Exception e) { + this.logger.debug("Engine verification failed for '{}': {}", enginePath, e.getMessage()); + return false; } - throw new CxException( 1, "Engine '" + engineName + "' is not installed or not symlinked to /usr/local/bin." ); } private String checkEngine(String engineName, String osType ) throws CxException, IOException, InterruptedException {