Skip to content

Commit 22caa90

Browse files
authored
✨ Support CodeTF Findings Without IDs (#443)
When a finding has no ID, we prefer to reflect this in CodeTF vs make up a new ID that is not significant to the tool that produced the finding. /towards ISS-1837
1 parent 1d589b3 commit 22caa90

File tree

5 files changed

+38
-57
lines changed

5 files changed

+38
-57
lines changed

core-codemods/src/main/java/io/codemodder/codemods/MavenSecureURLCodemod.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,7 @@ private CodemodFileScanningResult processXml(final Path file, final List<Result>
104104
})
105105
.findFirst();
106106
if (matchingResult.isPresent()) {
107-
String id =
108-
SarifFindingKeyUtil.buildFindingId(matchingResult.get(), file, line);
107+
String id = SarifFindingKeyUtil.buildFindingId(matchingResult.get());
109108
Integer sarifLine =
110109
matchingResult
111110
.get()

framework/codemodder-base/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ dependencies {
2121
api(libs.java.security.toolkit)
2222
api(libs.commons.lang3)
2323

24-
api("io.codemodder:codetf-java:4.1.3")
24+
api("io.codemodder:codetf-java:4.2.1")
2525
api(libs.slf4j.api)
2626
api(libs.javaparser.core)
2727
api(libs.javaparser.symbolsolver.core)
Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
package io.codemodder;
22

3-
import com.contrastsecurity.sarif.Fingerprints;
43
import com.contrastsecurity.sarif.Result;
5-
import java.nio.file.Path;
6-
import java.util.Collection;
7-
import java.util.HashMap;
8-
import java.util.Map;
94
import org.apache.commons.lang3.StringUtils;
105

116
/** Utility class for building keys for SARIF findings. */
@@ -14,27 +9,20 @@ public final class SarifFindingKeyUtil {
149
private SarifFindingKeyUtil() {}
1510

1611
/**
17-
* Builds a finding ID for a SARIF finding based on the provided result, file path, and line
18-
* number.
12+
* Builds a finding ID for a SARIF finding based on the provided result.
13+
*
14+
* <p>Individual results are identified by the {@code guid} property, if present. Multiple results
15+
* across scans are identified by the {@code correlationGuid} property. We prefer to identify the
16+
* result by its {@code guid} if present, and fall back to the {@code correlationGuid} if not. We
17+
* can be reasonably certain that the {@code correlationGuid} is unique within a single {@code
18+
* run}.
1919
*/
20-
public static String buildFindingId(final Result result, final Path path, final int line) {
21-
// prefer the guid, then the correlation guid
20+
public static String buildFindingId(final Result result) {
2221
if (!StringUtils.isBlank(result.getGuid())) {
2322
return result.getGuid().trim();
2423
} else if (!StringUtils.isBlank(result.getCorrelationGuid())) {
2524
return result.getCorrelationGuid().trim();
2625
}
27-
28-
// use a fingerprint, as at least that is some guarantee of uniqueness
29-
final Fingerprints fingerprints = result.getFingerprints();
30-
final Map<String, String> fingerPrintProperties =
31-
fingerprints != null ? fingerprints.getAdditionalProperties() : new HashMap<>();
32-
if (!fingerPrintProperties.isEmpty()) {
33-
Collection<String> values = fingerPrintProperties.values();
34-
return values.iterator().next();
35-
}
36-
37-
// ultimate fallback, some composite ID that will not represent anything
38-
return String.format("%s-%s-%d", result.getRuleId(), path.getFileName(), line);
26+
return null;
3927
}
4028
}

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

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,7 @@ public CodemodFileScanningResult visit(
134134
if (changeSuccessful.areChangesApplied()) {
135135
codemodChanges.add(
136136
buildCodemodChange(
137-
context.path(),
138-
region.start().line(),
139-
changeSuccessful.getDependenciesRequired(),
140-
result));
137+
region.start().line(), changeSuccessful.getDependenciesRequired(), result));
141138
}
142139
}
143140
}
@@ -149,17 +146,13 @@ public CodemodFileScanningResult visit(
149146
}
150147

