Skip to content

Commit ff519dc

Browse files
authored
ryandens/appscan message text (#423)
- **:recycle: provide messageText to all RuleSarifFactory impls** - **Bind AppScan sarif to rule by rule name from message text**
1 parent 901144f commit ff519dc

File tree

10 files changed

+47
-40
lines changed

10 files changed

+47
-40
lines changed

framework/codemodder-base/src/main/java/io/codemodder/DefaultSarifParser.java

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package io.codemodder;
22

3-
import com.contrastsecurity.sarif.ReportingDescriptor;
43
import com.contrastsecurity.sarif.Result;
54
import com.contrastsecurity.sarif.Run;
65
import com.contrastsecurity.sarif.SarifSchema210;
@@ -9,6 +8,7 @@
98
import java.nio.file.Files;
109
import java.nio.file.Path;
1110
import java.util.*;
11+
import java.util.stream.Collectors;
1212
import java.util.stream.Stream;
1313
import org.slf4j.Logger;
1414
import org.slf4j.LoggerFactory;
@@ -28,12 +28,13 @@ private Optional<SarifSchema210> readSarifFile(final Path sarifFile) {
2828
/** Send the arguments to all factories and returns the first that built something. */
2929
private Optional<Map.Entry<String, RuleSarif>> tryToBuild(
3030
final String toolName,
31-
final String rule,
31+
final RuleDescriptor rule,
3232
final SarifSchema210 sarif,
3333
final CodeDirectory codeDirectory,
3434
final List<RuleSarifFactory> factories) {
3535
for (final var factory : factories) {
36-
final var maybeRuleSarif = factory.build(toolName, rule, sarif, codeDirectory);
36+
final var maybeRuleSarif =
37+
factory.build(toolName, rule.ruleId, rule.messageText, sarif, codeDirectory);
3738
if (maybeRuleSarif.isPresent()) {
3839
return Optional.of(Map.entry(toolName, maybeRuleSarif.get()));
3940
}
@@ -43,7 +44,9 @@ private Optional<Map.Entry<String, RuleSarif>> tryToBuild(
4344
return Optional.empty();
4445
}
4546

46-
private String extractRuleId(final Result result, final Run run) {
47+
private record RuleDescriptor(String ruleId, String messageText) {}
48+
49+
private RuleDescriptor extractRuleId(final Result result, final Run run) {
4750
if (result.getRuleId() == null) {
4851
var toolIndex = result.getRule().getToolComponent().getIndex();
4952
var ruleIndex = result.getRule().getIndex();
@@ -52,15 +55,16 @@ private String extractRuleId(final Result result, final Run run) {
5255
.skip(toolIndex)
5356
.findFirst()
5457
.flatMap(tool -> tool.getRules().stream().skip(ruleIndex).findFirst())
55-
.map(ReportingDescriptor::getId);
58+
.map(descriptor -> new RuleDescriptor(descriptor.getId(), null));
59+
5660
if (maybeRule.isPresent()) {
5761
return maybeRule.get();
5862
} else {
5963
LOG.info("Could not find rule id for result.");
6064
return null;
6165
}
6266
}
63-
return result.getRuleId();
67+
return new RuleDescriptor(result.getRuleId(), result.getMessage().getText());
6468
}
6569

6670
private Stream<Map.Entry<String, RuleSarif>> fromSarif(
@@ -77,8 +81,11 @@ private Stream<Map.Entry<String, RuleSarif>> fromSarif(
7781
? runResults.stream()
7882
.map(result -> extractRuleId(result, run))
7983
.filter(Objects::nonNull)
80-
.distinct()
81-
: Stream.<String>empty();
84+
.filter(ruleDescriptor -> ruleDescriptor.ruleId != null)
85+
.collect(Collectors.toMap(r -> r.ruleId, r -> r, (r1, r2) -> r1))
86+
.values()
87+
.stream()
88+
: Stream.<RuleDescriptor>empty();
8289

8390
return allResults.flatMap(
8491
rule -> tryToBuild(toolName, rule, sarif, codeDirectory, factories).stream());

framework/codemodder-base/src/main/java/io/codemodder/RuleSarifFactory.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,9 @@ public interface RuleSarifFactory {
88

99
/** Builds {@link RuleSarif}s if it supports {@code toolName}. */
1010
Optional<RuleSarif> build(
11-
String toolName, String rule, SarifSchema210 sarif, CodeDirectory codeDirectory);
11+
String toolName,
12+
String rule,
13+
String messageText,
14+
SarifSchema210 sarif,
15+
CodeDirectory codeDirectory);
1216
}

plugins/codemodder-plugin-appscan/src/main/java/io/codemodder/providers/sarif/appscan/AppScanModule.java

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,10 @@ protected void configure() {
4141
.findFirst();
4242

4343
annotation.ifPresent(
44-
providedAppScanScan -> {
45-
RuleSarif sarif = null;
46-
for (final var ruleId : providedAppScanScan.ruleIds()) {
47-
final var value = map.get(ruleId);
48-
if (value != null) {
49-
sarif = value;
50-
break;
51-
}
52-
}
53-
54-
if (sarif == null) {
55-
sarif = RuleSarif.EMPTY;
56-
}
57-
58-
bind(RuleSarif.class).annotatedWith(providedAppScanScan).toInstance(sarif);
59-
});
44+
providedAppScanScan ->
45+
bind(RuleSarif.class)
46+
.annotatedWith(providedAppScanScan)
47+
.toInstance(map.getOrDefault(providedAppScanScan.ruleName(), RuleSarif.EMPTY)));
6048
}
6149
}
6250
}

plugins/codemodder-plugin-appscan/src/main/java/io/codemodder/providers/sarif/appscan/AppScanRuleSarif.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
final class AppScanRuleSarif implements RuleSarif {
1313

1414
private final SarifSchema210 sarif;
15-
private final String ruleId;
15+
private final String messageText;
1616
private final Map<Path, List<Result>> resultsCache;
1717
private final List<String> locations;
1818

@@ -24,9 +24,9 @@ final class AppScanRuleSarif implements RuleSarif {
2424
* locations, which are strange combinations of class name and file path, into predictable paths.
2525
*/
2626
AppScanRuleSarif(
27-
final String ruleId, final SarifSchema210 sarif, final CodeDirectory codeDirectory) {
27+
final String messageText, final SarifSchema210 sarif, final CodeDirectory codeDirectory) {
2828
this.sarif = Objects.requireNonNull(sarif);
29-
this.ruleId = Objects.requireNonNull(ruleId);
29+
this.messageText = Objects.requireNonNull(messageText);
3030
this.resultsCache = new HashMap<>();
3131
this.locations =
3232
sarif.getRuns().get(0).getArtifacts().stream()
@@ -76,7 +76,7 @@ public List<Result> getResultsByLocationPath(final Path path) {
7676
p ->
7777
sarif.getRuns().stream()
7878
.flatMap(run -> run.getResults().stream())
79-
.filter(result -> result.getRuleId().equals(ruleId))
79+
.filter(result -> result.getMessage().getText().equals(messageText))
8080
.filter(
8181
result ->
8282
artifactLocationIndices.get(path) != null
@@ -113,7 +113,7 @@ public SarifSchema210 rawDocument() {
113113
*/
114114
@Override
115115
public String getRule() {
116-
return ruleId;
116+
return messageText;
117117
}
118118

119119
static final String toolName = "HCL AppScan Static Analyzer";

plugins/codemodder-plugin-appscan/src/main/java/io/codemodder/providers/sarif/appscan/AppScanRuleSarifFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ public final class AppScanRuleSarifFactory implements RuleSarifFactory {
1313
public Optional<RuleSarif> build(
1414
final String toolName,
1515
final String rule,
16+
final String messageText,
1617
final SarifSchema210 sarif,
1718
final CodeDirectory codeDirectory) {
1819
if (AppScanRuleSarif.toolName.equals(toolName)) {
19-
return Optional.of(new AppScanRuleSarif(rule, sarif, codeDirectory));
20+
return Optional.of(new AppScanRuleSarif(messageText, sarif, codeDirectory));
2021
}
2122
return Optional.empty();
2223
}

plugins/codemodder-plugin-appscan/src/main/java/io/codemodder/providers/sarif/appscan/ProvidedAppScanScan.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@
1313
@Target(ElementType.PARAMETER)
1414
public @interface ProvidedAppScanScan {
1515

16-
/**
17-
* The AppScan rule "id" field from the sarif. If multiple are provided, we look for the first ID
18-
* in the SARIF before looking up alternative rule IDs
19-
*/
20-
String[] ruleIds();
16+
/** The AppScan rule name, which shows up as the "message text" in the SARIF results. */
17+
String ruleName();
2118
}

plugins/codemodder-plugin-appscan/src/test/java/io/codemodder/providers/sarif/appscan/AppScanModuleTest.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ static class AppScanSarifTestCodemod implements CodeChanger {
2828
private final RuleSarif ruleSarif;
2929

3030
@Inject
31-
AppScanSarifTestCodemod(@ProvidedAppScanScan(ruleIds = {"SA2813462719"}) RuleSarif ruleSarif) {
31+
AppScanSarifTestCodemod(@ProvidedAppScanScan(ruleName = "SQL Injection") RuleSarif ruleSarif) {
3232
this.ruleSarif = ruleSarif;
3333
}
3434

@@ -86,7 +86,11 @@ void it_works_with_appscan_sarif(@TempDir final Path repoDir) throws IOException
8686
AppScanRuleSarifFactory ruleSarifFactory = new AppScanRuleSarifFactory();
8787
Optional<RuleSarif> ruleSarif =
8888
ruleSarifFactory.build(
89-
"HCL AppScan Static Analyzer", "SA2813462719", rawSarif, CodeDirectory.from(repoDir));
89+
"HCL AppScan Static Analyzer",
90+
"SA2813462719",
91+
"SQL Injection",
92+
rawSarif,
93+
CodeDirectory.from(repoDir));
9094
assertThat(ruleSarif.isPresent(), is(true));
9195
AppScanModule module =
9296
new AppScanModule(List.of(AppScanSarifTestCodemod.class), List.of(ruleSarif.get()));

plugins/codemodder-plugin-appscan/src/test/java/io/codemodder/providers/sarif/appscan/AppScanRuleSarifFactoryTest.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,16 @@ void it_parses_sarif_and_maps_java_locations(@TempDir final Path tmpDir) throws
4343
new File("src/test/resources/webgoat_2023_8_binary.sarif"), SarifSchema210.class);
4444
Optional<RuleSarif> sarifRef =
4545
appScanRuleSarifFactory.build(
46-
"HCL AppScan Static Analyzer", "SA2813462719", rawSarif, CodeDirectory.from(tmpDir));
46+
"HCL AppScan Static Analyzer",
47+
"SA2813462719",
48+
"SQL Injection",
49+
rawSarif,
50+
CodeDirectory.from(tmpDir));
4751
assertThat(sarifRef.isPresent()).isTrue();
4852
RuleSarif ruleSarif = sarifRef.get();
4953

5054
// verify the rule sarif has the right stuff
51-
assertThat(ruleSarif.getRule()).isEqualTo("SA2813462719");
55+
assertThat(ruleSarif.getRule()).isEqualTo("SQL Injection");
5256
assertThat(ruleSarif.getDriver()).isEqualTo("HCL AppScan Static Analyzer");
5357
assertThat(ruleSarif.rawDocument()).isEqualTo(rawSarif);
5458

plugins/codemodder-plugin-codeql/src/main/java/io/codemodder/providers/sarif/codeql/CodeQLRuleSarifFactory.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public final class CodeQLRuleSarifFactory implements RuleSarifFactory {
1313
public Optional<RuleSarif> build(
1414
final String toolName,
1515
final String rule,
16+
final String messageText,
1617
final SarifSchema210 sarif,
1718
final CodeDirectory codeDirectory) {
1819
if (CodeQLRuleSarif.toolName.equals(toolName)) {

plugins/codemodder-plugin-semgrep/src/main/java/io/codemodder/providers/sarif/semgrep/SemgrepRuleSarifFactory.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public class SemgrepRuleSarifFactory implements RuleSarifFactory {
1515
public Optional<RuleSarif> build(
1616
final String toolName,
1717
final String rule,
18+
final String messageText,
1819
final SarifSchema210 sarif,
1920
final CodeDirectory codeDirectory) {
2021

0 commit comments

Comments
 (0)