diff --git a/pom.xml b/pom.xml
index f167102..9e8faa7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -34,7 +34,7 @@
com.fasterxml.jackson.core
jackson-databind
- 2.16.1
+ 2.21.1
org.projectlombok
diff --git a/src/main/java/com/checkmarx/ast/wrapper/CxConstants.java b/src/main/java/com/checkmarx/ast/wrapper/CxConstants.java
index ea2205b..6067544 100644
--- a/src/main/java/com/checkmarx/ast/wrapper/CxConstants.java
+++ b/src/main/java/com/checkmarx/ast/wrapper/CxConstants.java
@@ -43,6 +43,7 @@ public final class CxConstants {
static final String SCAN_ID = "--scan-id";
static final String PROJECT_ID = "--project-id";
static final String SIMILARITY_ID = "--similarity-id";
+ static final String VULNERABILITY_IDENTIFIERS = "--vulnerability-identifiers";
static final String QUERY_ID = "--query-id";
static final String STATE = "--state";
static final String COMMENT = "--comment";
diff --git a/src/main/java/com/checkmarx/ast/wrapper/CxWrapper.java b/src/main/java/com/checkmarx/ast/wrapper/CxWrapper.java
index 9e3c05f..6e73560 100644
--- a/src/main/java/com/checkmarx/ast/wrapper/CxWrapper.java
+++ b/src/main/java/com/checkmarx/ast/wrapper/CxWrapper.java
@@ -29,14 +29,12 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
-import static com.checkmarx.ast.wrapper.Execution.*;
public class CxWrapper {
@@ -170,12 +168,46 @@ public List triageShow(@NonNull UUID projectId, String similarityId,
arguments.add(similarityId);
arguments.add(CxConstants.SCAN_TYPE);
arguments.add(scanType);
-
arguments.addAll(jsonArguments());
return Execution.executeCommand(withConfigArguments(arguments), logger, Predicate::listFromLine, Predicate::validator);
}
+ /**
+ * SCA-specific triage show command.
+ */
+ public List triageScaShow(@NonNull UUID projectId, String vulnerabilities, String scanType)
+ throws IOException, InterruptedException, CxException {
+ this.logger.info("Executing 'triage show' command using the CLI for SCA.");
+
+ if (StringUtils.isBlank(vulnerabilities)) {
+ this.logger.warn("Skipping SCA triage show: no vulnerability identifiers were provided.");
+ return Collections.emptyList();
+ }
+
+ List arguments = new ArrayList<>();
+ arguments.add(CxConstants.CMD_TRIAGE);
+ arguments.add(CxConstants.SUB_CMD_SHOW);
+ arguments.add(CxConstants.SCAN_TYPE);
+ arguments.add(scanType);
+ arguments.add(CxConstants.VULNERABILITY_IDENTIFIERS);
+ arguments.add(vulnerabilities);
+ arguments.add(CxConstants.PROJECT_ID);
+ arguments.add(projectId.toString());
+ arguments.addAll(jsonArguments());
+
+ try {
+ return Execution.executeCommand(withConfigArguments(arguments), logger, Predicate::listFromLine, Predicate::validator);
+ } catch (CxException e) {
+ String message = e.getMessage();
+ if (message != null && message.contains("Failed to get SCA predicate result")) {
+ this.logger.info("No SCA triage history found for vulnerability identifiers: {}", vulnerabilities);
+ return Collections.emptyList();
+ }
+ throw e;
+ }
+ }
+
public List triageGetStates(boolean all) throws IOException, InterruptedException, CxException {
this.logger.info("Executing 'triage get-states' command using the CLI.");
@@ -224,6 +256,39 @@ public void triageUpdate(@NonNull UUID projectId, String similarityId, String sc
Execution.executeCommand(withConfigArguments(arguments), logger, line -> null);
}
+ /**
+ * SCA-specific triage update command.
+ */
+ public void triageScaUpdate(@NonNull UUID projectId,
+ String state,
+ String comment,
+ String vulnerabilities,
+ String scanType)
+ throws IOException, InterruptedException, CxException {
+ this.logger.info("Executing 'triage update' command using the CLI for SCA.");
+
+ if (StringUtils.isBlank(vulnerabilities)) {
+ this.logger.warn("Skipping SCA triage update: no vulnerability identifiers were provided.");
+ return;
+ }
+
+ List arguments = new ArrayList<>();
+ arguments.add(CxConstants.CMD_TRIAGE);
+ arguments.add(CxConstants.SUB_CMD_UPDATE);
+ arguments.add(CxConstants.SCAN_TYPE);
+ arguments.add(scanType);
+ arguments.add(CxConstants.VULNERABILITY_IDENTIFIERS);
+ arguments.add(vulnerabilities);
+ arguments.add(CxConstants.STATE);
+ arguments.add(state);
+ arguments.add(CxConstants.COMMENT);
+ arguments.add(comment);
+ arguments.add(CxConstants.PROJECT_ID);
+ arguments.add(projectId.toString());
+
+ Execution.executeCommand(withConfigArguments(arguments), logger, line -> null);
+ }
+
public Project projectShow(@NonNull UUID projectId) throws IOException, InterruptedException, CxException {
this.logger.info("Retrieving the details for project id: {}", projectId);
diff --git a/src/test/java/com/checkmarx/ast/PredicateTest.java b/src/test/java/com/checkmarx/ast/PredicateTest.java
index 7eb2f9c..ce1d05c 100644
--- a/src/test/java/com/checkmarx/ast/PredicateTest.java
+++ b/src/test/java/com/checkmarx/ast/PredicateTest.java
@@ -7,7 +7,7 @@
import com.checkmarx.ast.scan.Scan;
import com.checkmarx.ast.wrapper.CxConstants;
import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.Test;
import java.util.List;
@@ -52,4 +52,45 @@ void testGetStates() throws Exception {
List states = wrapper.triageGetStates(false);
Assertions.assertNotNull(states);
}
+
+ @Test
+ void testScaTriage() throws Exception {
+ // Automatically find a completed scan that has SCA results
+ List scans = wrapper.scanList("statuses=Completed");
+
+ Scan scaScan = null;
+ Result scaResult = null;
+
+ for (Scan scan : scans) {
+ Results results = wrapper.results(UUID.fromString(scan.getId()));
+ scaResult = results.getResults().stream()
+ .filter(res -> res.getType().equalsIgnoreCase("sca"))
+ .findFirst()
+ .orElse(null);
+ if (scaResult != null) {
+ scaScan = scan;
+ break;
+ }
+ }
+
+ Assumptions.assumeTrue(scaScan != null, "Skipping: no completed scan with SCA results found");
+
+ String packageIdentifier = scaResult.getData().getPackageIdentifier();
+ int firstDash = packageIdentifier.indexOf('-');
+ int lastDash = packageIdentifier.lastIndexOf('-');
+ String vulnerabilities = String.format("packagename=%s,packageversion=%s,vulnerabilityId=%s,packagemanager=%s",
+ packageIdentifier.substring(firstDash + 1, lastDash),
+ packageIdentifier.substring(lastDash + 1),
+ scaResult.getVulnerabilityDetails().getCveName(),
+ packageIdentifier.substring(0, firstDash).toLowerCase());
+
+ List predicates = wrapper.triageScaShow(UUID.fromString(scaScan.getProjectId()), vulnerabilities, scaResult.getType());
+ Assertions.assertNotNull(predicates);
+
+ try {
+ wrapper.triageScaUpdate(UUID.fromString(scaScan.getProjectId()), TO_VERIFY, "Edited via Java Wrapper", vulnerabilities, scaResult.getType());
+ } catch (Exception e) {
+ Assertions.fail("SCA triage update failed. Should not throw exception");
+ }
+ }
}