Skip to content

Commit f5eae64

Browse files
committed
adding other form of zip slip remediation
1 parent 0fd8818 commit f5eae64

File tree

18 files changed

+2733
-64
lines changed

18 files changed

+2733
-64
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public static List<Class<? extends CodeChanger>> asList() {
4343
CodeQLUnverifiedJwtCodemod.class,
4444
CodeQLXSSCodemod.class,
4545
CodeQLXXECodemod.class,
46+
CodeQLZipSlipHandler.class,
4647
DeclareVariableOnSeparateLineCodemod.class,
4748
DefectDojoSqlInjectionCodemod.class,
4849
DefineConstantForLiteralCodemod.class,
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package io.codemodder.codemods.codeql;
2+
3+
import com.contrastsecurity.sarif.Result;
4+
import com.github.javaparser.ast.CompilationUnit;
5+
import io.codemodder.*;
6+
import io.codemodder.codetf.DetectorRule;
7+
import io.codemodder.providers.sarif.codeql.ProvidedCodeQLScan;
8+
import io.codemodder.remediation.GenericRemediationMetadata;
9+
import io.codemodder.remediation.Remediator;
10+
import io.codemodder.remediation.zipslip.ZipSlipRemediator;
11+
import java.util.Optional;
12+
import javax.inject.Inject;
13+
14+
/** A codemod for automatically fixing Zip Slip issues from CodeQL. */
15+
@Codemod(
16+
id = "codeql:java/zipslip",
17+
reviewGuidance = ReviewGuidance.MERGE_AFTER_CURSORY_REVIEW,
18+
importance = Importance.HIGH,
19+
executionPriority = CodemodExecutionPriority.HIGH)
20+
public final class CodeQLZipSlipHandler extends CodeQLRemediationCodemod {
21+
22+
private final Remediator<Result> remediator;
23+
24+
@Inject
25+
public CodeQLZipSlipHandler(@ProvidedCodeQLScan(ruleId = "java/zipslip") final RuleSarif sarif) {
26+
super(GenericRemediationMetadata.ZIP_SLIP.reporter(), sarif);
27+
this.remediator = new ZipSlipRemediator<>();
28+
}
29+
30+
@Override
31+
public DetectorRule detectorRule() {
32+
return new DetectorRule(
33+
"zipslip",
34+
"Arbitrary file access during archive extraction (\"Zip Slip\")\n",
35+
"https://codeql.github.com/codeql-query-help/java/java-zipslip/");
36+
}
37+
38+
@Override
39+
public CodemodFileScanningResult visit(
40+
final CodemodInvocationContext context, final CompilationUnit cu) {
41+
return remediator.remediateAll(
42+
cu,
43+
context.path().toString(),
44+
detectorRule(),
45+
ruleSarif.getResultsByLocationPath(context.path()),
46+
SarifFindingKeyUtil::buildFindingId,
47+
r -> r.getLocations().get(0).getPhysicalLocation().getRegion().getStartLine(),
48+
r -> Optional.of(r.getLocations().get(0).getPhysicalLocation().getRegion().getEndLine()),
49+
r ->
50+
Optional.of(
51+
r.getLocations().get(0).getPhysicalLocation().getRegion().getStartColumn()));
52+
}
53+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package io.codemodder.codemods.codeql;
2+
3+
import io.codemodder.testutils.CodemodTestMixin;
4+
import io.codemodder.testutils.Metadata;
5+
6+
@Metadata(
7+
codemodType = CodeQLZipSlipHandler.class,
8+
testResourceDir = "codeql-zipslip",
9+
renameTestFile = "Path Traversal/ZipTraversal.java",
10+
expectingFixesAtLines = {11},
11+
dependencies = {})
12+
final class CodeQLZipSlipHandlerTest implements CodemodTestMixin {}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import java.util.zip.ZipFile;
2+
import java.util.zip.ZipEntry;
3+
class Foo { // added this to make this a valid file for testing
4+
public void extract(ZipFile zip) {
5+
6+
String toDir = "/my/target/directory/";
7+
Enumeration entries = zip.entries();
8+
while (entries.hasMoreElements()) {
9+
ZipEntry zipEntry = entries.nextElement();
10+
11+
File file = new File(toDir, sanitizeZipFilename(zipEntry.getName()));
12+
InputStream istr = zipFile.getInputStream(zipEntry);
13+
final OutputStream os = Files.newOutputStream(file.toPath());
14+
bos = new BufferedOutputStream(os);
15+
IOUtils.copy(bis, bos);
16+
17+
}
18+
}
19+
20+
String sanitizeZipFilename(String entryName) {
21+
if (entryName == null || entryName.trim().isEmpty()) {
22+
return entryName;
23+
}
24+
while (entryName.contains("../") || entryName.contains("..\\")) {
25+
entryName = entryName.replace("../", "").replace("..\\", "");
26+
}
27+
return entryName;
28+
}
29+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import java.util.zip.ZipFile;
2+
import java.util.zip.ZipEntry;
3+
class Foo { // added this to make this a valid file for testing
4+
public void extract(ZipFile zip) {
5+
6+
String toDir = "/my/target/directory/";
7+
Enumeration entries = zip.entries();
8+
while (entries.hasMoreElements()) {
9+
ZipEntry zipEntry = entries.nextElement();
10+
11+
File file = new File(toDir, zipEntry.getName());
12+
InputStream istr = zipFile.getInputStream(zipEntry);
13+
final OutputStream os = Files.newOutputStream(file.toPath());
14+
bos = new BufferedOutputStream(os);
15+
IOUtils.copy(bis, bos);
16+
17+
}
18+
}
19+
}

0 commit comments

Comments
 (0)