From a3513cc90670e194dba484e16fdf89e6d78bd7bb Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Mon, 10 Nov 2025 10:30:55 -0500 Subject: [PATCH 01/12] feat: package and utilize generated suppression file --- core/pom.xml | 20 ++++++++++++++++++ .../analyzer/AbstractSuppressionAnalyzer.java | 21 ++++++++++++++++--- pom.xml | 5 +++++ 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/core/pom.xml b/core/pom.xml index 05407c13ead..5b394e9c9b4 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -100,6 +100,26 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved. + + org.codehaus.mojo + exec-maven-plugin + + + process-resources + + exec + + + + + wget + + -O + ${project.build.directory}/classes/generated-suppressions.xml + https://dependency-check.github.io/DependencyCheck/suppressions/publishedSuppressions.xml + + + org.jsonschema2pojo jsonschema2pojo-maven-plugin diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java index f03d2f6157f..06a6166cdba 100644 --- a/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java +++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java @@ -68,6 +68,10 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer { * The file name of the base suppression XML file. */ private static final String BASE_SUPPRESSION_FILE = "dependencycheck-base-suppression.xml"; + /** + * The file name of the generated suppression XML file. + */ + private static final String GENERATED_SUPPRESSION_FILE = "generated-suppressions.xml"; /** * The key used to store and retrieve the suppression files. */ @@ -195,17 +199,28 @@ private void loadSuppressionBaseData(final Engine engine) throws SuppressionPars * @throws SuppressionParseException thrown if the XML cannot be parsed. */ private void loadPackagedSuppressionBaseData(final SuppressionParser parser, final Engine engine) throws SuppressionParseException { + loadPackagedSuppressionBaseData(BASE_SUPPRESSION_FILE, parser, engine); + loadPackagedSuppressionBaseData(GENERATED_SUPPRESSION_FILE, parser, engine); + } + /** + * Loads the base suppression rules packaged with the application. + * + * @param parser The suppression parser to use + * @param engine a reference the dependency-check engine + * @throws SuppressionParseException thrown if the XML cannot be parsed. + */ + private void loadPackagedSuppressionBaseData(final String packagedFileName, final SuppressionParser parser, final Engine engine) throws SuppressionParseException { List ruleList = null; final URL jarLocation = AbstractSuppressionAnalyzer.class.getProtectionDomain().getCodeSource().getLocation(); String suppressionFileLocation = jarLocation.getFile(); if (suppressionFileLocation.endsWith(".jar")) { - suppressionFileLocation = "jar:file:" + suppressionFileLocation + "!/" + BASE_SUPPRESSION_FILE; + suppressionFileLocation = "jar:file:" + suppressionFileLocation + "!/" + packagedFileName; } else if (suppressionFileLocation.startsWith("nested:") && suppressionFileLocation.endsWith(".jar!/")) { // suppressionFileLocation -> nested:/app/app.jar/!BOOT-INF/lib/dependency-check-core-.jar!/ // goal-> jar:nested:/app/app.jar/!BOOT-INF/lib/dependency-check-core-.jar!/dependencycheck-base-suppression.xml - suppressionFileLocation = "jar:" + suppressionFileLocation + BASE_SUPPRESSION_FILE; + suppressionFileLocation = "jar:" + suppressionFileLocation + packagedFileName; } else { - suppressionFileLocation = "file:" + suppressionFileLocation + BASE_SUPPRESSION_FILE; + suppressionFileLocation = "file:" + suppressionFileLocation + packagedFileName; } URL baseSuppresssionURL = null; try { diff --git a/pom.xml b/pom.xml index 956e349c38a..0ddc10eef37 100644 --- a/pom.xml +++ b/pom.xml @@ -187,6 +187,11 @@ Copyright (c) 2012 - Jeremy Long clean install + + org.codehaus.mojo + exec-maven-plugin + 3.6.2 + org.jsonschema2pojo jsonschema2pojo-maven-plugin From 2f3a2ea1b3a5a70b6a23c374b0e7cf93c0860d8d Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Mon, 10 Nov 2025 10:48:18 -0500 Subject: [PATCH 02/12] fix: use different downloader per copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- core/pom.xml | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/core/pom.xml b/core/pom.xml index 5b394e9c9b4..e9ebcb339b9 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -101,24 +101,23 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved. - org.codehaus.mojo - exec-maven-plugin + com.googlecode.maven-download-plugin + download-maven-plugin + 1.6.3 + download-published-suppressions process-resources - exec + wget + + https://dependency-check.github.io/DependencyCheck/suppressions/publishedSuppressions.xml + ${project.build.directory}/classes + generated-suppressions.xml + - - wget - - -O - ${project.build.directory}/classes/generated-suppressions.xml - https://dependency-check.github.io/DependencyCheck/suppressions/publishedSuppressions.xml - - org.jsonschema2pojo From c1f7ded63fc747fc86b4f1ecbecd1f2fdc81be80 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Mon, 10 Nov 2025 10:49:11 -0500 Subject: [PATCH 03/12] Apply suggestion from @jeremylong --- core/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/pom.xml b/core/pom.xml index e9ebcb339b9..9a964dac9ed 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -107,7 +107,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved. download-published-suppressions - process-resources + generate-resources wget From 1d588943ad9770cf82b76ceeca22254da5cdfb29 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Mon, 10 Nov 2025 10:50:14 -0500 Subject: [PATCH 04/12] Apply suggestion from @jeremylong --- core/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/pom.xml b/core/pom.xml index 9a964dac9ed..b75ac5ca4db 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -103,7 +103,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved. com.googlecode.maven-download-plugin download-maven-plugin - 1.6.3 + 1.13.0 download-published-suppressions From f61f55141aeeac7b04e821c4ec7cef640ee821f6 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Mon, 10 Nov 2025 10:51:39 -0500 Subject: [PATCH 05/12] Apply suggestions from code review --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 0ddc10eef37..a017bd1962c 100644 --- a/pom.xml +++ b/pom.xml @@ -188,9 +188,9 @@ Copyright (c) 2012 - Jeremy Long - org.codehaus.mojo - exec-maven-plugin - 3.6.2 + com.googlecode.maven-download-plugin + download-maven-plugin + 1.13.0 org.jsonschema2pojo From cab3470b12f853f0c42f1c40e44a5861ed693cda Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Mon, 10 Nov 2025 10:54:03 -0500 Subject: [PATCH 06/12] Apply suggestion from @jeremylong --- .../dependencycheck/analyzer/AbstractSuppressionAnalyzer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java index 06a6166cdba..fd82e1d0095 100644 --- a/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java +++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java @@ -203,8 +203,9 @@ private void loadPackagedSuppressionBaseData(final SuppressionParser parser, fin loadPackagedSuppressionBaseData(GENERATED_SUPPRESSION_FILE, parser, engine); } /** - * Loads the base suppression rules packaged with the application. + * Loads the suppression rules packaged with the application. * + * @param packagedFileName the name of the packaged suppression file to load * @param parser The suppression parser to use * @param engine a reference the dependency-check engine * @throws SuppressionParseException thrown if the XML cannot be parsed. From aa386060fd59fce5665652ca0bf5c40511f21ddb Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Mon, 10 Nov 2025 10:54:48 -0500 Subject: [PATCH 07/12] Apply suggestion from @jeremylong --- core/pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/core/pom.xml b/core/pom.xml index b75ac5ca4db..57244057122 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -103,7 +103,6 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved. com.googlecode.maven-download-plugin download-maven-plugin - 1.13.0 download-published-suppressions From a9748b221b4b2f38f744d047a1686097a4b695f8 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Tue, 18 Nov 2025 11:00:23 -0500 Subject: [PATCH 08/12] fix: dependency relocated Co-authored-by: Chad Wilson <29788154+chadlwilson@users.noreply.github.com> --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a017bd1962c..cb76d09ca84 100644 --- a/pom.xml +++ b/pom.xml @@ -188,9 +188,9 @@ Copyright (c) 2012 - Jeremy Long - com.googlecode.maven-download-plugin + io.github.download-maven-plugin download-maven-plugin - 1.13.0 + 2.0.0 org.jsonschema2pojo From 3b25d1cccd16055872b260864b78cc35060272ef Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Wed, 10 Dec 2025 06:08:16 -0500 Subject: [PATCH 09/12] Apply suggestion from @nhumblot Co-authored-by: Nicolas Humblot --- core/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/pom.xml b/core/pom.xml index a3405575b1b..773754ad039 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -101,7 +101,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved. - com.googlecode.maven-download-plugin + io.github.download-maven-plugin download-maven-plugin From 33996d22b7d5ca39bef04a4f08332ac9f5e243e2 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Wed, 10 Dec 2025 09:21:40 -0500 Subject: [PATCH 10/12] fix: improvements per peer review --- core/pom.xml | 2 +- .../analyzer/AbstractSuppressionAnalyzer.java | 80 +++++++++---------- 2 files changed, 37 insertions(+), 45 deletions(-) diff --git a/core/pom.xml b/core/pom.xml index 773754ad039..ebe8b4232c4 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -113,7 +113,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved. https://dependency-check.github.io/DependencyCheck/suppressions/publishedSuppressions.xml ${project.build.directory}/classes - generated-suppressions.xml + dependencycheck-hosted-suppression-snapshot.xml diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java index fd82e1d0095..54e622d608a 100644 --- a/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java +++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java @@ -30,6 +30,8 @@ import java.util.Set; import java.util.regex.Pattern; import javax.annotation.concurrent.ThreadSafe; + +import org.jetbrains.annotations.NotNull; import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.data.update.HostedSuppressionsDataSource; @@ -69,9 +71,9 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer { */ private static final String BASE_SUPPRESSION_FILE = "dependencycheck-base-suppression.xml"; /** - * The file name of the generated suppression XML file. + * The file name of the snapshot of the hosted suppression XML file. */ - private static final String GENERATED_SUPPRESSION_FILE = "generated-suppressions.xml"; + private static final String HOSTED_SUPPRESSION_SNAPSHOT_FILE = "dependencycheck-hosted-suppression-snapshot.xml"; /** * The key used to store and retrieve the suppression files. */ @@ -191,27 +193,33 @@ private void loadSuppressionBaseData(final Engine engine) throws SuppressionPars loadHostedSuppressionBaseData(parser, engine); } - /** - * Loads the base suppression rules packaged with the application. - * - * @param parser The suppression parser to use - * @param engine a reference the dependency-check engine - * @throws SuppressionParseException thrown if the XML cannot be parsed. - */ - private void loadPackagedSuppressionBaseData(final SuppressionParser parser, final Engine engine) throws SuppressionParseException { - loadPackagedSuppressionBaseData(BASE_SUPPRESSION_FILE, parser, engine); - loadPackagedSuppressionBaseData(GENERATED_SUPPRESSION_FILE, parser, engine); - } /** * Loads the suppression rules packaged with the application. * - * @param packagedFileName the name of the packaged suppression file to load * @param parser The suppression parser to use * @param engine a reference the dependency-check engine * @throws SuppressionParseException thrown if the XML cannot be parsed. */ - private void loadPackagedSuppressionBaseData(final String packagedFileName, final SuppressionParser parser, final Engine engine) throws SuppressionParseException { + private void loadPackagedSuppressionBaseData(final SuppressionParser parser, final Engine engine) throws SuppressionParseException { List ruleList = null; + URL baseSuppresssionURL = getPackagedFile(BASE_SUPPRESSION_FILE); + try (InputStream in = baseSuppresssionURL.openStream()) { + ruleList = parser.parseSuppressionRules(in); + } catch (SAXException | IOException ex) { + throw new SuppressionParseException("Unable to parse the base suppression data file", ex); + } + if (ruleList != null && !ruleList.isEmpty()) { + if (engine.hasObject(SUPPRESSION_OBJECT_KEY)) { + @SuppressWarnings("unchecked") + final List rules = (List) engine.getObject(SUPPRESSION_OBJECT_KEY); + rules.addAll(ruleList); + } else { + engine.putObject(SUPPRESSION_OBJECT_KEY, ruleList); + } + } + } + + private static @NotNull URL getPackagedFile(String packagedFileName) throws SuppressionParseException { final URL jarLocation = AbstractSuppressionAnalyzer.class.getProtectionDomain().getCodeSource().getLocation(); String suppressionFileLocation = jarLocation.getFile(); if (suppressionFileLocation.endsWith(".jar")) { @@ -229,20 +237,7 @@ private void loadPackagedSuppressionBaseData(final String packagedFileName, fina } catch (MalformedURLException e) { throw new SuppressionParseException("Unable to load the base suppression data file", e); } - try (InputStream in = baseSuppresssionURL.openStream()) { - ruleList = parser.parseSuppressionRules(in); - } catch (SAXException | IOException ex) { - throw new SuppressionParseException("Unable to parse the base suppression data file", ex); - } - if (ruleList != null && !ruleList.isEmpty()) { - if (engine.hasObject(SUPPRESSION_OBJECT_KEY)) { - @SuppressWarnings("unchecked") - final List rules = (List) engine.getObject(SUPPRESSION_OBJECT_KEY); - rules.addAll(ruleList); - } else { - engine.putObject(SUPPRESSION_OBJECT_KEY, ruleList); - } - } + return baseSuppresssionURL; } /** @@ -258,31 +253,28 @@ private void loadPackagedSuppressionBaseData(final String packagedFileName, fina * @param parser The suppression parser to use */ private void loadHostedSuppressionBaseData(final SuppressionParser parser, final Engine engine) { - final File repoFile; - boolean repoEmpty = false; final boolean enabled = getSettings().getBoolean(Settings.KEYS.HOSTED_SUPPRESSIONS_ENABLED, true); if (!enabled) { return; } - final boolean autoupdate = getSettings().getBoolean(Settings.KEYS.AUTO_UPDATE, true); - final boolean forceupdate = getSettings().getBoolean(Settings.KEYS.HOSTED_SUPPRESSIONS_FORCEUPDATE, false); try { final String configuredUrl = getSettings().getString(Settings.KEYS.HOSTED_SUPPRESSIONS_URL, HostedSuppressionsDataSource.DEFAULT_SUPPRESSIONS_URL); final URL url = new URL(configuredUrl); final String fileName = new File(url.getPath()).getName(); - repoFile = new File(getSettings().getDataDirectory(), fileName); - if (!repoFile.isFile() || repoFile.length() <= 1L) { - repoEmpty = true; - LOGGER.warn("Hosted Suppressions file is empty or missing - attempting to force the update"); - getSettings().setBoolean(Settings.KEYS.HOSTED_SUPPRESSIONS_FORCEUPDATE, true); - } - if ((!autoupdate && forceupdate) || (autoupdate && repoEmpty)) { - if (engine == null) { - LOGGER.warn("Engine was null, this should only happen in tests - skipping forced update"); - } else { - repoEmpty = forceUpdateHostedSuppressions(engine, repoFile); + final File repoFile = new File(getSettings().getDataDirectory(), fileName); + boolean repoEmpty = !repoFile.isFile() || repoFile.length() <= 1L; + if (repoEmpty) { + // utilize the snapshot hosted suppression file + URL hostedSuppressionSnapshotURL = getPackagedFile(HOSTED_SUPPRESSION_SNAPSHOT_FILE); + try (InputStream in = hostedSuppressionSnapshotURL.openStream()) { + Files.copy(in, repoFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + repoEmpty = false; + LOGGER.debug("Copied hosted suppression snapshot file to {}", repoFile.toPath()); + } catch (IOException ex) { + LOGGER.warn("Unable to copy the hosted suppression snapshot file to {}, results may contain false positives " + + "already resolved by the DependencyCheck project", repoFile.toPath(), ex); } } if (!repoEmpty) { From 5d0ac78f27707525ce7c921d10c11728bba4f2bd Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sun, 14 Dec 2025 07:22:26 -0500 Subject: [PATCH 11/12] Update core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../dependencycheck/analyzer/AbstractSuppressionAnalyzer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java index 54e622d608a..24f7d1d0fac 100644 --- a/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java +++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java @@ -235,7 +235,7 @@ private void loadPackagedSuppressionBaseData(final SuppressionParser parser, fin try { baseSuppresssionURL = new URL(suppressionFileLocation); } catch (MalformedURLException e) { - throw new SuppressionParseException("Unable to load the base suppression data file", e); + throw new SuppressionParseException("Unable to load the packaged file: " + packagedFileName, e); } return baseSuppresssionURL; } From eceeada49c2ea4e3aadaafcb1256fcc77b29ff7b Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sun, 14 Dec 2025 07:24:26 -0500 Subject: [PATCH 12/12] fix: typos --- .../analyzer/AbstractSuppressionAnalyzer.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java b/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java index 24f7d1d0fac..28ea42e91ec 100644 --- a/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java +++ b/core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java @@ -202,8 +202,8 @@ private void loadSuppressionBaseData(final Engine engine) throws SuppressionPars */ private void loadPackagedSuppressionBaseData(final SuppressionParser parser, final Engine engine) throws SuppressionParseException { List ruleList = null; - URL baseSuppresssionURL = getPackagedFile(BASE_SUPPRESSION_FILE); - try (InputStream in = baseSuppresssionURL.openStream()) { + URL baseSuppressionURL = getPackagedFile(BASE_SUPPRESSION_FILE); + try (InputStream in = baseSuppressionURL.openStream()) { ruleList = parser.parseSuppressionRules(in); } catch (SAXException | IOException ex) { throw new SuppressionParseException("Unable to parse the base suppression data file", ex); @@ -231,13 +231,13 @@ private void loadPackagedSuppressionBaseData(final SuppressionParser parser, fin } else { suppressionFileLocation = "file:" + suppressionFileLocation + packagedFileName; } - URL baseSuppresssionURL = null; + URL baseSuppressionURL = null; try { - baseSuppresssionURL = new URL(suppressionFileLocation); + baseSuppressionURL = new URL(suppressionFileLocation); } catch (MalformedURLException e) { throw new SuppressionParseException("Unable to load the packaged file: " + packagedFileName, e); } - return baseSuppresssionURL; + return baseSuppressionURL; } /**