diff --git a/docs/Configuration.md b/docs/Configuration.md index d2da155e3..f786c3e79 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -26,6 +26,7 @@ * [GitHub](#github) * [GitLab](#gitlab) * [Azure DevOps](#azure) + * [Sarif](#sarif) * [Bitbucket (Cloud and Server)](#bitbucket) * [JSON Config Override](#json) * [BugTrackers](#bugtrackers) @@ -944,6 +945,23 @@ azure: | `zero-vulnerability-summary` | false | if true, will not comment in PR decoration any details for scans as vulnerabilities are zero. | **Note**: A service account is required with access to the repositories that are scanned, pull requests that are commented on, and Azure WorkItems that are created/updated. + +### Sarif +```yaml +sarif: + hassnippet: true +``` + +| Configuration | Default | Description | +|------------------------|---------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `hassnippet` |false | In Checkmarx CX-Flow, when the hasSnippet flag is set to true, the tool displays relevant code snippets under the "Region" section of the UI. These snippets provide a portion of the code where potential vulnerabilities are detected, giving developers context to better understand the issue. This feature helps in identifying the exact location of security concerns, streamlining the remediation process by offering precise, actionable insights directly within the code. | + +**Note**: Command line parameter for snippet is `--sarif.hassnippet=true` + + + + + ### Bitbucket (Cloud and Server) ```yaml bitbucket: diff --git a/src/main/java/com/checkmarx/flow/config/SarifProperties.java b/src/main/java/com/checkmarx/flow/config/SarifProperties.java index d27bc233a..0bb41d675 100644 --- a/src/main/java/com/checkmarx/flow/config/SarifProperties.java +++ b/src/main/java/com/checkmarx/flow/config/SarifProperties.java @@ -1,5 +1,8 @@ package com.checkmarx.flow.config; +import lombok.Getter; +import lombok.Setter; +import org.checkerframework.checker.index.qual.SearchIndexBottom; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import org.springframework.validation.annotation.Validated; @@ -21,6 +24,10 @@ public class SarifProperties { private String sarifSchema="https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json"; private String sarifVersion = "2.1.0"; private String semanticVersion = "1.0.0"; + + @Getter + @Setter + private boolean hasSnippet = false; private Map severityMap = new HashMap<>(); private Map securitySeverityMap = new HashMap<>(); diff --git a/src/main/java/com/checkmarx/flow/custom/SarifIssueTracker.java b/src/main/java/com/checkmarx/flow/custom/SarifIssueTracker.java index 634d410c2..5eee33af9 100644 --- a/src/main/java/com/checkmarx/flow/custom/SarifIssueTracker.java +++ b/src/main/java/com/checkmarx/flow/custom/SarifIssueTracker.java @@ -218,19 +218,33 @@ private void generateSastResults(ScanResults results, List r 1 : (Integer.valueOf(Optional.ofNullable(node.get("column")).orElse("1"))); /* Sarif format does not support 0 as column number */ Integer len = (Integer.valueOf(Optional.ofNullable(node.get("length")).orElse("1")) == 0) ? 1 : (Integer.valueOf(Optional.ofNullable(node.get("length")).orElse("1"))); /* Sarif format does not support 0 as column number */ + Region regioObj; + if(properties.isHasSnippet()){ + regioObj= Region.builder() + .startLine(line) + .endLine(line) + .startColumn(col) + .endColumn(col+len) + .snippet(StringUtils.isEmpty(node.get("snippet")) ? "Code Snippet" : node.get("snippet")) + .build(); + }else{ + regioObj= Region.builder() + .startLine(line) + .endLine(line) + .startColumn(col) + .endColumn(col+len) + .build(); + } + + locations.add(Location.builder() .physicalLocation(PhysicalLocation.builder() .artifactLocation(ArtifactLocation.builder() .uri(node.get("file")) .uriBaseId("%SRCROOT%") - //.index(pathNodeId-1) - .build()) - .region(Region.builder() - .startLine(line) - .endLine(line) - .startColumn(col) - .endColumn(col+len) + .index(pathNodeId-1) .build()) + .region(regioObj) .build()) .message(Message.builder() .text(StringUtils.isEmpty(node.get("snippet")) ? "Code Snippet" : node.get("snippet")).build()) @@ -250,6 +264,7 @@ private void generateSastResults(ScanResults results, List r List threadFlows = Lists.newArrayList(); threadFlows.add(ThreadFlow.builder() .locations(threadFlowLocations).build()); + List codeFlows = Lists.newArrayList(); codeFlows.add(CodeFlow.builder() .threadFlows(threadFlows).build()); @@ -452,6 +467,8 @@ public static class Region { public Integer startColumn; @JsonProperty("endColumn") public Integer endColumn; + @JsonProperty("snippet") + public String snippet; } @Data