io.codemodder.providers.sarif.semgrep.SingleSemgrepRuleSarif Maven / Gradle / Ivy
Show all versions of codemodder-plugin-semgrep Show documentation
package io.codemodder.providers.sarif.semgrep;
import com.contrastsecurity.sarif.Region;
import com.contrastsecurity.sarif.Result;
import com.contrastsecurity.sarif.SarifSchema210;
import io.codemodder.RuleSarif;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* {@inheritDoc}
*
* Semgrep's SARIF has a relatively simple model but the "ruleId" in the document is weird. It
* places the whole path to the rule in the field. This means our filtering logic is a little weird
* and unexpected, but it works.
*/
final class SingleSemgrepRuleSarif implements RuleSarif {
private final SarifSchema210 sarif;
private final String ruleId;
private final Map> resultsCache;
private final Path repositoryRoot;
SingleSemgrepRuleSarif(
final String ruleId, final SarifSchema210 sarif, final Path codeDirectory) {
this.sarif = Objects.requireNonNull(sarif);
this.ruleId = Objects.requireNonNull(ruleId);
this.repositoryRoot = Objects.requireNonNull(codeDirectory);
this.resultsCache = new HashMap<>();
}
@Override
public SarifSchema210 rawDocument() {
return sarif;
}
@Override
public String getRule() {
return ruleId;
}
@Override
public List getRegionsFromResultsByRule(final Path path) {
return getResultsByLocationPath(path).stream()
.map(result -> result.getLocations().get(0).getPhysicalLocation().getRegion())
.toList();
}
@Override
public List getResultsByLocationPath(final Path path) {
if (resultsCache.containsKey(path)) {
return resultsCache.get(path);
}
List results =
sarif.getRuns().get(0).getResults().stream()
/*
* The default Semgrep rules have a rule id reported that is what you'd expect. When you run
* your own custom rules locally, they'll contain part of the file system path to the rule.
*
* Because this provides support for both types, we need this check to account for which type
* of rule id we're dealing with.
*/
.filter(
result ->
result.getRuleId().endsWith("." + ruleId) || result.getRuleId().equals(ruleId))
.filter(
result -> {
String uri =
result
.getLocations()
.get(0)
.getPhysicalLocation()
.getArtifactLocation()
.getUri();
try {
return Files.isSameFile(path, repositoryRoot.resolve(uri));
} catch (IOException e) {
// this can happen if the file referenced in SARIF doesn't exist (like in tests)
log.debug("Couldn't find file referenced in SARIF", e);
return false;
}
})
.toList();
resultsCache.put(path, results);
return results;
}
@Override
public String getDriver() {
return sarif.getRuns().get(0).getTool().getDriver().getName();
}
private static final Logger log = LoggerFactory.getLogger(SingleSemgrepRuleSarif.class);
}