Skip to content

Maintenance release for Usagi#2

Open
janblom wants to merge 28 commits intomasterfrom
add-tests-for-bekeley-db-using-junie
Open

Maintenance release for Usagi#2
janblom wants to merge 28 commits intomasterfrom
add-tests-for-bekeley-db-using-junie

Conversation

@janblom
Copy link
Copy Markdown

@janblom janblom commented Feb 23, 2026

  • replaced Ant (build tool) by Maven
  • updated minor dependency versions, and major when possible
  • checked for, and eliminated, known vulnerabilities
  • added unit and integration tests (based on junit, assertj-swing and cacio-tta)
  • updated README.md

@janblom janblom self-assigned this Feb 23, 2026
@janblom janblom force-pushed the add-tests-for-bekeley-db-using-junie branch from aa13a49 to d6d7689 Compare February 23, 2026 16:36
try (ZipInputStream zis = new ZipInputStream(is)) {
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
File newFile = new File(targetDir.toFile(), entry.getName());

Check failure

Code scanning / CodeQL

Arbitrary file access during archive extraction ("Zip Slip")

Unsanitized archive entry, which may contain '..', is used in a [file system operation](1). Unsanitized archive entry, which may contain '..', is used in a [file system operation](2). Unsanitized archive entry, which may contain '..', is used in a [file system operation](3).

Copilot Autofix

AI about 1 month ago

To fix the issue, every ZipEntry destination path must be normalized and verified to remain within targetDir before any filesystem operation (directory creation or file writing) is performed. This prevents archive entries with .. or absolute paths from escaping the extraction root.

Concretely, in unzipResource we should:

  • Convert targetDir to an absolute, normalized Path once (e.g., Path targetDirNormalized = targetDir.toAbsolutePath().normalize();).
  • For each ZipEntry, resolve its name against targetDirNormalized (Path resolvedPath = targetDirNormalized.resolve(entry.getName()).normalize();).
  • Check that resolvedPath starts with targetDirNormalized using Path.startsWith. If not, throw an IOException (or skip the entry).
  • Use this safe resolvedPath (converted to File if needed) for mkdirs, getParentFile, and FileOutputStream.

We can keep the existing imports; we already import java.nio.file.Path and java.nio.file.Files, and we do not need any external libraries. The main code change is around line 21: replace the direct new File(targetDir.toFile(), entry.getName()) construction with the normalized Path approach and then derive a File from it. Also, we should ensure that directory creation uses Files.createDirectories (or keep mkdirs via File if we prefer), but the critical part is that all operations use the validated path.

Suggested changeset 1
src/test/java/org/ohdsi/usagi/TestUtils.java

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/test/java/org/ohdsi/usagi/TestUtils.java b/src/test/java/org/ohdsi/usagi/TestUtils.java
--- a/src/test/java/org/ohdsi/usagi/TestUtils.java
+++ b/src/test/java/org/ohdsi/usagi/TestUtils.java
@@ -11,6 +11,7 @@
 
 public class TestUtils {
     public static void unzipResource(String resourceName, Path targetDir) throws IOException {
+        Path targetDirNormalized = targetDir.toAbsolutePath().normalize();
         try (InputStream is = TestUtils.class.getResourceAsStream(resourceName)) {
             if (is == null) {
                 throw new IOException("Resource not found: " + resourceName);
@@ -18,7 +19,11 @@
             try (ZipInputStream zis = new ZipInputStream(is)) {
                 ZipEntry entry;
                 while ((entry = zis.getNextEntry()) != null) {
-                    File newFile = new File(targetDir.toFile(), entry.getName());
+                    Path resolvedPath = targetDirNormalized.resolve(entry.getName()).normalize();
+                    if (!resolvedPath.startsWith(targetDirNormalized)) {
+                        throw new IOException("Entry is outside of the target dir: " + entry.getName());
+                    }
+                    File newFile = resolvedPath.toFile();
                     if (entry.isDirectory()) {
                         newFile.mkdirs();
                     } else {
EOF
@@ -11,6 +11,7 @@

public class TestUtils {
public static void unzipResource(String resourceName, Path targetDir) throws IOException {
Path targetDirNormalized = targetDir.toAbsolutePath().normalize();
try (InputStream is = TestUtils.class.getResourceAsStream(resourceName)) {
if (is == null) {
throw new IOException("Resource not found: " + resourceName);
@@ -18,7 +19,11 @@
try (ZipInputStream zis = new ZipInputStream(is)) {
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
File newFile = new File(targetDir.toFile(), entry.getName());
Path resolvedPath = targetDirNormalized.resolve(entry.getName()).normalize();
if (!resolvedPath.startsWith(targetDirNormalized)) {
throw new IOException("Entry is outside of the target dir: " + entry.getName());
}
File newFile = resolvedPath.toFile();
if (entry.isDirectory()) {
newFile.mkdirs();
} else {
Copilot is powered by AI and may make mistakes. Always verify output.
@janblom janblom committed this autofix suggestion about 1 month ago.
@janblom janblom force-pushed the add-tests-for-bekeley-db-using-junie branch from 4975ccc to 83802f1 Compare March 5, 2026 08:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants