Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature 3141 implement first version of secret validator application #3280

3 changes: 3 additions & 0 deletions gradle/projects.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ projectType = [
to have dependency injection and access to some other spring boot parts */
project(':sechub-wrapper-checkmarx'),
project(':sechub-wrapper-prepare'),

/* special application to validate and categorize results of secret scans */
project(':sechub-wrapper-secret-validator'),


],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
// SPDX-License-Identifier: MIT
package com.mercedesbenz.sechub.sereco.importer;

import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Component;

import de.jcup.sarif_2_1_0.model.PartialFingerprints;
import de.jcup.sarif_2_1_0.model.ReportingDescriptor;
import de.jcup.sarif_2_1_0.model.Result;
import de.jcup.sarif_2_1_0.model.Run;
import de.jcup.sarif_2_1_0.model.Tool;
import de.jcup.sarif_2_1_0.model.ToolComponent;
import de.jcup.sarif_2_1_0.model.*;

@Component
public class GitleaksSarifImportWorkaround implements SarifImportProductWorkaround {
Expand Down Expand Up @@ -42,6 +38,38 @@ public String resolveFindingRevisionId(Result result, Run run) {
return null;
}

@Override
public String resolveCustomSechubSeverity(Result result, Run run) {
if (result == null) {
return null;
}
if (!isGitleaksRun(run)) {
return null;
}
List<Location> locations = result.getLocations();
if (locations == null || locations.isEmpty()) {
return null;
}
PhysicalLocation physicalLocation = locations.get(0).getPhysicalLocation();
if (physicalLocation == null) {
return null;
}
Region region = physicalLocation.getRegion();
if (region == null) {
return null;
}
PropertyBag properties = region.getProperties();
if (properties == null) {
return null;
}
Map<String, Object> additionalProperties = properties.getAdditionalProperties();
if (additionalProperties == null) {
return null;
}
String severityKey = SarifImporterKeys.SECRETSCAN_SECHUB_SEVERITY.getKey();
return (String) additionalProperties.get(severityKey);
}

private boolean isGitleaksRun(Run run) {
if (run == null) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@ public default String resolveType(ReportingDescriptor rule, Run run) {
public default String resolveFindingRevisionId(Result result, Run run) {
return null;
}

public default String resolveCustomSechubSeverity(Result result, Run run) {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@ private <R, E> R visitAllWorkaroundsAndUseFirstResultNotNull(E element, Run run,
return null;
}

public String resolveCustomSechubSeverity(Result result, Run run) {
return visitAllWorkaroundsAndUseFirstResultNotNull(result, run, new WorkaroundVisitor<String, Result>() {

@Override
public String visit(Result element, Run run, SarifImportProductWorkaround workaround) {
return workaround.resolveCustomSechubSeverity(result, run);
}
});
}

public interface WorkaroundVisitor<R, E> {

public R visit(E element, Run run, SarifImportProductWorkaround workaround);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: MIT
package com.mercedesbenz.sechub.sereco.importer;

/*
* If this needs to get changed, make sure to change
* com.mercedesbenz.sechub.wrapper.secret.validator.support.SarifImporterKeys accordingly
*/
public enum SarifImporterKeys {

SECRETSCAN_SECHUB_SEVERITY("secretscan.sechub.severity", "The key for the sechub severity which is more precise than the SARIF Level enum."),

SECRETSCAN_VALIDATED_BY_URL("secretscan.validated.by.url", "The key for the URL the secret was validated with."),

;

private String key;
private String description;

private SarifImporterKeys(String key, String description) {
this.key = key;
this.description = description;
}

public String getKey() {
return key;
}

public String getDescription() {
return description;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,13 @@ private void handleWebRequest(Result result, SerecoWeb serecoWeb) {
}

private SerecoSeverity resolveSeverity(Result result, Run run) {
Level level = sarifSchema210LogicSupport.resolveLevel(result, run);
return mapToSeverity(level);
String customSecHubSeverity = workaroundSupport.resolveCustomSechubSeverity(result, run);
SerecoSeverity serecoSeverity = severityFromString(customSecHubSeverity);
if (serecoSeverity == null) {
Level level = sarifSchema210LogicSupport.resolveLevel(result, run);
return mapToSeverity(level);
}
return serecoSeverity;
}

private class ResultData {
Expand Down Expand Up @@ -523,6 +528,10 @@ private SerecoSeverity mapToSeverity(Level level) {
}
}

private SerecoSeverity severityFromString(String customSecHubSeverity) {
return SerecoSeverity.fromString(customSecHubSeverity);
}

@Override
public boolean isAbleToImportForProduct(ImportParameter param) {
/* first we do the simple check... */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class SarifV1JSONImporterTest {
private static String sarif_2_1_0_gosec2_9_5_example5_cosdescan;
private static String sarif_2_1_0_sarif_2_1_0_gitleaks_8_0;
private static String sarif_2_1_0_sarif_2_1_0_gitleaks_8_0_one_finding_with_revision_id;
private static String sarif_2_1_0_gitleaks_8_0_with_validator_severity_properties;
private static String sarif_2_1_0_gitleaks_8_0_with_invalid_validator_severity_properties;

private SarifV1JSONImporter importerToTest;

Expand All @@ -51,6 +53,9 @@ public static void before() {
sarif_2_1_0_owasp_zap = loadSarifTestFile("sarif_2.1.0_owasp_zap.json");
sarif_2_1_0_sarif_2_1_0_gitleaks_8_0 = loadSarifTestFile("sarif_2.1.0_gitleaks_8.0.json");
sarif_2_1_0_sarif_2_1_0_gitleaks_8_0_one_finding_with_revision_id = loadSarifTestFile("sarif_2.1.0_gitleaks_8.0-one-finding-with-revision.json");
sarif_2_1_0_gitleaks_8_0_with_validator_severity_properties = loadSarifTestFile("sarif_2.1.0_gitleaks_8.0-with-validator-severity-properties.json");
sarif_2_1_0_gitleaks_8_0_with_invalid_validator_severity_properties = loadSarifTestFile(
"sarif_2.1.0_gitleaks_8.0-with-invalid-validator-severity-properties.json");
}

@BeforeEach
Expand Down Expand Up @@ -319,6 +324,86 @@ void gitleaks_8_0_simple_example_secretscan__can_be_imported_and_revision_inform
/* @formatter:on */
}

@Test
void sarif_2_1_0_gitleaks_8_0_with_validator_severity_properties__can_be_imported_and_severities_are_available() throws Exception {
/* prepare */
importerToTest.workaroundSupport.workarounds.add(new GitleaksSarifImportWorkaround());
SerecoMetaData result = importerToTest.importResult(sarif_2_1_0_gitleaks_8_0_with_validator_severity_properties, ScanType.SECRET_SCAN);

/* execute */
List<SerecoVulnerability> vulnerabilities = result.getVulnerabilities();

/* test */
/* @formatter:off */
assertVulnerabilities(vulnerabilities).
hasVulnerabilities(6).
verifyVulnerability().
withSeverity(SerecoSeverity.INFO).
withCodeLocation("UnSAFE_Bank/Backend/docker-compose.yml", 12, 14).
containingSource("531486b2bf646636a6a1bba61e78ec4a4a54efbd").
done().
isContained().
verifyVulnerability().
withSeverity(SerecoSeverity.UNCLASSIFIED).
withCodeLocation("UnSAFE_Bank/Backend/src/api/application/config/database.php", 80, 7).
containingSource("531486b2bf646636a6a1bba61e78ec4a4a54efbd").
done().
isContained().
verifyVulnerability().
withSeverity(SerecoSeverity.LOW).
withCodeLocation("UnSAFE_Bank/Backend/web/src/app/thunks/Authentication/ForgotPassword/handleForgotPasswordGetOTPThunk.tsx", 32, 14).
containingSource("9bbc0d79e686e847bc305c9bd4cc2ea6").
done().
isContained().
verifyVulnerability().
withSeverity(SerecoSeverity.MEDIUM).
withCodeLocation("UnSAFE_Bank/Backend/web/src/app/thunks/OTP/handleGetOTPThunk.tsx", 31, 14).
containingSource("9bbc0d79e686e847bc305c9bd4cc2ea6").
done().
isContained().
verifyVulnerability().
withSeverity(SerecoSeverity.HIGH).
withCodeLocation("UnSAFE_Bank/iOS/Source Code/Podfile.lock", 23, 4).
containingSource("b3816fddcf28aa29d94b10ec305cd52be14c472b").
done().
isContained().
verifyVulnerability().
withSeverity(SerecoSeverity.CRITICAL).
withCodeLocation("UnSAFE_Bank/iOS/Source Code/Pods/Manifest.lock", 23, 4).
containingSource("b3816fddcf28aa29d94b10ec305cd52be14c472b").
done().
isContained();
/* @formatter:on */
}

@Test
void sarif_2_1_0_gitleaks_8_0_with_invalid_validator_severity_properties__can_be_imported_and_severities_are_set_to_sarif_default() throws Exception {
/* prepare */
importerToTest.workaroundSupport.workarounds.add(new GitleaksSarifImportWorkaround());
SerecoMetaData result = importerToTest.importResult(sarif_2_1_0_gitleaks_8_0_with_invalid_validator_severity_properties, ScanType.SECRET_SCAN);

/* execute */
List<SerecoVulnerability> vulnerabilities = result.getVulnerabilities();

/* test */
/* @formatter:off */
assertVulnerabilities(vulnerabilities).
hasVulnerabilities(2).
verifyVulnerability().
withSeverity(SerecoSeverity.MEDIUM).
withCodeLocation("UnSAFE_Bank/Backend/docker-compose.yml", 12, 14).
containingSource("531486b2bf646636a6a1bba61e78ec4a4a54efbd").
done().
isContained().
verifyVulnerability().
withSeverity(SerecoSeverity.MEDIUM).
withCodeLocation("UnSAFE_Bank/Backend/src/api/application/config/database.php", 80, 7).
containingSource("531486b2bf646636a6a1bba61e78ec4a4a54efbd").
done().
isContained();
/* @formatter:on */
}

@Test
void brakeman_sarif_report_can_be_imported() {
/* prepare */
Expand Down
Loading
Loading