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(); } }