From 0c75ce58e76414ddbdc925d57c8c6d0aa5fa8f25 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 17 Feb 2026 15:51:46 +0000
Subject: [PATCH 1/3] Initial plan
From 6ca3d9c82b3e02d9a7ad58f5bd4f0f6fa3cc1efa Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 17 Feb 2026 15:57:50 +0000
Subject: [PATCH 2/3] fix: Use ThreadLocal for thread-safe task storage in
AntTaskHolder
Co-authored-by: jeremylong <862914+jeremylong@users.noreply.github.com>
---
.../owasp/dependencycheck/ant/logging/AntTaskHolder.java | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/ant/src/main/java/org/owasp/dependencycheck/ant/logging/AntTaskHolder.java b/ant/src/main/java/org/owasp/dependencycheck/ant/logging/AntTaskHolder.java
index 3b8ad175ca..a1b967b2c3 100644
--- a/ant/src/main/java/org/owasp/dependencycheck/ant/logging/AntTaskHolder.java
+++ b/ant/src/main/java/org/owasp/dependencycheck/ant/logging/AntTaskHolder.java
@@ -22,10 +22,13 @@
/**
* Holds a reference to the current Ant Task for logging. Replaces the old
* StaticLoggerBinder singleton pattern used with SLF4J 1.x.
+ *
+ * Uses ThreadLocal to ensure thread-safety when Ant runs tasks in parallel.
+ *
*/
public final class AntTaskHolder {
- private static volatile Task task;
+ private static final ThreadLocal task = new ThreadLocal<>();
private AntTaskHolder() {
}
@@ -36,7 +39,7 @@ private AntTaskHolder() {
* @param t the Ant task
*/
public static void setTask(Task t) {
- task = t;
+ task.set(t);
}
/**
@@ -45,6 +48,6 @@ public static void setTask(Task t) {
* @return the Ant task, or null if not set
*/
public static Task getTask() {
- return task;
+ return task.get();
}
}
From ea50cec1c7f2241612a6d38c3aac1b9df4c43665 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 17 Feb 2026 15:58:41 +0000
Subject: [PATCH 3/3] fix: Add ThreadLocal cleanup to prevent memory leaks
Co-authored-by: jeremylong <862914+jeremylong@users.noreply.github.com>
---
.../owasp/dependencycheck/ant/logging/AntTaskHolder.java | 9 +++++++++
.../java/org/owasp/dependencycheck/taskdefs/Purge.java | 1 +
2 files changed, 10 insertions(+)
diff --git a/ant/src/main/java/org/owasp/dependencycheck/ant/logging/AntTaskHolder.java b/ant/src/main/java/org/owasp/dependencycheck/ant/logging/AntTaskHolder.java
index a1b967b2c3..5cabdd7fc0 100644
--- a/ant/src/main/java/org/owasp/dependencycheck/ant/logging/AntTaskHolder.java
+++ b/ant/src/main/java/org/owasp/dependencycheck/ant/logging/AntTaskHolder.java
@@ -50,4 +50,13 @@ public static void setTask(Task t) {
public static Task getTask() {
return task.get();
}
+
+ /**
+ * Removes the current Ant task from the thread-local storage.
+ * This should be called when the task completes to prevent memory leaks
+ * in environments with thread pooling.
+ */
+ public static void remove() {
+ task.remove();
+ }
}
diff --git a/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java b/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java
index afa1aa6559..5f4f6011af 100644
--- a/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java
+++ b/ant/src/main/java/org/owasp/dependencycheck/taskdefs/Purge.java
@@ -121,6 +121,7 @@ public final void execute() throws BuildException {
executeWithContextClassloader();
} finally {
Thread.currentThread().setContextClassLoader(current);
+ AntTaskHolder.remove();
}
}