Skip to content

Commit 9661375

Browse files
committed
fix: CVE-2022-41967
Dragonfly v0.3.0-SNAPSHOT fails to properly configure the DocumentBuilderFactory to prevent XML enternal entity (XXE) attacks when parsing maven-metadata.xml files provided by external Maven repositories during "SNAPSHOT" version resolution. This patches CVE-2022-41967 by disabling features which may lead to XXE. If you are currently using v0.3.0-SNAPSHOT it is STRONGLY advised to update Dragonfly to v0.3.1-SNAPSHOT just to be safe.
1 parent 887c489 commit 9661375

18 files changed

+110
-71
lines changed

Diff for: AUTHORS

-8
This file was deleted.

Diff for: LICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2021 Joshua Sing <joshua@hypera.dev>
3+
Copyright (c) 2021-2022 Joshua Sing <joshua@hypera.dev>
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

Diff for: SECURITY.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77

88
### Supported Versions
99
| Version | Supported |
10-
| ------- | ------------------ |
11-
| 0.3.0 | :white_check_mark: |
10+
|---------| ------------------ |
11+
| 0.3.x | :white_check_mark: |
1212
| < 0.3 | :x: |
1313

1414
### Reporting a Vulnerability

Diff for: pom.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
<groupId>dev.hypera</groupId>
3131
<artifactId>Dragonfly</artifactId>
32-
<version>0.3.0-SNAPSHOT</version>
32+
<version>0.3.1-SNAPSHOT</version>
3333
<packaging>jar</packaging>
3434

3535
<name>Dragonfly</name>
@@ -121,7 +121,7 @@
121121
<dependency>
122122
<groupId>org.jetbrains</groupId>
123123
<artifactId>annotations</artifactId>
124-
<version>22.0.0</version>
124+
<version>23.1.0</version>
125125
</dependency>
126126
<dependency>
127127
<groupId>me.lucko</groupId>

Diff for: src/main/java/dev/hypera/dragonfly/Dragonfly.java

+13-12
Original file line numberDiff line numberDiff line change
@@ -40,23 +40,24 @@
4040
import java.util.function.Consumer;
4141
import java.util.stream.Collectors;
4242
import org.jetbrains.annotations.ApiStatus.Internal;
43+
import org.jetbrains.annotations.NotNull;
4344

4445
/**
4546
* Main Dragonfly class.
4647
* @author Joshua Sing <joshua@hypera.dev>
4748
*/
4849
public class Dragonfly {
4950

50-
private static final String VERSION = "0.3.0-SNAPSHOT";
51+
private static final @NotNull String VERSION = "0.3.1-SNAPSHOT";
5152

5253
private final int timeout;
53-
private final Path directory;
54-
private final Set<String> repositories;
55-
private final Consumer<Status> statusHandler;
54+
private final @NotNull Path directory;
55+
private final @NotNull Set<String> repositories;
56+
private final @NotNull Consumer<Status> statusHandler;
5657

57-
private final DependencyDownloader dependencyDownloader = new DependencyDownloader(this);
58-
private final DependencyRelocator dependencyRelocator;
59-
private final DependencyLoader dependencyLoader;
58+
private final @NotNull DependencyDownloader dependencyDownloader = new DependencyDownloader(this);
59+
private final @NotNull DependencyRelocator dependencyRelocator;
60+
private final @NotNull DependencyLoader dependencyLoader;
6061

6162

6263
@Internal
@@ -74,7 +75,7 @@ protected Dragonfly(int timeout, IClassLoader classLoader, Path directory, Set<S
7475
}
7576
}
7677

