Skip to content

Commit 189133b

Browse files
carlosu7nahsra
andauthored
Populate detectionTool metadata for CodeQL codemods (#356)
add finding to CodeQL codemods issue #313 --------- Co-authored-by: Arshan Dabirsiaghi <[email protected]>
1 parent a9d8d95 commit 189133b

File tree

12 files changed

+210
-23
lines changed

12 files changed

+210
-23
lines changed

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import com.github.javaparser.ast.CompilationUnit;
55
import com.github.javaparser.ast.expr.Expression;
66
import io.codemodder.*;
7+
import io.codemodder.codetf.DetectorRule;
78
import io.codemodder.javaparser.ChangesResult;
9+
import io.codemodder.providers.sarif.codeql.CodeQLSarifJavaParserChanger;
810
import io.codemodder.providers.sarif.codeql.ProvidedCodeQLScan;
911
import javax.inject.Inject;
1012

@@ -17,7 +19,7 @@
1719
reviewGuidance = ReviewGuidance.MERGE_WITHOUT_REVIEW,
1820
importance = Importance.MEDIUM,
1921
executionPriority = CodemodExecutionPriority.HIGH)
20-
public final class InputResourceLeakCodemod extends SarifPluginJavaParserChanger<Expression> {
22+
public final class InputResourceLeakCodemod extends CodeQLSarifJavaParserChanger<Expression> {
2123

2224
@Inject
2325
public InputResourceLeakCodemod(
@@ -35,4 +37,12 @@ public ChangesResult onResultFound(
3537
? ChangesResult.changesApplied
3638
: ChangesResult.noChanges;
3739
}
40+
41+
@Override
42+
public DetectorRule detectorRule() {
43+
return new DetectorRule(
44+
"input-resource-leak",
45+
"Prevent resource leaks",
46+
"https://codeql.github.com/codeql-query-help/java/java-input-resource-leak/");
47+
}
3848
}

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
import com.github.javaparser.ast.stmt.Statement;
1111
import io.codemodder.*;
1212
import io.codemodder.ast.ASTTransforms;
13+
import io.codemodder.codetf.DetectorRule;
1314
import io.codemodder.javaparser.ChangesResult;
15+
import io.codemodder.providers.sarif.codeql.CodeQLSarifJavaParserChanger;
1416
import io.codemodder.providers.sarif.codeql.ProvidedCodeQLScan;
1517
import java.util.Optional;
1618
import javax.inject.Inject;
@@ -21,7 +23,7 @@
2123
reviewGuidance = ReviewGuidance.MERGE_WITHOUT_REVIEW,
2224
importance = Importance.LOW,
2325
executionPriority = CodemodExecutionPriority.HIGH)
24-
public class InsecureCookieCodemod extends SarifPluginJavaParserChanger<MethodCallExpr> {
26+
public final class InsecureCookieCodemod extends CodeQLSarifJavaParserChanger<MethodCallExpr> {
2527

2628
@Inject
2729
public InsecureCookieCodemod(
@@ -61,4 +63,12 @@ public ChangesResult onResultFound(
6163
}
6264
return ChangesResult.noChanges;
6365
}
66+
67+
@Override
68+
public DetectorRule detectorRule() {
69+
return new DetectorRule(
70+
"insecure-cookie",
71+
"Add secure flag to HTTP cookies",
72+
"https://codeql.github.com/codeql-query-help/java/java-input-resource-leak/");
73+
}
6474
}

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import com.github.javaparser.ast.CompilationUnit;
55
import com.github.javaparser.ast.expr.MethodCallExpr;
66
import io.codemodder.*;
7+
import io.codemodder.codetf.DetectorRule;
78
import io.codemodder.javaparser.ChangesResult;
9+
import io.codemodder.providers.sarif.codeql.CodeQLSarifJavaParserChanger;
810
import io.codemodder.providers.sarif.codeql.ProvidedCodeQLScan;
911
import javax.inject.Inject;
1012

@@ -17,7 +19,7 @@
1719
reviewGuidance = ReviewGuidance.MERGE_WITHOUT_REVIEW,
1820
importance = Importance.MEDIUM,
1921
executionPriority = CodemodExecutionPriority.HIGH)
20-
public final class JDBCResourceLeakCodemod extends SarifPluginJavaParserChanger<MethodCallExpr> {
22+
public final class JDBCResourceLeakCodemod extends CodeQLSarifJavaParserChanger<MethodCallExpr> {
2123

2224
@Inject
2325
public JDBCResourceLeakCodemod(
@@ -35,4 +37,12 @@ public ChangesResult onResultFound(
3537
? ChangesResult.changesApplied
3638
: ChangesResult.noChanges;
3739
}
40+
41+
@Override
42+
public DetectorRule detectorRule() {
43+
return new DetectorRule(
44+
"database-resource-leak",
45+
"Prevent database resource leaks (CodeQL)",
46+
"https://codeql.github.com/codeql-query-help/java/java-database-resource-leak/");
47+
}
3848
}

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
import io.codemodder.*;
1818
import io.codemodder.ast.ASTTransforms;
1919
import io.codemodder.ast.ASTs;
20+
import io.codemodder.codetf.DetectorRule;
2021
import io.codemodder.javaparser.ChangesResult;
22+
import io.codemodder.providers.sarif.codeql.CodeQLSarifJavaParserChanger;
2123
import io.codemodder.providers.sarif.codeql.ProvidedCodeQLScan;
2224
import io.github.pixee.security.UnwantedTypes;
2325
import java.util.List;
@@ -36,7 +38,7 @@
3638
reviewGuidance = ReviewGuidance.MERGE_WITHOUT_REVIEW,
3739
importance = Importance.MEDIUM,
3840
executionPriority = CodemodExecutionPriority.HIGH)
39-
public final class JEXLInjectionCodemod extends SarifPluginJavaParserChanger<Expression> {
41+
public final class JEXLInjectionCodemod extends CodeQLSarifJavaParserChanger<Expression> {
4042

4143
@Inject
4244
public JEXLInjectionCodemod(
@@ -175,4 +177,12 @@ private static Optional<MethodCallExpr> findJEXLBuilderCreate(final MethodCallEx
175177
}
176178
return Optional.empty();
177179
}
180+
181+
@Override
182+
public DetectorRule detectorRule() {
183+
return new DetectorRule(
184+
"jexl-expression-injection",
185+
"Expression language injection",
186+
"https://codeql.github.com/codeql-query-help/java/java-jexl-expression-injection/");
187+
}
178188
}

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

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package io.codemodder.codemods;
22

3+
import com.contrastsecurity.sarif.Region;
34
import com.contrastsecurity.sarif.Result;
45
import io.codemodder.*;
6+
import io.codemodder.codetf.DetectorRule;
7+
import io.codemodder.codetf.FixedFinding;
58
import io.codemodder.providers.sarif.codeql.ProvidedCodeQLScan;
69
import java.io.IOException;
710
import java.nio.file.Files;
@@ -11,7 +14,6 @@
1114
import java.util.Objects;
1215
import java.util.Optional;
1316
import java.util.Set;
14-
import java.util.stream.Collectors;
1517
import javax.inject.Inject;
1618
import javax.xml.stream.XMLEventFactory;
1719
import javax.xml.stream.XMLEventReader;
@@ -29,7 +31,8 @@
2931
reviewGuidance = ReviewGuidance.MERGE_WITHOUT_REVIEW,
3032
importance = Importance.MEDIUM,
3133
executionPriority = CodemodExecutionPriority.HIGH)
32-
public final class MavenSecureURLCodemod extends SarifPluginRawFileChanger {
34+
public final class MavenSecureURLCodemod extends SarifPluginRawFileChanger
35+
implements FixOnlyCodeChanger {
3336

3437
private final XPathStreamProcessor processor;
3538

@@ -41,18 +44,31 @@ public final class MavenSecureURLCodemod extends SarifPluginRawFileChanger {
4144
this.processor = Objects.requireNonNull(processor);
4245
}
4346

47+
@Override
48+
public String vendorName() {
49+
return "CodeQL";
50+
}
51+
52+
@Override
53+
public DetectorRule detectorRule() {
54+
return new DetectorRule(
55+
"non-https-url",
56+
"Failure to use HTTPS or SFTP URL in Maven artifact upload/download",
57+
"https://codeql.github.com/codeql-query-help/java/java-maven-non-https-url");
58+
}
59+
4460
@Override
4561
public CodemodFileScanningResult onFileFound(
4662
final CodemodInvocationContext context, final List<Result> results) {
4763
try {
48-
return processXml(context.path());
64+
return processXml(context.path(), results);
4965
} catch (SAXException | DocumentException | IOException | XMLStreamException e) {
5066
LOG.error("Problem transforming xml file: {}", context.path());
5167
return CodemodFileScanningResult.none();
5268
}
5369
}
5470

55-
private CodemodFileScanningResult processXml(final Path file)
71+
private CodemodFileScanningResult processXml(final Path file, final List<Result> results)
5672
throws SAXException, IOException, DocumentException, XMLStreamException {
5773
Optional<XPathStreamProcessChange> change =
5874
processor.process(
@@ -70,7 +86,31 @@ private CodemodFileScanningResult processXml(final Path file)
7086
Set<Integer> linesAffected = xmlChange.linesAffected();
7187

7288
List<CodemodChange> allWeaves =
73-
linesAffected.stream().map(CodemodChange::from).collect(Collectors.toList());
89+
linesAffected.stream()
90+
.map(
91+
line -> {
92+
Optional<Result> matchingResult =
93+
results.stream()
94+
.filter(
95+
result -> {
96+
Region region =
97+
result.getLocations().get(0).getPhysicalLocation().getRegion();
98+
Integer resultStartLine = region.getStartLine();
99+
Integer resultEndLine = region.getEndLine();
100+
return resultStartLine == line
101+
|| (resultStartLine <= line
102+
&& resultEndLine != null
103+
&& resultEndLine >= line);
104+
})
105+
.findFirst();
106+
if (matchingResult.isPresent()) {
107+
String id =
108+
SarifFindingKeyUtil.buildFindingId(matchingResult.get(), file, line);
109+
return CodemodChange.from(line, new FixedFinding(id, detectorRule()));
110+
}
111+
return CodemodChange.from(line);
112+
})
113+
.toList();
74114

75115
// overwrite the previous web.xml with the new one
76116
Files.copy(xmlChange.transformedXml(), file, StandardCopyOption.REPLACE_EXISTING);

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import com.github.javaparser.ast.CompilationUnit;
55
import com.github.javaparser.ast.expr.Expression;
66
import io.codemodder.*;
7+
import io.codemodder.codetf.DetectorRule;
78
import io.codemodder.javaparser.ChangesResult;
9+
import io.codemodder.providers.sarif.codeql.CodeQLSarifJavaParserChanger;
810
import io.codemodder.providers.sarif.codeql.ProvidedCodeQLScan;
911
import javax.inject.Inject;
1012

@@ -17,7 +19,7 @@
1719
reviewGuidance = ReviewGuidance.MERGE_WITHOUT_REVIEW,
1820
importance = Importance.MEDIUM,
1921
executionPriority = CodemodExecutionPriority.HIGH)
20-
public final class OutputResourceLeakCodemod extends SarifPluginJavaParserChanger<Expression> {
22+
public final class OutputResourceLeakCodemod extends CodeQLSarifJavaParserChanger<Expression> {
2123

2224
@Inject
2325
public OutputResourceLeakCodemod(
@@ -35,4 +37,12 @@ public ChangesResult onResultFound(
3537
? ChangesResult.changesApplied
3638
: ChangesResult.noChanges;
3739
}
40+
41+
@Override
42+
public DetectorRule detectorRule() {
43+
return new DetectorRule(
44+
"output-resource-leak",
45+
"Prevent resource leaks",
46+
"https://codeql.github.com/codeql-query-help/java/java-output-resource-leak/");
47+
}
3848
}

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
import com.github.javaparser.ast.expr.MethodCallExpr;
88
import io.codemodder.*;
99
import io.codemodder.ast.ASTs;
10+
import io.codemodder.codetf.DetectorRule;
1011
import io.codemodder.javaparser.ChangesResult;
12+
import io.codemodder.providers.sarif.codeql.CodeQLSarifJavaParserChanger;
1113
import io.codemodder.providers.sarif.codeql.ProvidedCodeQLScan;
1214
import javax.inject.Inject;
1315

@@ -17,7 +19,7 @@
1719
reviewGuidance = ReviewGuidance.MERGE_WITHOUT_REVIEW,
1820
importance = Importance.MEDIUM,
1921
executionPriority = CodemodExecutionPriority.HIGH)
20-
public class StackTraceExposureCodemod extends SarifPluginJavaParserChanger<Expression> {
22+
public final class StackTraceExposureCodemod extends CodeQLSarifJavaParserChanger<Expression> {
2123

2224
@Inject
2325
public StackTraceExposureCodemod(
@@ -51,4 +53,12 @@ public ChangesResult onResultFound(
5153
// cover the most common usage
5254
return ChangesResult.noChanges;
5355
}
56+
57+
@Override
58+
public DetectorRule detectorRule() {
59+
return new DetectorRule(
60+
"stack-trace-exposure",
61+
"Prevent information leak of stack trace details to HTTP responses",
62+
"https://codeql.github.com/codeql-query-help/java/java-stack-trace-exposure/");
63+
}
5464
}

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
import io.codemodder.ast.ASTTransforms;
1010
import io.codemodder.ast.ASTs;
1111
import io.codemodder.ast.LocalVariableDeclaration;
12+
import io.codemodder.codetf.DetectorRule;
1213
import io.codemodder.javaparser.ChangesResult;
14+
import io.codemodder.providers.sarif.codeql.CodeQLSarifJavaParserChanger;
1315
import io.codemodder.providers.sarif.codeql.ProvidedCodeQLScan;
1416
import javax.inject.Inject;
1517

@@ -19,7 +21,7 @@
1921
reviewGuidance = ReviewGuidance.MERGE_WITHOUT_REVIEW,
2022
importance = Importance.MEDIUM,
2123
executionPriority = CodemodExecutionPriority.HIGH)
22-
public class UnverifiedJwtCodemod extends SarifPluginJavaParserChanger<Expression> {
24+
public final class UnverifiedJwtCodemod extends CodeQLSarifJavaParserChanger<Expression> {
2325

2426
@Inject
2527
public UnverifiedJwtCodemod(
@@ -94,4 +96,12 @@ public ChangesResult onResultFound(
9496

9597
return ChangesResult.noChanges;
9698
}
99+
100+
@Override
101+
public DetectorRule detectorRule() {
102+
return new DetectorRule(
103+
"missing-jwt-signature-check",
104+
"Switch JWT calls to versions that enforce signature validity",
105+
"https://codeql.github.com/codeql-query-help/java/java-missing-jwt-signature-check/");
106+
}
97107
}

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

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,35 @@
66
import java.util.Collection;
77
import java.util.HashMap;
88
import java.util.Map;
9+
import org.apache.commons.lang3.StringUtils;
910

1011
/** Utility class for building keys for SARIF findings. */
11-
final class SarifFindingKeyUtil {
12+
public final class SarifFindingKeyUtil {
1213

1314
private SarifFindingKeyUtil() {}
1415

15-
/** Builds a key for a SARIF finding based on the provided result, file path, and line number. */
16-
public static String buildKey(final Result result, final Path path, final int line) {
17-
final Fingerprints fingerprints = result.getFingerprints();
16+
/**
17+
* Builds a finding ID for a SARIF finding based on the provided result, file path, and line
18+
* number.
19+
*/
20+
public static String buildFindingId(final Result result, final Path path, final int line) {
21+
// prefer the guid, then the correlation guid
22+
if (!StringUtils.isBlank(result.getGuid())) {
23+
return result.getGuid().trim();
24+
} else if (!StringUtils.isBlank(result.getCorrelationGuid())) {
25+
return result.getCorrelationGuid().trim();
26+
}
1827

28+
// use a fingerprint, as at least that is some guarantee of uniqueness
29+
final Fingerprints fingerprints = result.getFingerprints();
1930
final Map<String, String> fingerPrintProperties =
2031
fingerprints != null ? fingerprints.getAdditionalProperties() : new HashMap<>();
21-
22-
if (fingerPrintProperties.isEmpty()) {
23-
return String.format("%s-%s-%d", result.getRuleId(), path.getFileName(), line);
32+
if (!fingerPrintProperties.isEmpty()) {
33+
Collection<String> values = fingerPrintProperties.values();
34+
return values.iterator().next();
2435
}
2536

26-
Collection<String> values = fingerPrintProperties.values();
27-
28-
return values.iterator().next();
37+
// ultimate fallback, some composite ID that will not represent anything
38+
return String.format("%s-%s-%d", result.getRuleId(), path.getFileName(), line);
2939
}
3040
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,8 @@ private CodemodChange buildCodemodChange(
159159
line,
160160
dependencies,
161161
new FixedFinding(
162-
SarifFindingKeyUtil.buildKey(result, path, line), fixOnlyCodeChanger.detectorRule()));
162+
SarifFindingKeyUtil.buildFindingId(result, path, line),
163+
fixOnlyCodeChanger.detectorRule()));
163164
}
164165

165166
return CodemodChange.from(line, dependencies);

0 commit comments

Comments
 (0)