CVE-2024-24042: Insufficient Information (NVD-CWE-noinfo)
value: Directory Traversal vulnerability in Devan-Kerman ARRP v.0.8.1 and before allows a remote attacker to execute arbitrary code via the dumpDirect in RuntimeResourcePackImpl component.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-03-19T07:15Z
Repository: https://github.com/Devan-Kerman/ARRP
Language: Java
Files changed: gradle.properties, src/main/java/net/devtech/arrp/impl/RuntimeResourcePackImpl.java, src/test/java/test/RRPPreTest.java
Commit date: 2024-01-08 19:01:54 -0600
Commit message: oops v0.8.2

Diff: diff --git a/gradle.properties b/gradle.properties
index a26da17..6fb762f 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -6,9 +6,9 @@ loader_version=0.14.21
 
 #Fabric api
 fabric_version=0.84.0+1.20.1
 
 # Mod Properties
-mod_version=0.8.0
+mod_version=0.8.1
 maven_group=net.devtech
 archives_base_name=arrp
 # Dependencies
diff --git a/src/main/java/net/devtech/arrp/impl/RuntimeResourcePackImpl.java b/src/main/java/net/devtech/arrp/impl/RuntimeResourcePackImpl.java
index ecf0ba6..c545df4 100644
--- a/src/main/java/net/devtech/arrp/impl/RuntimeResourcePackImpl.java
+++ b/src/main/java/net/devtech/arrp/impl/RuntimeResourcePackImpl.java
@@ -301,11 +301,11 @@ public class RuntimeResourcePackImpl implements RuntimeResourcePack, ResourcePac
 		// data dump time
 		try {
 			for(Map.Entry<List<String>, Supplier<byte[]>> e : this.root.entrySet()) {
 				String pathStr = String.join("/", e.getKey());
 				Path path = output.resolve(pathStr);
-				if(path.startsWith(output)) {
+				if(path.toAbsolutePath().startsWith(output.toAbsolutePath())) {
 					Files.createDirectories(path.getParent());
 					Files.write(path, e.getValue().get());
 				} else {
 					LOGGER.error("RRP contains out-of-directory path! \"" + pathStr + "\"");
 				}
@@ -552,11 +552,11 @@ public class RuntimeResourcePackImpl implements RuntimeResourcePack, ResourcePac
 	private void write(Path dir, Identifier identifier, byte[] data) {
 		try {
 			String namespace = identifier.getNamespace();
 			String path = identifier.getPath();
 			Path file = dir.resolve(namespace).resolve(path);
-			if(file.startsWith(dir)) {
+			if(file.toAbsolutePath().startsWith(dir.toAbsolutePath())) {
 				Files.createDirectories(file.getParent());
 				try(OutputStream output = Files.newOutputStream(file)) {
 					output.write(data);
 				}
 			} else {
diff --git a/src/test/java/test/RRPPreTest.java b/src/test/java/test/RRPPreTest.java
index a33f14a..ab88905 100644
--- a/src/test/java/test/RRPPreTest.java
+++ b/src/test/java/test/RRPPreTest.java
@@ -14,10 +14,11 @@ import static net.devtech.arrp.json.models.JModel.faces;
 import static net.devtech.arrp.json.models.JModel.model;
 import static net.devtech.arrp.json.models.JModel.textures;
 
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
+import net.devtech.arrp.api.RuntimeResourcePack;
 import net.devtech.arrp.impl.RuntimeResourcePackImpl;
 import net.devtech.arrp.json.blockstate.JMultipart;
 import net.devtech.arrp.json.blockstate.JState;
 import net.devtech.arrp.json.blockstate.JVariant;
 import net.devtech.arrp.json.blockstate.JWhen;
@@ -25,13 +26,18 @@ import net.devtech.arrp.json.lang.JLang;
 import net.devtech.arrp.json.models.JModel;
 import net.devtech.arrp.json.models.JTextures;
 
 import net.minecraft.util.Identifier;
 import net.minecraft.util.math.Direction;
+import java.nio.file.Path;
 
 public class RRPPreTest {
 	public static void main(String[] args) {
+		RuntimeResourcePack pack = RuntimeResourcePack.create("test:test");
+		pack.addLang(new Identifier("aaaa:aaaa"), new JLang().entry("aaaa", "bbbbb"));
+		pack.dumpDirect(Path.of("aaaa"));
+
 		JState iron_block = state(variant(JState.model("block/iron_block")));
 		JState oak_fence = state(multipart(JState.model("block/oak_fence_post")),
 				multipart(JState.model("block/oak_fence_side").uvlock()).when(when().add("north", "true")),
 				multipart(JState.model("block/oak_fence_side").y(90).uvlock()).when(when().add("east", "true")),
 				multipart(JState.model("block/oak_fence_side").y(180).uvlock()).when(when().add("south", "true")),
@@ -45,10 +51,12 @@ public class RRPPreTest {
 		                                                      .north(face("all").uv(9, 0, 11, 16))
 		                                                      .south(face("all").uv(9, 0, 11, 16))
 		                                                      .west(face("all").uv(9, 0, 11, 16))
 		                                                      .east(face("all").uv(9, 0, 11, 16))));
 
+
+
 		Gson gson = new GsonBuilder().registerTypeAdapter(JMultipart.class, new JMultipart.Serializer())
 		                             .registerTypeAdapter(JWhen.class, new JWhen.Serializer())
 		                             .registerTypeAdapter(JState.class, new JState.Serializer())
 		                             .registerTypeAdapter(JVariant.class, new JVariant.Serializer())
 		                             .registerTypeAdapter(JTextures.class, new JTextures.Serializer())

Vulnerable code: mod_version=0.8.0
				if(path.startsWith(output)) {
			if(file.startsWith(dir)) {
Fixed code: mod_version=0.8.1
				if(path.toAbsolutePath().startsWith(output.toAbsolutePath())) {
			if(file.toAbsolutePath().startsWith(dir.toAbsolutePath())) {
import net.devtech.arrp.api.RuntimeResourcePack;
import java.nio.file.Path;
		RuntimeResourcePack pack = RuntimeResourcePack.create("test:test");
		pack.addLang(new Identifier("aaaa:aaaa"), new JLang().entry("aaaa", "bbbbb"));
		pack.dumpDirect(Path.of("aaaa"));