77-
public static String getVersion() {
78+
public static @NotNull String getVersion() {
7879
return VERSION;
7980
}
8081

@@ -84,7 +85,7 @@ public static String getVersion() {
8485
* @param dependencies Dependencies to be loaded.
8586
* @return If the load was successful, in the form of a {@link CompletableFuture<Boolean>}.
8687
*/
87-
public CompletableFuture<Boolean> load(Dependency... dependencies) {
88+
public @NotNull CompletableFuture<Boolean> load(@NotNull Dependency... dependencies) {
8889
return CompletableFuture.supplyAsync(() -> {
8990
try {
9091
statusHandler.accept(Status.STARTING);
@@ -137,11 +138,11 @@ public int getTimeout() {
137138
return timeout;
138139
}
139140

140-
public Path getDirectory() {
141+
public @NotNull Path getDirectory() {
141142
return directory;
142143
}
143144

144-
public Set<String> getRepositories() {
145+
public @NotNull Set<String> getRepositories() {
145146
return repositories;
146147
}
147148

@@ -151,7 +152,7 @@ public Set<String> getRepositories() {
151152
* @return Stored instance of {@link DependencyDownloader}.
152153
*/
153154
@Internal
154-
public DependencyDownloader getDependencyDownloader() {
155+
public @NotNull DependencyDownloader getDependencyDownloader() {
155156
return dependencyDownloader;
156157
}
157158

Diff for: src/main/java/dev/hypera/dragonfly/DragonflyBuilder.java

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import java.util.HashSet;
3333
import java.util.Set;
3434
import java.util.function.Consumer;
35+
import org.jetbrains.annotations.Contract;
3536
import org.jetbrains.annotations.NotNull;
3637

3738
/**
@@ -115,6 +116,7 @@ private DragonflyBuilder(@NotNull IClassLoader classLoader, @NotNull Path direct
115116
*
116117
* @return New {@link Dragonfly} instance.
117118
*/
119+
@Contract(value = "-> new", pure = true)
118120
public @NotNull Dragonfly build() {
119121
try {
120122
return new Dragonfly(timeout, classLoader, directory, repositories, deleteOnRelocate, statusHandler);

Diff for: src/main/java/dev/hypera/dragonfly/downloaders/impl/MavenDownloader.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@
4141
@Downloader(MavenDependency.class)
4242
public class MavenDownloader implements IDownloader<MavenDependency> {
4343

44-
private final MavenResolver resolver = new MavenResolver();
45-
private final MavenSnapshotResolver snapshotResolver = new MavenSnapshotResolver();
44+
private final @NotNull MavenResolver resolver = new MavenResolver();
45+
private final @NotNull MavenSnapshotResolver snapshotResolver = new MavenSnapshotResolver();
4646

4747
@Override
4848
public void download(@NotNull Dragonfly dragonfly, @NotNull MavenDependency dependency) throws DownloadFailureException {

Diff for: src/main/java/dev/hypera/dragonfly/exceptions/DownloadFailureException.java

+8-4
Original file line numberDiff line numberDiff line change
@@ -23,25 +23,29 @@
2323

2424
package dev.hypera.dragonfly.exceptions;
2525

26+
import org.jetbrains.annotations.NotNull;
27+
2628
public class DownloadFailureException extends DragonflyException {
2729

30+
private static final long serialVersionUID = 5648475409314204882L;
31+
2832
public DownloadFailureException() {
2933
super();
3034
}
3135

32-
public DownloadFailureException(String message) {
36+
public DownloadFailureException(@NotNull String message) {
3337
super(message);
3438
}
3539

36-
public DownloadFailureException(String message, Throwable cause) {
40+
public DownloadFailureException(@NotNull String message, @NotNull Throwable cause) {
3741
super(message, cause);
3842
}
3943

40-
public DownloadFailureException(Throwable cause) {
44+
public DownloadFailureException(@NotNull Throwable cause) {
4145
super(cause);
4246
}
4347

44-
protected DownloadFailureException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
48+
protected DownloadFailureException(@NotNull String message, @NotNull Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
4549
super(message, cause, enableSuppression, writableStackTrace);
4650
}
4751

Diff for: src/main/java/dev/hypera/dragonfly/exceptions/DragonflyException.java

+8-4
Original file line numberDiff line numberDiff line change
@@ -23,29 +23,33 @@
2323

2424
package dev.hypera.dragonfly.exceptions;
2525

26+
import org.jetbrains.annotations.NotNull;
27+
2628
/**
2729
* Dragonfly Exception.
2830
* @author Joshua Sing <joshua@hypera.dev>
2931
*/
3032
public class DragonflyException extends Exception {
3133

34+
private static final long serialVersionUID = 3565376065959848642L;
35+
3236
public DragonflyException() {
3337
super();
3438
}
3539

36-
public DragonflyException(String message) {
40+
public DragonflyException(@NotNull String message) {
3741
super(message);
3842
}
3943

40-
public DragonflyException(String message, Throwable cause) {
44+
public DragonflyException(@NotNull String message, @NotNull Throwable cause) {
4145
super(message, cause);
4246
}
4347

44-
public DragonflyException(Throwable cause) {
48+
public DragonflyException(@NotNull Throwable cause) {
4549
super(cause);
4650
}
4751

48-
protected DragonflyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
52+
protected DragonflyException(@NotNull String message, @NotNull Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
4953
super(message, cause, enableSuppression, writableStackTrace);
5054
}
5155

Diff for: src/main/java/dev/hypera/dragonfly/exceptions/LoadFailureException.java

+8-4
Original file line numberDiff line numberDiff line change
@@ -23,25 +23,29 @@
2323

2424
package dev.hypera.dragonfly.exceptions;
2525

26+
import org.jetbrains.annotations.NotNull;
27+
2628
public class LoadFailureException extends DragonflyException {
2729

30+
private static final long serialVersionUID = -8555618454694039541L;
31+
2832
public LoadFailureException() {
2933
super();
3034
}
3135

32-
public LoadFailureException(String message) {
36+
public LoadFailureException(@NotNull String message) {
3337
super(message);
3438
}
3539

36-
public LoadFailureException(String message, Throwable cause) {
40+
public LoadFailureException(@NotNull String message, @NotNull Throwable cause) {
3741
super(message, cause);
3842
}
3943

40-
public LoadFailureException(Throwable cause) {
44+
public LoadFailureException(@NotNull Throwable cause) {
4145
super(cause);
4246
}
4347

44-
protected LoadFailureException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
48+
protected LoadFailureException(@NotNull String message, @NotNull Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
4549
super(message, cause, enableSuppression, writableStackTrace);
4650
}
4751

Diff for: src/main/java/dev/hypera/dragonfly/exceptions/RelocationFailureException.java

+8-4
Original file line numberDiff line numberDiff line change
@@ -23,25 +23,29 @@
2323

2424
package dev.hypera.dragonfly.exceptions;
2525

26+
import org.jetbrains.annotations.NotNull;
27+
2628
public class RelocationFailureException extends DragonflyException {
2729

30+
private static final long serialVersionUID = -2817144091943660838L;
31+
2832
public RelocationFailureException() {
2933
super();
3034
}
3135

32-
public RelocationFailureException(String message) {
36+
public RelocationFailureException(@NotNull String message) {
3337
super(message);
3438
}
3539

36-
public RelocationFailureException(String message, Throwable cause) {
40+
public RelocationFailureException(@NotNull String message, @NotNull Throwable cause) {
3741
super(message, cause);
3842
}
3943

40-
public RelocationFailureException(Throwable cause) {
44+
public RelocationFailureException(@NotNull Throwable cause) {
4145
super(cause);
4246
}
4347

44-
protected RelocationFailureException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
48+
protected RelocationFailureException(@NotNull String message, @NotNull Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
4549
super(message, cause, enableSuppression, writableStackTrace);
4650
}
4751

Diff for: src/main/java/dev/hypera/dragonfly/exceptions/ResolveFailureException.java

+8-4
Original file line numberDiff line numberDiff line change
@@ -23,25 +23,29 @@
2323

2424
package dev.hypera.dragonfly.exceptions;
2525

26+
import org.jetbrains.annotations.NotNull;
27+
2628
public class ResolveFailureException extends DownloadFailureException {
2729

30+
private static final long serialVersionUID = -8393996338726021911L;
31+
2832
public ResolveFailureException() {
2933
super();
3034
}
3135

32-
public ResolveFailureException(String message) {
36+
public ResolveFailureException(@NotNull String message) {
3337
super(message);
3438
}
3539

36-
public ResolveFailureException(String message, Throwable cause) {
40+
public ResolveFailureException(@NotNull String message, @NotNull Throwable cause) {
3741
super(message, cause);
3842
}
3943

40-
public ResolveFailureException(Throwable cause) {
44+
public ResolveFailureException(@NotNull Throwable cause) {
4145
super(cause);
4246
}
4347

44-
protected ResolveFailureException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
48+
protected ResolveFailureException(@NotNull String message, @NotNull Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
4549
super(message, cause, enableSuppression, writableStackTrace);
4650
}
4751

Diff for: src/main/java/dev/hypera/dragonfly/loading/DependencyLoader.java

+6-5
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.net.MalformedURLException;
3030
import java.util.List;
3131
import org.jetbrains.annotations.ApiStatus.Internal;
32+
import org.jetbrains.annotations.NotNull;
3233

3334
/**
3435
* Dependency loader.
@@ -37,11 +38,11 @@
3738
*/
3839
public class DependencyLoader {
3940

40-
private final Dragonfly dragonfly;
41-
private final IClassLoader classLoader;
41+
private final @NotNull Dragonfly dragonfly;
42+
private final @NotNull IClassLoader classLoader;
4243

4344
@Internal
44-
public DependencyLoader(Dragonfly dragonfly, IClassLoader classLoader) {
45+
public DependencyLoader(@NotNull Dragonfly dragonfly, @NotNull IClassLoader classLoader) {
4546
this.dragonfly = dragonfly;
4647
this.classLoader = classLoader;
4748
}
@@ -52,7 +53,7 @@ public DependencyLoader(Dragonfly dragonfly, IClassLoader classLoader) {
5253
* @param dependencies Dependencies to be loaded.
5354
* @throws LoadFailureException if something went wrong while loading the dependencies.
5455
*/
55-
public void load(List<Dependency> dependencies) throws LoadFailureException {
56+
public void load(@NotNull List<Dependency> dependencies) throws LoadFailureException {
5657
for (Dependency dependency : dependencies) {
5758
load(dependency);
5859
}
@@ -64,7 +65,7 @@ public void load(List<Dependency> dependencies) throws LoadFailureException {
6465
* @param dependency Dependency to be loaded.
6566
* @throws LoadFailureException if something went wrong while loading the dependency.
6667
*/
67-
private void load(Dependency dependency) throws LoadFailureException {
68+
private void load(@NotNull Dependency dependency) throws LoadFailureException {
6869
try {
6970
classLoader.addURL(dragonfly.getDirectory().resolve(dependency.getFileName()).toUri().toURL());
7071
} catch (MalformedURLException ex) {

Diff for: src/main/java/dev/hypera/dragonfly/loading/DragonflyClassLoader.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.net.URL;
2727
import java.net.URLClassLoader;
2828
import org.jetbrains.annotations.ApiStatus.Internal;
29+
import org.jetbrains.annotations.NotNull;
2930

3031
/**
3132
* Dragonfly class loader, a child-first {@link URLClassLoader} used for loading Dragonfly's internal dependencies.
@@ -35,17 +36,17 @@
3536
@Internal
3637
public class DragonflyClassLoader extends URLClassLoader {
3738

38-
public DragonflyClassLoader(ClassLoader classLoader) {
39+
public DragonflyClassLoader(@NotNull ClassLoader classLoader) {
3940
super(new URL[0], classLoader);
4041
}
4142

4243
@Override
43-
public void addURL(URL url) {
44+
public void addURL(@NotNull URL url) {
4445
super.addURL(url);
4546
}
4647

4748
@Override
48-
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
49+
protected @NotNull Class<?> loadClass(@NotNull String name, boolean resolve) throws ClassNotFoundException {
4950
Class<?> loadedClass = findLoadedClass(name);
5051
if (null == loadedClass) {
5152
try {

0 commit comments

Comments
 (0)