151148
private CodemodChange buildCodemodChange(
152-
final Path path,
153-
final int line,
154-
final List<DependencyGAV> dependencies,
155-
final Result result) {
149+
final int line, final List<DependencyGAV> dependencies, final Result result) {
156150
if (this instanceof FixOnlyCodeChanger fixOnlyCodeChanger) {
157151
return CodemodChange.from(
158152
line,
159153
dependencies,
160154
new FixedFinding(
161-
SarifFindingKeyUtil.buildFindingId(result, path, line),
162-
fixOnlyCodeChanger.detectorRule()));
155+
SarifFindingKeyUtil.buildFindingId(result), fixOnlyCodeChanger.detectorRule()));
163156
}
164157

165158
return CodemodChange.from(line, dependencies);

framework/codemodder-base/src/test/java/io/codemodder/SarifFindingKeyUtilTest.java

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,39 @@
22

33
import static org.assertj.core.api.Assertions.assertThat;
44

5-
import com.contrastsecurity.sarif.Fingerprints;
65
import com.contrastsecurity.sarif.Result;
7-
import java.io.IOException;
8-
import java.nio.file.Files;
9-
import java.nio.file.Path;
6+
import org.junit.jupiter.api.BeforeEach;
107
import org.junit.jupiter.api.Test;
11-
import org.junit.jupiter.api.io.TempDir;
128

9+
/** Unit tests for {@link SarifFindingKeyUtil}. */
1310
final class SarifFindingKeyUtilTest {
1411

15-
@Test
16-
void it_creates_key(@TempDir final Path tmpDir) throws IOException {
17-
Path tmpFile = tmpDir.resolve("my-code.txt");
18-
Files.writeString(tmpFile, "my code");
12+
private Result result;
1913

20-
Result result = new Result();
14+
@BeforeEach
15+
void before() {
16+
result = new Result();
2117
result.setRuleId("my-rule");
18+
}
2219

23-
assertThat(SarifFindingKeyUtil.buildFindingId(result, tmpFile, 1))
24-
.isEqualTo("my-rule-my-code.txt-1");
25-
26-
Fingerprints fingerprints = new Fingerprints();
27-
fingerprints.setAdditionalProperty("my-key", "my-fingerprint-value");
28-
result.setFingerprints(fingerprints);
29-
assertThat(SarifFindingKeyUtil.buildFindingId(result, tmpFile, 1))
30-
.isEqualTo("my-fingerprint-value");
31-
32-
result.setCorrelationGuid(" my-correlation-guid ");
33-
assertThat(SarifFindingKeyUtil.buildFindingId(result, tmpFile, 1))
34-
.isEqualTo("my-correlation-guid");
20+
@Test
21+
void it_supports_findings_without_ids() {
22+
final var id = SarifFindingKeyUtil.buildFindingId(result);
23+
assertThat(id).isNull();
24+
}
3525

26+
@Test
27+
void it_prefers_guid() {
3628
result.setGuid("my-guid");
37-
assertThat(SarifFindingKeyUtil.buildFindingId(result, tmpFile, 1)).isEqualTo("my-guid");
29+
result.setCorrelationGuid("my-correlation-guid");
30+
final var id = SarifFindingKeyUtil.buildFindingId(result);
31+
assertThat(id).isEqualTo("my-guid");
32+
}
33+
34+
@Test
35+
void it_falls_back_to_correlation_guid() {
36+
result.setCorrelationGuid("my-correlation-guid");
37+
final var id = SarifFindingKeyUtil.buildFindingId(result);
38+
assertThat(id).isEqualTo("my-correlation-guid");
3839
}
3940
}

0 commit comments

Comments
 (0)