From 336213208ef40b12b330e18f9322136bc463048b Mon Sep 17 00:00:00 2001 From: Eyal Kapon Date: Sun, 1 Sep 2024 10:37:21 +0300 Subject: [PATCH 1/9] upgraded the AM version --- src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java b/src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java index 0908c6b2..558af867 100644 --- a/src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java +++ b/src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java @@ -58,7 +58,7 @@ public abstract class ScanBinaryExecutor { private static final int USER_NOT_ENTITLED = 31; private static final int NOT_SUPPORTED = 13; private static final String SCANNER_BINARY_NAME = "analyzerManager"; - private static final String SCANNER_BINARY_VERSION = "1.6.3"; + private static final String SCANNER_BINARY_VERSION = "1.8.14"; private static final String BINARY_DOWNLOAD_URL = "xsc-gen-exe-analyzer-manager-local/v1/" + SCANNER_BINARY_VERSION; private static final String DOWNLOAD_SCANNER_NAME = "analyzerManager.zip"; private static final String MINIMAL_XRAY_VERSION_SUPPORTED_FOR_ENTITLEMENT = "3.66.0"; From fc59dc46b7acac0753ec016f8ce1086ffa103f5c Mon Sep 17 00:00:00 2001 From: Eyal Kapon Date: Sun, 1 Sep 2024 15:12:28 +0300 Subject: [PATCH 2/9] cr fixes --- src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java b/src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java index 558af867..f8b6336c 100644 --- a/src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java +++ b/src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java @@ -124,6 +124,8 @@ String getBinaryDownloadURL(String externalResourcesRepo) { abstract List execute(ScanConfig.Builder inputFileBuilder, Runnable checkCanceled, ProgressIndicator indicator) throws IOException, InterruptedException, URISyntaxException; protected List execute(ScanConfig.Builder inputFileBuilder, List args, Runnable checkCanceled, ProgressIndicator indicator) throws IOException, InterruptedException { + log.warn("reading"); + log.warn(execute(inputFileBuilder, args, checkCanceled, false, indicator).toString()); return execute(inputFileBuilder, args, checkCanceled, false, indicator); } From ca8535e8e8c45efd058091ab8b7dee16834d8241 Mon Sep 17 00:00:00 2001 From: Eyal Kapon Date: Sun, 1 Sep 2024 15:14:27 +0300 Subject: [PATCH 3/9] cr fixes --- src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java b/src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java index f8b6336c..558af867 100644 --- a/src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java +++ b/src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java @@ -124,8 +124,6 @@ String getBinaryDownloadURL(String externalResourcesRepo) { abstract List execute(ScanConfig.Builder inputFileBuilder, Runnable checkCanceled, ProgressIndicator indicator) throws IOException, InterruptedException, URISyntaxException; protected List execute(ScanConfig.Builder inputFileBuilder, List args, Runnable checkCanceled, ProgressIndicator indicator) throws IOException, InterruptedException { - log.warn("reading"); - log.warn(execute(inputFileBuilder, args, checkCanceled, false, indicator).toString()); return execute(inputFileBuilder, args, checkCanceled, false, indicator); } From 4fa264372bec0e04f64afa67a8066602c2084ccf Mon Sep 17 00:00:00 2001 From: Eyal Kapon Date: Tue, 3 Sep 2024 16:04:08 +0300 Subject: [PATCH 4/9] grabbing the value of applicability from the sarif and checking by it. also added the right types --- build.gradle | 2 +- .../idea/inspections/JFrogSecurityWarning.java | 4 ++-- .../jfrog/ide/idea/scan/ScanBinaryExecutor.java | 3 ++- .../java/com/jfrog/ide/idea/scan/data/Rule.java | 8 ++++++++ .../jfrog/ide/idea/scan/data/RuleProperties.java | 15 +++++++++++++++ .../java/com/jfrog/ide/idea/scan/data/Run.java | 9 +++++++++ 6 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/jfrog/ide/idea/scan/data/RuleProperties.java diff --git a/build.gradle b/build.gradle index 082ab1c1..85db788d 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ import java.net.http.HttpResponse import java.nio.file.Paths plugins { - id "org.jetbrains.intellij" version "1.16.0" + id "org.jetbrains.intellij" version "1.17.0" id "java" id "maven-publish" id "de.undercouch.download" version "5.3.0" diff --git a/src/main/java/com/jfrog/ide/idea/inspections/JFrogSecurityWarning.java b/src/main/java/com/jfrog/ide/idea/inspections/JFrogSecurityWarning.java index ace09f18..37e8b60e 100644 --- a/src/main/java/com/jfrog/ide/idea/inspections/JFrogSecurityWarning.java +++ b/src/main/java/com/jfrog/ide/idea/inspections/JFrogSecurityWarning.java @@ -52,7 +52,7 @@ public JFrogSecurityWarning( this.codeFlows = codeFlows; } - public JFrogSecurityWarning(SarifResult result, SourceCodeScanType reporter) { + public JFrogSecurityWarning(SarifResult result, SourceCodeScanType reporter, Rule rule) { this(getFirstRegion(result).getStartLine() - 1, getFirstRegion(result).getStartColumn() - 1, getFirstRegion(result).getEndLine() - 1, @@ -62,7 +62,7 @@ public JFrogSecurityWarning(SarifResult result, SourceCodeScanType reporter) { result.getRuleId(), getFirstRegion(result).getSnippet().getText(), reporter, - !result.getKind().equals("pass"), + (!result.getKind().equals("pass") && (rule.getRuleProperties().map(properties -> !properties.getApplicability().equals("not_applicable")).orElse(true))), Severity.fromSarif(result.getSeverity()), convertCodeFlowsToFindingInfo(result.getCodeFlows()) ); diff --git a/src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java b/src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java index 558af867..2a2e984c 100644 --- a/src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java +++ b/src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java @@ -260,7 +260,8 @@ protected boolean isPackageTypeSupported(PackageManagerType type) { protected List parseOutputSarif(Path outputFile) throws IOException { Output output = getOutputObj(outputFile); List warnings = new ArrayList<>(); - output.getRuns().forEach(run -> run.getResults().stream().filter(SarifResult::isNotSuppressed).forEach(result -> warnings.add(new JFrogSecurityWarning(result, scanType)))); + + output.getRuns().forEach(run -> run.getResults().stream().filter(SarifResult::isNotSuppressed).forEach(result -> warnings.add(new JFrogSecurityWarning(result, scanType, run.getRuleFromRunById(result.getRuleId()))))); Optional run = output.getRuns().stream().findFirst(); if (run.isPresent()) { diff --git a/src/main/java/com/jfrog/ide/idea/scan/data/Rule.java b/src/main/java/com/jfrog/ide/idea/scan/data/Rule.java index c0088b0d..514580b6 100644 --- a/src/main/java/com/jfrog/ide/idea/scan/data/Rule.java +++ b/src/main/java/com/jfrog/ide/idea/scan/data/Rule.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; +import java.util.Optional; public class Rule { @@ -15,6 +16,9 @@ public class Rule { @JsonProperty("fullDescription") private Message fullDescription; + @JsonProperty("properties") + private RuleProperties properties; + public String getId() { return id; } @@ -43,6 +47,10 @@ public void setFullDescription(Message fullDescription) { this.fullDescription = fullDescription; } + public Optional getRuleProperties() { + return Optional.ofNullable(properties); + } + @Override public int hashCode() { return Objects.hash(id); diff --git a/src/main/java/com/jfrog/ide/idea/scan/data/RuleProperties.java b/src/main/java/com/jfrog/ide/idea/scan/data/RuleProperties.java new file mode 100644 index 00000000..cae90d1d --- /dev/null +++ b/src/main/java/com/jfrog/ide/idea/scan/data/RuleProperties.java @@ -0,0 +1,15 @@ +package com.jfrog.ide.idea.scan.data; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; + +@Getter +public class RuleProperties { + + @JsonProperty("conclusion") + private String conclusion; + + @JsonProperty("applicability") + private String applicability; + +} diff --git a/src/main/java/com/jfrog/ide/idea/scan/data/Run.java b/src/main/java/com/jfrog/ide/idea/scan/data/Run.java index 53e36272..683fec56 100644 --- a/src/main/java/com/jfrog/ide/idea/scan/data/Run.java +++ b/src/main/java/com/jfrog/ide/idea/scan/data/Run.java @@ -39,6 +39,15 @@ public List getResults() { return results; } + public Rule getRuleFromRunById(String ruleId) { + List rules = this.getTool().getDriver().getRules(); + return rules.stream() + .filter(rule -> rule.getId().equals(ruleId)) + .findFirst() + .orElseThrow(() -> new NoSuchElementException("No rule found with id: " + ruleId)); + + } + public void setResults(List results) { this.results = results; } From 6719ecbbb6bf17c38b91129f8d40f84a21600761 Mon Sep 17 00:00:00 2001 From: Eyal Kapon Date: Tue, 3 Sep 2024 16:45:17 +0300 Subject: [PATCH 5/9] added test --- .../ide/idea/scan/ScanBinaryExecutorTest.java | 15 +- .../sourceCode/not_applic_kind_pass.sarif | 165 ++++++++++++++++++ 2 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 src/test/resources/sourceCode/not_applic_kind_pass.sarif diff --git a/src/test/java/com/jfrog/ide/idea/scan/ScanBinaryExecutorTest.java b/src/test/java/com/jfrog/ide/idea/scan/ScanBinaryExecutorTest.java index 16481044..d3d92125 100644 --- a/src/test/java/com/jfrog/ide/idea/scan/ScanBinaryExecutorTest.java +++ b/src/test/java/com/jfrog/ide/idea/scan/ScanBinaryExecutorTest.java @@ -23,7 +23,7 @@ public class ScanBinaryExecutorTest extends TestCase { private final ScanBinaryExecutor scanner = new ApplicabilityScannerExecutor(new NullLog()); private final Path SIMPLE_OUTPUT = new File("src/test/resources/sourceCode/simple_output.sarif").toPath(); private final Path NOT_APPLIC_OUTPUT = new File("src/test/resources/sourceCode/not_applic_output.sarif").toPath(); - + private final Path NOT_APPLIC_KIND_PASS_OUTPUT = new File("src/test/resources/sourceCode/not_applic_kind_pass.sarif").toPath(); public void testInputBuilder() throws IOException { ScanConfig.Builder inputFileBuilder = new ScanConfig.Builder(); Path inputPath = null; @@ -85,6 +85,19 @@ public void testSarifParserNotApplicResults() throws IOException { assertFalse(parsedOutput.get(3).isApplicable()); } + public void testSarifParserNotApplicResultsButKindPass() throws IOException { + List parsedOutput = scanner.parseOutputSarif(NOT_APPLIC_KIND_PASS_OUTPUT); + assertEquals(5, parsedOutput.size()); + // 1 known applicable results (code evidence returned) + assertEquals("applic_CVE-2022-25878", parsedOutput.get(0).getRuleID()); + assertTrue(parsedOutput.get(0).isApplicable()); + // 2 known no-applicable results (have a scanner but no code evidence returned) + assertEquals("applic_CVE-2021-25878", parsedOutput.get(2).getRuleID()); + assertFalse(parsedOutput.get(2).isApplicable()); + assertEquals("applic_CVE-2022-29019", parsedOutput.get(3).getRuleID()); + assertFalse(parsedOutput.get(3).isApplicable()); + } + public void testGetBinaryDownloadURL() { final String externalRepoName = "test-releases-repo"; final String expectedExternalRepoUrl = "test-releases-repo/artifactory/xsc-gen-exe-analyzer-manager-local/"; diff --git a/src/test/resources/sourceCode/not_applic_kind_pass.sarif b/src/test/resources/sourceCode/not_applic_kind_pass.sarif new file mode 100644 index 00000000..5bcd82ab --- /dev/null +++ b/src/test/resources/sourceCode/not_applic_kind_pass.sarif @@ -0,0 +1,165 @@ +{ + "runs": [ + { + "tool": { + "driver": { + "name": "JFrog Applicability Scanner", + "rules": [ + { + "id": "applic_CVE-2021-3807", + "fullDescription": { + "text": "The scanner checks whether the vulnerable function `ansi-regex` is called.", + "markdown": "The scanner checks whether the vulnerable function `ansi-regex` is called." + }, + "name": "CVE-2021-3807", + "shortDescription": { + "text": "Scanner for CVE-2021-3807" + }, + "properties": { + "applicability": "not_applicable", + "conclusion": "positive", + "security-severity": "6.9" + } + }, + { + "id": "applic_CVE-2021-3918", + "fullDescription": { + "text": "The scanner checks whether any of the following vulnerable functions are called:\n\n* `util.setProperty` with external input to its 2nd (`path`) or 3rd (`value`) arguments.\n* `ReflectionObject.setParsedOption` with external input to its 2nd (`name`) or 3rd (`value`) arguments.\n* `parse` with external input to its 1st (`source`) argument.\n* `load`\n* `loadSync`\n\nThe scanner also checks whether the `Object.freeze()` remediation is not present.", + "markdown": "The scanner checks whether any of the following vulnerable functions are called:\n\n* `util.setProperty` with external input to its 2nd (`path`) or 3rd (`value`) arguments.\n* `ReflectionObject.setParsedOption` with external input to its 2nd (`name`) or 3rd (`value`) arguments.\n* `parse` with external input to its 1st (`source`) argument.\n* `load`\n* `loadSync`\n\nThe scanner also checks whether the `Object.freeze()` remediation is not present." + }, + "name": "CVE-2021-3918", + "shortDescription": { + "text": "Scanner for CVE-2021-3918" + }, + "properties": { + "applicability": "not_applicable", + "conclusion": "positive", + "security-severity": "6.9" + } + }, + { + "id": "applic_CVE-2022-25878", + "name": "CVE-2022-25878", + "shortDescription": { + "text": "Scanner for CVE-2022-25878" + }, + "fullDescription": { + "text": "The scanner checks whether any of the following vulnerable functions are called:\n\n* `util.setProperty` with external input to its 2nd (`path`) or 3rd (`value`) arguments.\n* `ReflectionObject.setParsedOption` with external input to its 2nd (`name`) or 3rd (`value`) arguments.\n* `parse` with external input to its 1st (`source`) argument.\n* `load`\n* `loadSync`\n\nThe scanner also checks whether the `Object.freeze()` remediation is not present.", + "markdown": "The scanner checks whether any of the following vulnerable functions are called:\n\n* `util.setProperty` with external input to its 2nd (`path`) or 3rd (`value`) arguments.\n* `ReflectionObject.setParsedOption` with external input to its 2nd (`name`) or 3rd (`value`) arguments.\n* `parse` with external input to its 1st (`source`) argument.\n* `load`\n* `loadSync`\n\nThe scanner also checks whether the `Object.freeze()` remediation is not present." + }, + "properties": { + "applicability": "applicable", + "conclusion": "positive", + "security-severity": "6.9" + } + } + ], + "version": "APPLIC_SCANNERv0.2.3" + } + }, + "invocations": [ + { + "executionSuccessful": true, + "arguments": [ + "ca_scanner/applicability_scanner", + "scan", + "aplic_config.yaml" + ], + "workingDirectory": { + "uri": "file:///Users/user/.jfrog-vscode-extension/issues/analyzerManager" + } + } + ], + "results": [ + { + "message": { + "text": "Prototype pollution `Object.freeze` remediation was not detected, The vulnerable function protobufjs.parse is called with external input, The vulnerable function protobufjs.load(Sync) is called" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "file:///examples/applic-demo/../applic-demo/index.js" + }, + "region": { + "endColumn": 18, + "endLine": 21, + "snippet": { + "text": "protobuf.parse(p)" + }, + "startColumn": 1, + "startLine": 21 + } + } + } + ], + "ruleId": "applic_CVE-2022-25878" + }, + { + "message": { + "text": "Prototype pollution `Object.freeze` remediation was not detected, The vulnerable function protobufjs.parse is called with external input, The vulnerable function protobufjs.load(Sync) is called" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "file:///examples/applic-demo/../applic-demo/index.js" + }, + "region": { + "endColumn": 74, + "endLine": 23, + "snippet": { + "text": "protobuf.load(\"/path/to/untrusted.proto\", function(err, root) { return })" + }, + "startColumn": 1, + "startLine": 23 + } + } + } + ], + "ruleId": "applic_CVE-2022-25878" + }, + { + "message": { + "text": "Some remediation for not applicable issue." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "file:///examples/applic-demo/../applic-demo/index.js" + }, + "region": { + "endColumn": 1, + "endLine": 23, + "snippet": { + "text": "protobuf.load(\"/path/to/untrusted.proto\", function(err, root) { return })" + }, + "startColumn": 1, + "startLine": 1 + } + } + } + ], + "ruleId": "applic_CVE-2021-3807" + }, + { + "message": { + "text": "The scanner checks whether the vulnerable function `ansi-regex` is called." + }, + "kind": "pass", + "ruleId": "applic_CVE-2021-3807" + }, + { + "message": { + "text": "The scanner checks whether any of the following vulnerable functions are called:\n\n* `json-schema.validate` with external input to its 1st (`instance`) argument.\n* `json-schema.checkPropertyChange` with external input to its 2nd (`schema`) argument." + }, + "kind": "pass", + "ruleId": "applic_CVE-2021-3918" + } + ] + } + ], + "version": "2.1.0", + "$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json" +} \ No newline at end of file From 87e54806dab415358b4f57cc76c0abc31fea77fc Mon Sep 17 00:00:00 2001 From: Eyal Kapon Date: Tue, 3 Sep 2024 17:41:10 +0300 Subject: [PATCH 6/9] added test and fixed the logic --- .../inspections/JFrogSecurityWarning.java | 3 +- .../com/jfrog/ide/idea/scan/data/Driver.java | 8 + .../com/jfrog/ide/idea/scan/data/Run.java | 7 +- .../ide/idea/scan/ScanBinaryExecutorTest.java | 16 +- .../applicable_kind_pass_output.sarif | 140 +++++++++++++++ .../sourceCode/not_applic_kind_pass.sarif | 165 ------------------ 6 files changed, 161 insertions(+), 178 deletions(-) create mode 100644 src/test/resources/sourceCode/applicable_kind_pass_output.sarif delete mode 100644 src/test/resources/sourceCode/not_applic_kind_pass.sarif diff --git a/src/main/java/com/jfrog/ide/idea/inspections/JFrogSecurityWarning.java b/src/main/java/com/jfrog/ide/idea/inspections/JFrogSecurityWarning.java index 37e8b60e..110b6bda 100644 --- a/src/main/java/com/jfrog/ide/idea/inspections/JFrogSecurityWarning.java +++ b/src/main/java/com/jfrog/ide/idea/inspections/JFrogSecurityWarning.java @@ -62,7 +62,7 @@ public JFrogSecurityWarning(SarifResult result, SourceCodeScanType reporter, Rul result.getRuleId(), getFirstRegion(result).getSnippet().getText(), reporter, - (!result.getKind().equals("pass") && (rule.getRuleProperties().map(properties -> !properties.getApplicability().equals("not_applicable")).orElse(true))), + (!result.getKind().equals("pass") && (rule.getRuleProperties().map(properties -> properties.getApplicability().equals("applicable")).orElse(true))), Severity.fromSarif(result.getSeverity()), convertCodeFlowsToFindingInfo(result.getCodeFlows()) ); @@ -114,3 +114,4 @@ private static String uriToPath(String path) { return Paths.get(URI.create(path)).toString(); } } + diff --git a/src/main/java/com/jfrog/ide/idea/scan/data/Driver.java b/src/main/java/com/jfrog/ide/idea/scan/data/Driver.java index 74a1dcf7..22a4347b 100644 --- a/src/main/java/com/jfrog/ide/idea/scan/data/Driver.java +++ b/src/main/java/com/jfrog/ide/idea/scan/data/Driver.java @@ -48,4 +48,12 @@ public boolean equals(Object other) { return (Objects.equals(this.name, rhs.name) && (CollectionUtils.isEqualCollection(this.rules, rhs.rules))); } + public Rule getRuleById(String ruleId) { + return rules.stream() + .filter(rule -> rule.getId().equals(ruleId)) + .findFirst() + .orElseThrow(() -> new IndexOutOfBoundsException("Rule not found")); + } + + } diff --git a/src/main/java/com/jfrog/ide/idea/scan/data/Run.java b/src/main/java/com/jfrog/ide/idea/scan/data/Run.java index 683fec56..71b32e76 100644 --- a/src/main/java/com/jfrog/ide/idea/scan/data/Run.java +++ b/src/main/java/com/jfrog/ide/idea/scan/data/Run.java @@ -40,12 +40,7 @@ public List getResults() { } public Rule getRuleFromRunById(String ruleId) { - List rules = this.getTool().getDriver().getRules(); - return rules.stream() - .filter(rule -> rule.getId().equals(ruleId)) - .findFirst() - .orElseThrow(() -> new NoSuchElementException("No rule found with id: " + ruleId)); - + return this.getTool().getDriver().getRuleById(ruleId); } public void setResults(List results) { diff --git a/src/test/java/com/jfrog/ide/idea/scan/ScanBinaryExecutorTest.java b/src/test/java/com/jfrog/ide/idea/scan/ScanBinaryExecutorTest.java index d3d92125..918ab813 100644 --- a/src/test/java/com/jfrog/ide/idea/scan/ScanBinaryExecutorTest.java +++ b/src/test/java/com/jfrog/ide/idea/scan/ScanBinaryExecutorTest.java @@ -23,7 +23,7 @@ public class ScanBinaryExecutorTest extends TestCase { private final ScanBinaryExecutor scanner = new ApplicabilityScannerExecutor(new NullLog()); private final Path SIMPLE_OUTPUT = new File("src/test/resources/sourceCode/simple_output.sarif").toPath(); private final Path NOT_APPLIC_OUTPUT = new File("src/test/resources/sourceCode/not_applic_output.sarif").toPath(); - private final Path NOT_APPLIC_KIND_PASS_OUTPUT = new File("src/test/resources/sourceCode/not_applic_kind_pass.sarif").toPath(); + private final Path APPLIC_KIND_PASS_OUTPUT = new File("src/test/resources/sourceCode/applicable_kind_pass_output.sarif").toPath(); public void testInputBuilder() throws IOException { ScanConfig.Builder inputFileBuilder = new ScanConfig.Builder(); Path inputPath = null; @@ -85,12 +85,14 @@ public void testSarifParserNotApplicResults() throws IOException { assertFalse(parsedOutput.get(3).isApplicable()); } - public void testSarifParserNotApplicResultsButKindPass() throws IOException { - List parsedOutput = scanner.parseOutputSarif(NOT_APPLIC_KIND_PASS_OUTPUT); - assertEquals(5, parsedOutput.size()); - // 1 known applicable results (code evidence returned) + public void testSarifParserApplicResultsWithKindPass() throws IOException { + List parsedOutput = scanner.parseOutputSarif(APPLIC_KIND_PASS_OUTPUT); + assertEquals(4, parsedOutput.size()); + // 2 known applicable results (code evidence returned) assertEquals("applic_CVE-2022-25878", parsedOutput.get(0).getRuleID()); - assertTrue(parsedOutput.get(0).isApplicable()); + assertFalse(parsedOutput.get(0).isApplicable()); + assertEquals("CVE-2022-25978", parsedOutput.get(1).getRuleID()); + assertTrue(parsedOutput.get(1).isApplicable()); // 2 known no-applicable results (have a scanner but no code evidence returned) assertEquals("applic_CVE-2021-25878", parsedOutput.get(2).getRuleID()); assertFalse(parsedOutput.get(2).isApplicable()); @@ -98,6 +100,8 @@ public void testSarifParserNotApplicResultsButKindPass() throws IOException { assertFalse(parsedOutput.get(3).isApplicable()); } + + public void testGetBinaryDownloadURL() { final String externalRepoName = "test-releases-repo"; final String expectedExternalRepoUrl = "test-releases-repo/artifactory/xsc-gen-exe-analyzer-manager-local/"; diff --git a/src/test/resources/sourceCode/applicable_kind_pass_output.sarif b/src/test/resources/sourceCode/applicable_kind_pass_output.sarif new file mode 100644 index 00000000..97b8094a --- /dev/null +++ b/src/test/resources/sourceCode/applicable_kind_pass_output.sarif @@ -0,0 +1,140 @@ +{ + "runs": [ + { + "tool": { + "driver": { + "name": "JFrog Applicability Scanner", + "rules": [ + { + "id": "applic_CVE-2022-25878", + "properties": { + "conclusion": "positive", + "applicability": "not_applicable" + }, + "fullDescription": { + "text": "The scanner checks whether the vulnerable function `pem.Decode` is called.", + "markdown": "The scanner checks whether the vulnerable function `pem.Decode` is called." + }, + "shortDescription": { + "text": "Scanner for CVE-2020-28502" + } + }, + { + "id": "CVE-2022-25978", + "properties": { + "conclusion": "negative", + "applicability": "applicable" + }, + "fullDescription": { + "text": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used.", + "markdown": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used." + }, + "shortDescription": { + "text": "Scanner for CVE-2020-5310" + } + }, + { + "id": "applic_CVE-2021-25878", + "fullDescription": { + "text": "The scanner checks whether the vulnerable function `pem.Decode` is called.", + "markdown": "The scanner checks whether the vulnerable function `pem.Decode` is called." + }, + "shortDescription": { + "text": "Scanner for CVE-2020-28502" + } + }, + { + "id": "applic_CVE-2022-29019", + "fullDescription": { + "text": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used.", + "markdown": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used." + }, + "shortDescription": { + "text": "Scanner for CVE-2020-5310" + } + } + + ], + "version": "APPLIC_SCANNERv0.2.0" + } + }, + "invocations": [ + { + "executionSuccessful": true, + "arguments": [ + "scan" + ], + "workingDirectory": { + "uri": "" + } + } + ], + "results": [ + { + "message": { + "text": "The vulnerable function protobufjs.load is called" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "file:///examples/applic-demo/index.js" + }, + "region": { + "endColumn": 17, + "endLine": 20, + "snippet": { + "text": "protobuf.parse(p)" + }, + "startColumn": 0, + "startLine": 20 + } + } + } + ], + "ruleId": "applic_CVE-2022-25878" + }, + { + "message": { + "text": "The vulnerable function protobufjs.parse is called." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "file:///examples/applic-demo/index.js" + }, + "region": { + "endColumn": 73, + "endLine": 22, + "snippet": { + "text": "protobuf.load(\"/path/to/untrusted.proto\", function(err, root) { return })" + }, + "startColumn": 0, + "startLine": 18 + } + } + } + ], + "ruleId": "CVE-2022-25978" + }, + { + "message": { + "text": "The scanner checks whether the vulnerable function `ansi-regex` is called." + }, + "kind": "pass", + "ruleId": "applic_CVE-2021-25878" + }, + { + "message": { + "text": "The scanner checks whether the vulnerable function `ansi-regex` is called." + }, + "kind": "pass", + "ruleId": "applic_CVE-2022-29019" + } + ] + } + ], + "version": "2.1.0", + "$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json" +} \ No newline at end of file diff --git a/src/test/resources/sourceCode/not_applic_kind_pass.sarif b/src/test/resources/sourceCode/not_applic_kind_pass.sarif deleted file mode 100644 index 5bcd82ab..00000000 --- a/src/test/resources/sourceCode/not_applic_kind_pass.sarif +++ /dev/null @@ -1,165 +0,0 @@ -{ - "runs": [ - { - "tool": { - "driver": { - "name": "JFrog Applicability Scanner", - "rules": [ - { - "id": "applic_CVE-2021-3807", - "fullDescription": { - "text": "The scanner checks whether the vulnerable function `ansi-regex` is called.", - "markdown": "The scanner checks whether the vulnerable function `ansi-regex` is called." - }, - "name": "CVE-2021-3807", - "shortDescription": { - "text": "Scanner for CVE-2021-3807" - }, - "properties": { - "applicability": "not_applicable", - "conclusion": "positive", - "security-severity": "6.9" - } - }, - { - "id": "applic_CVE-2021-3918", - "fullDescription": { - "text": "The scanner checks whether any of the following vulnerable functions are called:\n\n* `util.setProperty` with external input to its 2nd (`path`) or 3rd (`value`) arguments.\n* `ReflectionObject.setParsedOption` with external input to its 2nd (`name`) or 3rd (`value`) arguments.\n* `parse` with external input to its 1st (`source`) argument.\n* `load`\n* `loadSync`\n\nThe scanner also checks whether the `Object.freeze()` remediation is not present.", - "markdown": "The scanner checks whether any of the following vulnerable functions are called:\n\n* `util.setProperty` with external input to its 2nd (`path`) or 3rd (`value`) arguments.\n* `ReflectionObject.setParsedOption` with external input to its 2nd (`name`) or 3rd (`value`) arguments.\n* `parse` with external input to its 1st (`source`) argument.\n* `load`\n* `loadSync`\n\nThe scanner also checks whether the `Object.freeze()` remediation is not present." - }, - "name": "CVE-2021-3918", - "shortDescription": { - "text": "Scanner for CVE-2021-3918" - }, - "properties": { - "applicability": "not_applicable", - "conclusion": "positive", - "security-severity": "6.9" - } - }, - { - "id": "applic_CVE-2022-25878", - "name": "CVE-2022-25878", - "shortDescription": { - "text": "Scanner for CVE-2022-25878" - }, - "fullDescription": { - "text": "The scanner checks whether any of the following vulnerable functions are called:\n\n* `util.setProperty` with external input to its 2nd (`path`) or 3rd (`value`) arguments.\n* `ReflectionObject.setParsedOption` with external input to its 2nd (`name`) or 3rd (`value`) arguments.\n* `parse` with external input to its 1st (`source`) argument.\n* `load`\n* `loadSync`\n\nThe scanner also checks whether the `Object.freeze()` remediation is not present.", - "markdown": "The scanner checks whether any of the following vulnerable functions are called:\n\n* `util.setProperty` with external input to its 2nd (`path`) or 3rd (`value`) arguments.\n* `ReflectionObject.setParsedOption` with external input to its 2nd (`name`) or 3rd (`value`) arguments.\n* `parse` with external input to its 1st (`source`) argument.\n* `load`\n* `loadSync`\n\nThe scanner also checks whether the `Object.freeze()` remediation is not present." - }, - "properties": { - "applicability": "applicable", - "conclusion": "positive", - "security-severity": "6.9" - } - } - ], - "version": "APPLIC_SCANNERv0.2.3" - } - }, - "invocations": [ - { - "executionSuccessful": true, - "arguments": [ - "ca_scanner/applicability_scanner", - "scan", - "aplic_config.yaml" - ], - "workingDirectory": { - "uri": "file:///Users/user/.jfrog-vscode-extension/issues/analyzerManager" - } - } - ], - "results": [ - { - "message": { - "text": "Prototype pollution `Object.freeze` remediation was not detected, The vulnerable function protobufjs.parse is called with external input, The vulnerable function protobufjs.load(Sync) is called" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "file:///examples/applic-demo/../applic-demo/index.js" - }, - "region": { - "endColumn": 18, - "endLine": 21, - "snippet": { - "text": "protobuf.parse(p)" - }, - "startColumn": 1, - "startLine": 21 - } - } - } - ], - "ruleId": "applic_CVE-2022-25878" - }, - { - "message": { - "text": "Prototype pollution `Object.freeze` remediation was not detected, The vulnerable function protobufjs.parse is called with external input, The vulnerable function protobufjs.load(Sync) is called" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "file:///examples/applic-demo/../applic-demo/index.js" - }, - "region": { - "endColumn": 74, - "endLine": 23, - "snippet": { - "text": "protobuf.load(\"/path/to/untrusted.proto\", function(err, root) { return })" - }, - "startColumn": 1, - "startLine": 23 - } - } - } - ], - "ruleId": "applic_CVE-2022-25878" - }, - { - "message": { - "text": "Some remediation for not applicable issue." - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "file:///examples/applic-demo/../applic-demo/index.js" - }, - "region": { - "endColumn": 1, - "endLine": 23, - "snippet": { - "text": "protobuf.load(\"/path/to/untrusted.proto\", function(err, root) { return })" - }, - "startColumn": 1, - "startLine": 1 - } - } - } - ], - "ruleId": "applic_CVE-2021-3807" - }, - { - "message": { - "text": "The scanner checks whether the vulnerable function `ansi-regex` is called." - }, - "kind": "pass", - "ruleId": "applic_CVE-2021-3807" - }, - { - "message": { - "text": "The scanner checks whether any of the following vulnerable functions are called:\n\n* `json-schema.validate` with external input to its 1st (`instance`) argument.\n* `json-schema.checkPropertyChange` with external input to its 2nd (`schema`) argument." - }, - "kind": "pass", - "ruleId": "applic_CVE-2021-3918" - } - ] - } - ], - "version": "2.1.0", - "$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json" -} \ No newline at end of file From 72e3e72fff8d09b782b9bd40e94c53c087c438a1 Mon Sep 17 00:00:00 2001 From: Eyal Kapon Date: Thu, 5 Sep 2024 11:25:11 +0300 Subject: [PATCH 7/9] cr fixes --- build.gradle | 2 +- .../inspections/JFrogSecurityWarning.java | 12 ++++- .../com/jfrog/ide/idea/scan/data/Rule.java | 5 ++ .../ide/idea/scan/ScanBinaryExecutorTest.java | 21 +++++--- .../applicable_kind_pass_output.sarif | 54 ++++++++++++++++--- 5 files changed, 77 insertions(+), 17 deletions(-) diff --git a/build.gradle b/build.gradle index 85db788d..082ab1c1 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ import java.net.http.HttpResponse import java.nio.file.Paths plugins { - id "org.jetbrains.intellij" version "1.17.0" + id "org.jetbrains.intellij" version "1.16.0" id "java" id "maven-publish" id "de.undercouch.download" version "5.3.0" diff --git a/src/main/java/com/jfrog/ide/idea/inspections/JFrogSecurityWarning.java b/src/main/java/com/jfrog/ide/idea/inspections/JFrogSecurityWarning.java index 110b6bda..17f47aff 100644 --- a/src/main/java/com/jfrog/ide/idea/inspections/JFrogSecurityWarning.java +++ b/src/main/java/com/jfrog/ide/idea/inspections/JFrogSecurityWarning.java @@ -58,16 +58,24 @@ public JFrogSecurityWarning(SarifResult result, SourceCodeScanType reporter, Rul getFirstRegion(result).getEndLine() - 1, getFirstRegion(result).getEndColumn() - 1, result.getMessage().getText(), - !result.getLocations().isEmpty() ? uriToPath(result.getLocations().get(0).getPhysicalLocation().getArtifactLocation().getUri()) : "", + getFilePath(result), result.getRuleId(), getFirstRegion(result).getSnippet().getText(), reporter, - (!result.getKind().equals("pass") && (rule.getRuleProperties().map(properties -> properties.getApplicability().equals("applicable")).orElse(true))), + isWarningApplicable(result,rule), Severity.fromSarif(result.getSeverity()), convertCodeFlowsToFindingInfo(result.getCodeFlows()) ); } + private static boolean isWarningApplicable(SarifResult result,Rule rule){ + return !result.getKind().equals("pass") && (rule.getRuleProperties().map(properties -> properties.getApplicability().equals("applicable")).orElse(true)); + } + + private static String getFilePath(SarifResult result){ + return !result.getLocations().isEmpty() ? uriToPath(result.getLocations().get(0).getPhysicalLocation().getArtifactLocation().getUri()) : ""; + } + private static FindingInfo[][] convertCodeFlowsToFindingInfo(List codeFlows) { if (codeFlows == null || codeFlows.isEmpty()) { return null; diff --git a/src/main/java/com/jfrog/ide/idea/scan/data/Rule.java b/src/main/java/com/jfrog/ide/idea/scan/data/Rule.java index 514580b6..f6bd89a0 100644 --- a/src/main/java/com/jfrog/ide/idea/scan/data/Rule.java +++ b/src/main/java/com/jfrog/ide/idea/scan/data/Rule.java @@ -1,6 +1,8 @@ package com.jfrog.ide.idea.scan.data; import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import org.apache.batik.svggen.font.table.RangeRecord; import java.util.Objects; import java.util.Optional; @@ -56,6 +58,7 @@ public int hashCode() { return Objects.hash(id); } + @Override public boolean equals(Object other) { if (other == this) { @@ -68,3 +71,5 @@ public boolean equals(Object other) { return Objects.equals(this.id, rhs.id); } } + + diff --git a/src/test/java/com/jfrog/ide/idea/scan/ScanBinaryExecutorTest.java b/src/test/java/com/jfrog/ide/idea/scan/ScanBinaryExecutorTest.java index 918ab813..00669272 100644 --- a/src/test/java/com/jfrog/ide/idea/scan/ScanBinaryExecutorTest.java +++ b/src/test/java/com/jfrog/ide/idea/scan/ScanBinaryExecutorTest.java @@ -7,6 +7,7 @@ import junit.framework.TestCase; import org.apache.commons.io.FileUtils; import org.jfrog.build.api.util.NullLog; +import org.junit.Assert; import java.io.File; import java.io.IOException; @@ -15,6 +16,7 @@ import java.util.List; import static com.jfrog.ide.common.utils.Utils.createYAMLMapper; +import static org.junit.Assert.assertThrows; /** * @author tala @@ -87,21 +89,28 @@ public void testSarifParserNotApplicResults() throws IOException { public void testSarifParserApplicResultsWithKindPass() throws IOException { List parsedOutput = scanner.parseOutputSarif(APPLIC_KIND_PASS_OUTPUT); - assertEquals(4, parsedOutput.size()); - // 2 known applicable results (code evidence returned) + assertEquals(6, parsedOutput.size()); + //Not Applicable with kind pass assertEquals("applic_CVE-2022-25878", parsedOutput.get(0).getRuleID()); assertFalse(parsedOutput.get(0).isApplicable()); - assertEquals("CVE-2022-25978", parsedOutput.get(1).getRuleID()); + //Applicable with kind pass + assertEquals("applic_CVE-2022-25978", parsedOutput.get(1).getRuleID()); assertTrue(parsedOutput.get(1).isApplicable()); - // 2 known no-applicable results (have a scanner but no code evidence returned) + //Not applicable with kind pass and no properties assertEquals("applic_CVE-2021-25878", parsedOutput.get(2).getRuleID()); assertFalse(parsedOutput.get(2).isApplicable()); + //Applicable with kind fail assertEquals("applic_CVE-2022-29019", parsedOutput.get(3).getRuleID()); - assertFalse(parsedOutput.get(3).isApplicable()); + assertTrue(parsedOutput.get(3).isApplicable()); + //Not applicable as its not_covered + assertEquals("applic_CVE-2022-29004", parsedOutput.get(4).getRuleID()); + assertFalse(parsedOutput.get(4).isApplicable()); + //Not applicable as its undetermined + assertEquals("applic_CVE-2022-29014", parsedOutput.get(5).getRuleID()); + assertFalse(parsedOutput.get(5).isApplicable()); } - public void testGetBinaryDownloadURL() { final String externalRepoName = "test-releases-repo"; final String expectedExternalRepoUrl = "test-releases-repo/artifactory/xsc-gen-exe-analyzer-manager-local/"; diff --git a/src/test/resources/sourceCode/applicable_kind_pass_output.sarif b/src/test/resources/sourceCode/applicable_kind_pass_output.sarif index 97b8094a..e32d5554 100644 --- a/src/test/resources/sourceCode/applicable_kind_pass_output.sarif +++ b/src/test/resources/sourceCode/applicable_kind_pass_output.sarif @@ -16,11 +16,11 @@ "markdown": "The scanner checks whether the vulnerable function `pem.Decode` is called." }, "shortDescription": { - "text": "Scanner for CVE-2020-28502" + "text": "Scanner for applic_CVE-2022-25878" } }, { - "id": "CVE-2022-25978", + "id": "applic_CVE-2022-25978", "properties": { "conclusion": "negative", "applicability": "applicable" @@ -30,7 +30,7 @@ "markdown": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used." }, "shortDescription": { - "text": "Scanner for CVE-2020-5310" + "text": "Scanner for applic_CVE-2022-25978" } }, { @@ -40,7 +40,7 @@ "markdown": "The scanner checks whether the vulnerable function `pem.Decode` is called." }, "shortDescription": { - "text": "Scanner for CVE-2020-28502" + "text": "Scanner for applic_CVE-2021-25878" } }, { @@ -50,10 +50,35 @@ "markdown": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used." }, "shortDescription": { - "text": "Scanner for CVE-2020-5310" + "text": "Scanner for applic_CVE-2022-29019" } + }, + { + "id": "applic_CVE-2022-29004", + "fullDescription": { + "text": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used.", + "markdown": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used." + }, + "shortDescription": { + "text": "Scanner for applic_CVE-2022-29004" + }, "properties": { + "conclusion": "positive", + "applicability": "not_covered" + } + }, + { + "id": "applic_CVE-2022-29014", + "fullDescription": { + "text": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used.", + "markdown": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used." + }, + "shortDescription": { + "text": "Scanner for applic_CVE-2022-29014" + }, "properties": { + "conclusion": "positive", + "applicability": "undetermined" + } } - ], "version": "APPLIC_SCANNERv0.2.0" } @@ -116,7 +141,7 @@ } } ], - "ruleId": "CVE-2022-25978" + "ruleId": "applic_CVE-2022-25978" }, { "message": { @@ -129,8 +154,21 @@ "message": { "text": "The scanner checks whether the vulnerable function `ansi-regex` is called." }, - "kind": "pass", + "kind": "fail", "ruleId": "applic_CVE-2022-29019" + }, + { + "message": { + "text": "The scanner checks whether the vulnerable function `call-all-ansi` is called." + }, + "kind": "pass", + "ruleId": "applic_CVE-2022-29004" + }, + {"message": { + "text": "The scanner checks whether the vulnerable function `not-call-all-ansi` is called." + }, + "kind": "pass", + "ruleId": "applic_CVE-2022-29014" } ] } From 74922492099e5016114192a26bf84a2efba42aca Mon Sep 17 00:00:00 2001 From: Eyal Kapon Date: Thu, 5 Sep 2024 11:27:55 +0300 Subject: [PATCH 8/9] cr fixes --- src/main/java/com/jfrog/ide/idea/scan/data/Rule.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/com/jfrog/ide/idea/scan/data/Rule.java b/src/main/java/com/jfrog/ide/idea/scan/data/Rule.java index f6bd89a0..31d83609 100644 --- a/src/main/java/com/jfrog/ide/idea/scan/data/Rule.java +++ b/src/main/java/com/jfrog/ide/idea/scan/data/Rule.java @@ -1,9 +1,6 @@ package com.jfrog.ide.idea.scan.data; import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Getter; -import org.apache.batik.svggen.font.table.RangeRecord; - import java.util.Objects; import java.util.Optional; From bba983832949e74631240576a4c115dee1c5fbab Mon Sep 17 00:00:00 2001 From: Eyal Kapon Date: Thu, 5 Sep 2024 16:10:49 +0300 Subject: [PATCH 9/9] added missing test --- .../ide/idea/scan/ScanBinaryExecutor.java | 2 +- .../com/jfrog/ide/idea/scan/data/Driver.java | 2 +- .../ide/idea/scan/ScanBinaryExecutorTest.java | 24 +-- .../resources/sourceCode/faulty_output.sarif | 184 ++++++++++++++++++ .../sourceCode/not_applic_output.sarif | 133 ------------- 5 files changed, 192 insertions(+), 153 deletions(-) create mode 100644 src/test/resources/sourceCode/faulty_output.sarif delete mode 100644 src/test/resources/sourceCode/not_applic_output.sarif diff --git a/src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java b/src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java index 2a2e984c..8bc206fe 100644 --- a/src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java +++ b/src/main/java/com/jfrog/ide/idea/scan/ScanBinaryExecutor.java @@ -257,7 +257,7 @@ protected boolean isPackageTypeSupported(PackageManagerType type) { return type != null && supportedPackageTypes.contains(type); } - protected List parseOutputSarif(Path outputFile) throws IOException { + protected List parseOutputSarif(Path outputFile) throws IOException,IndexOutOfBoundsException { Output output = getOutputObj(outputFile); List warnings = new ArrayList<>(); diff --git a/src/main/java/com/jfrog/ide/idea/scan/data/Driver.java b/src/main/java/com/jfrog/ide/idea/scan/data/Driver.java index 22a4347b..ed3e33cd 100644 --- a/src/main/java/com/jfrog/ide/idea/scan/data/Driver.java +++ b/src/main/java/com/jfrog/ide/idea/scan/data/Driver.java @@ -48,7 +48,7 @@ public boolean equals(Object other) { return (Objects.equals(this.name, rhs.name) && (CollectionUtils.isEqualCollection(this.rules, rhs.rules))); } - public Rule getRuleById(String ruleId) { + public Rule getRuleById(String ruleId) throws IndexOutOfBoundsException { return rules.stream() .filter(rule -> rule.getId().equals(ruleId)) .findFirst() diff --git a/src/test/java/com/jfrog/ide/idea/scan/ScanBinaryExecutorTest.java b/src/test/java/com/jfrog/ide/idea/scan/ScanBinaryExecutorTest.java index 00669272..5b170789 100644 --- a/src/test/java/com/jfrog/ide/idea/scan/ScanBinaryExecutorTest.java +++ b/src/test/java/com/jfrog/ide/idea/scan/ScanBinaryExecutorTest.java @@ -7,7 +7,6 @@ import junit.framework.TestCase; import org.apache.commons.io.FileUtils; import org.jfrog.build.api.util.NullLog; -import org.junit.Assert; import java.io.File; import java.io.IOException; @@ -23,9 +22,9 @@ **/ public class ScanBinaryExecutorTest extends TestCase { private final ScanBinaryExecutor scanner = new ApplicabilityScannerExecutor(new NullLog()); + private final Path FAULTY_OUTPUT = new File("src/test/resources/sourceCode/faulty_output.sarif").toPath(); private final Path SIMPLE_OUTPUT = new File("src/test/resources/sourceCode/simple_output.sarif").toPath(); - private final Path NOT_APPLIC_OUTPUT = new File("src/test/resources/sourceCode/not_applic_output.sarif").toPath(); - private final Path APPLIC_KIND_PASS_OUTPUT = new File("src/test/resources/sourceCode/applicable_kind_pass_output.sarif").toPath(); + private final Path APPLIC_KIND_PASS_AND_FAIL_OUTPUT = new File("src/test/resources/sourceCode/applicable_kind_pass_output.sarif").toPath(); public void testInputBuilder() throws IOException { ScanConfig.Builder inputFileBuilder = new ScanConfig.Builder(); Path inputPath = null; @@ -72,23 +71,12 @@ public void testSarifParser() throws IOException { assertEquals(73, parsedOutput.get(1).getColEnd()); } - public void testSarifParserNotApplicResults() throws IOException { - List parsedOutput = scanner.parseOutputSarif(NOT_APPLIC_OUTPUT); - assertEquals(4, parsedOutput.size()); - // 2 known applicable results (code evidence returned) - assertEquals("applic_CVE-2022-25878", parsedOutput.get(0).getRuleID()); - assertTrue(parsedOutput.get(0).isApplicable()); - assertEquals("CVE-2022-25978", parsedOutput.get(1).getRuleID()); - assertTrue(parsedOutput.get(1).isApplicable()); - // 2 known no-applicable results (have a scanner but no code evidence returned) - assertEquals("applic_CVE-2021-25878", parsedOutput.get(2).getRuleID()); - assertFalse(parsedOutput.get(2).isApplicable()); - assertEquals("applic_CVE-2022-29019", parsedOutput.get(3).getRuleID()); - assertFalse(parsedOutput.get(3).isApplicable()); + public void testSarifParserWithMissingRole() throws IndexOutOfBoundsException { + assertThrows(IndexOutOfBoundsException.class,() -> scanner.parseOutputSarif(FAULTY_OUTPUT)); } - public void testSarifParserApplicResultsWithKindPass() throws IOException { - List parsedOutput = scanner.parseOutputSarif(APPLIC_KIND_PASS_OUTPUT); + public void testSarifParserApplicResultsWithKindPassAndFail() throws IOException { + List parsedOutput = scanner.parseOutputSarif(APPLIC_KIND_PASS_AND_FAIL_OUTPUT); assertEquals(6, parsedOutput.size()); //Not Applicable with kind pass assertEquals("applic_CVE-2022-25878", parsedOutput.get(0).getRuleID()); diff --git a/src/test/resources/sourceCode/faulty_output.sarif b/src/test/resources/sourceCode/faulty_output.sarif new file mode 100644 index 00000000..c6753151 --- /dev/null +++ b/src/test/resources/sourceCode/faulty_output.sarif @@ -0,0 +1,184 @@ +{ + "runs": [ + { + "tool": { + "driver": { + "name": "JFrog Applicability Scanner", + "rules": [ + { + "id": "applic_CVE-2022-25878", + "properties": { + "conclusion": "positive", + "applicability": "not_applicable" + }, + "fullDescription": { + "text": "The scanner checks whether the vulnerable function `pem.Decode` is called.", + "markdown": "The scanner checks whether the vulnerable function `pem.Decode` is called." + }, + "shortDescription": { + "text": "Scanner for applic_CVE-2022-25878" + } + }, + { + "id": "applic_CVE-2022-25978", + "properties": { + "conclusion": "negative", + "applicability": "applicable" + }, + "fullDescription": { + "text": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used.", + "markdown": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used." + }, + "shortDescription": { + "text": "Scanner for applic_CVE-2022-25978" + } + }, + { + "id": "applic_CVE-2021-25878", + "fullDescription": { + "text": "The scanner checks whether the vulnerable function `pem.Decode` is called.", + "markdown": "The scanner checks whether the vulnerable function `pem.Decode` is called." + }, + "shortDescription": { + "text": "Scanner for applic_CVE-2021-25878" + } + }, + { + "id": "applic_CVE-2022-29019", + "fullDescription": { + "text": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used.", + "markdown": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used." + }, + "shortDescription": { + "text": "Scanner for applic_CVE-2022-29019" + } + }, + { + "id": "applic_CVE-2022-29004", + "fullDescription": { + "text": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used.", + "markdown": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used." + }, + "shortDescription": { + "text": "Scanner for applic_CVE-2022-29004" + }, "properties": { + "conclusion": "positive", + "applicability": "not_covered" + } + }, + { + "id": "applic_CVE-2022-29014", + "fullDescription": { + "text": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used.", + "markdown": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used." + }, + "shortDescription": { + "text": "Scanner for applic_CVE-2022-29014" + }, "properties": { + "conclusion": "positive", + "applicability": "undetermined" + } + } + ], + "version": "APPLIC_SCANNERv0.2.0" + } + }, + "invocations": [ + { + "executionSuccessful": true, + "arguments": [ + "scan" + ], + "workingDirectory": { + "uri": "" + } + } + ], + "results": [ + { + "message": { + "text": "The vulnerable function protobufjs.load is called" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "file:///examples/applic-demo/index.js" + }, + "region": { + "endColumn": 17, + "endLine": 20, + "snippet": { + "text": "protobuf.parse(p)" + }, + "startColumn": 0, + "startLine": 20 + } + } + } + ], + "ruleId": "applic_CVE-2022-25878" + }, + { + "message": { + "text": "The vulnerable function protobufjs.parse is called." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "file:///examples/applic-demo/index.js" + }, + "region": { + "endColumn": 73, + "endLine": 22, + "snippet": { + "text": "protobuf.load(\"/path/to/untrusted.proto\", function(err, root) { return })" + }, + "startColumn": 0, + "startLine": 18 + } + } + } + ], + "ruleId": "applic_CVE-2022-25978" + }, + { + "message": { + "text": "The scanner checks whether the vulnerable function `ansi-regex` is called." + }, + "kind": "pass", + "ruleId": "applic_CVE-2021-25878" + }, + { + "message": { + "text": "The scanner checks whether the vulnerable function `ansi-regex` is called." + }, + "kind": "fail", + "ruleId": "applic_CVE-2022-29019" + }, + { + "message": { + "text": "The scanner checks whether the vulnerable function `call-all-ansi` is called." + }, + "kind": "pass", + "ruleId": "applic_CVE-2022-29004" + }, + {"message": { + "text": "The scanner checks whether the vulnerable function `not-call-all-ansi` is called." + }, + "kind": "pass", + "ruleId": "applic_CVE-2022-29014" + }, + {"message": { + "text": "The scanner checks whether the vulnerable function `not-call-all-ansi` is called." + }, + "kind": "pass", + "ruleId": "applic_CVE-2022-29614" + } + ] + } + ], + "version": "2.1.0", + "$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json" +} \ No newline at end of file diff --git a/src/test/resources/sourceCode/not_applic_output.sarif b/src/test/resources/sourceCode/not_applic_output.sarif deleted file mode 100644 index 38792e4d..00000000 --- a/src/test/resources/sourceCode/not_applic_output.sarif +++ /dev/null @@ -1,133 +0,0 @@ -{ - "runs": [ - { - "tool": { - "driver": { - "name": "JFrog Applicability Scanner", - "rules": [ - - { - "id": "applic_CVE-2022-25878", - "fullDescription": { - "text": "The scanner checks whether the vulnerable function `pem.Decode` is called.", - "markdown": "The scanner checks whether the vulnerable function `pem.Decode` is called." - }, - "shortDescription": { - "text": "Scanner for CVE-2020-28502" - } - }, - { - "id": "CVE-2022-25978", - "fullDescription": { - "text": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used.", - "markdown": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used." - }, - "shortDescription": { - "text": "Scanner for CVE-2020-5310" - } - }, - { - "id": "applic_CVE-2021-25878", - "fullDescription": { - "text": "The scanner checks whether the vulnerable function `pem.Decode` is called.", - "markdown": "The scanner checks whether the vulnerable function `pem.Decode` is called." - }, - "shortDescription": { - "text": "Scanner for CVE-2020-28502" - } - }, - { - "id": "applic_CVE-2022-29019", - "fullDescription": { - "text": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used.", - "markdown": "The scanner checks whether the vulnerable function `org.apache.xmlbeans.XmlObject.Factory.parse` is called or an interface that extends `org.apache.xmlbeans.XmlObject` is used." - }, - "shortDescription": { - "text": "Scanner for CVE-2020-5310" - } - } - - ], - "version": "APPLIC_SCANNERv0.2.0" - } - }, - "invocations": [ - { - "executionSuccessful": true, - "arguments": [ - "scan" - ], - "workingDirectory": { - "uri": "" - } - } - ], - "results": [ - { - "message": { - "text": "The vulnerable function protobufjs.load is called" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "file:///examples/applic-demo/index.js" - }, - "region": { - "endColumn": 17, - "endLine": 20, - "snippet": { - "text": "protobuf.parse(p)" - }, - "startColumn": 0, - "startLine": 20 - } - } - } - ], - "ruleId": "applic_CVE-2022-25878" - }, - { - "message": { - "text": "The vulnerable function protobufjs.parse is called." - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "file:///examples/applic-demo/index.js" - }, - "region": { - "endColumn": 73, - "endLine": 22, - "snippet": { - "text": "protobuf.load(\"/path/to/untrusted.proto\", function(err, root) { return })" - }, - "startColumn": 0, - "startLine": 18 - } - } - } - ], - "ruleId": "CVE-2022-25978" - }, - { - "message": { - "text": "The scanner checks whether the vulnerable function `ansi-regex` is called." - }, - "kind": "pass", - "ruleId": "applic_CVE-2021-25878" - }, - { - "message": { - "text": "The scanner checks whether the vulnerable function `ansi-regex` is called." - }, - "kind": "pass", - "ruleId": "applic_CVE-2022-29019" - } - ] - } - ], - "version": "2.1.0", - "$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json" -} \ No newline at end of file