3030import java .util .Set ;
3131import java .util .regex .Pattern ;
3232import javax .annotation .concurrent .ThreadSafe ;
33+
34+ import org .jetbrains .annotations .NotNull ;
3335import org .owasp .dependencycheck .Engine ;
3436import org .owasp .dependencycheck .analyzer .exception .AnalysisException ;
3537import org .owasp .dependencycheck .data .update .HostedSuppressionsDataSource ;
@@ -69,9 +71,9 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
6971 */
7072 private static final String BASE_SUPPRESSION_FILE = "dependencycheck-base-suppression.xml" ;
7173 /**
72- * The file name of the generated suppression XML file.
74+ * The file name of the snapshot of the hosted suppression XML file.
7375 */
74- private static final String GENERATED_SUPPRESSION_FILE = "generated-suppressions .xml" ;
76+ private static final String HOSTED_SUPPRESSION_SNAPSHOT_FILE = "dependencycheck-hosted-suppression-snapshot .xml" ;
7577 /**
7678 * The key used to store and retrieve the suppression files.
7779 */
@@ -191,27 +193,33 @@ private void loadSuppressionBaseData(final Engine engine) throws SuppressionPars
191193 loadHostedSuppressionBaseData (parser , engine );
192194 }
193195
194- /**
195- * Loads the base suppression rules packaged with the application.
196- *
197- * @param parser The suppression parser to use
198- * @param engine a reference the dependency-check engine
199- * @throws SuppressionParseException thrown if the XML cannot be parsed.
200- */
201- private void loadPackagedSuppressionBaseData (final SuppressionParser parser , final Engine engine ) throws SuppressionParseException {
202- loadPackagedSuppressionBaseData (BASE_SUPPRESSION_FILE , parser , engine );
203- loadPackagedSuppressionBaseData (GENERATED_SUPPRESSION_FILE , parser , engine );
204- }
205196 /**
206197 * Loads the suppression rules packaged with the application.
207198 *
208- * @param packagedFileName the name of the packaged suppression file to load
209199 * @param parser The suppression parser to use
210200 * @param engine a reference the dependency-check engine
211201 * @throws SuppressionParseException thrown if the XML cannot be parsed.
212202 */
213- private void loadPackagedSuppressionBaseData (final String packagedFileName , final SuppressionParser parser , final Engine engine ) throws SuppressionParseException {
203+ private void loadPackagedSuppressionBaseData (final SuppressionParser parser , final Engine engine ) throws SuppressionParseException {
214204 List <SuppressionRule > ruleList = null ;
205+ URL baseSuppresssionURL = getPackagedFile (BASE_SUPPRESSION_FILE );
206+ try (InputStream in = baseSuppresssionURL .openStream ()) {
207+ ruleList = parser .parseSuppressionRules (in );
208+ } catch (SAXException | IOException ex ) {
209+ throw new SuppressionParseException ("Unable to parse the base suppression data file" , ex );
210+ }
211+ if (ruleList != null && !ruleList .isEmpty ()) {
212+ if (engine .hasObject (SUPPRESSION_OBJECT_KEY )) {
213+ @ SuppressWarnings ("unchecked" )
214+ final List <SuppressionRule > rules = (List <SuppressionRule >) engine .getObject (SUPPRESSION_OBJECT_KEY );
215+ rules .addAll (ruleList );
216+ } else {
217+ engine .putObject (SUPPRESSION_OBJECT_KEY , ruleList );
218+ }
219+ }
220+ }
221+
222+ private static @ NotNull URL getPackagedFile (String packagedFileName ) throws SuppressionParseException {
215223 final URL jarLocation = AbstractSuppressionAnalyzer .class .getProtectionDomain ().getCodeSource ().getLocation ();
216224 String suppressionFileLocation = jarLocation .getFile ();
217225 if (suppressionFileLocation .endsWith (".jar" )) {
@@ -229,20 +237,7 @@ private void loadPackagedSuppressionBaseData(final String packagedFileName, fina
229237 } catch (MalformedURLException e ) {
230238 throw new SuppressionParseException ("Unable to load the base suppression data file" , e );
231239 }
232- try (InputStream in = baseSuppresssionURL .openStream ()) {
233- ruleList = parser .parseSuppressionRules (in );
234- } catch (SAXException | IOException ex ) {
235- throw new SuppressionParseException ("Unable to parse the base suppression data file" , ex );
236- }
237- if (ruleList != null && !ruleList .isEmpty ()) {
238- if (engine .hasObject (SUPPRESSION_OBJECT_KEY )) {
239- @ SuppressWarnings ("unchecked" )
240- final List <SuppressionRule > rules = (List <SuppressionRule >) engine .getObject (SUPPRESSION_OBJECT_KEY );
241- rules .addAll (ruleList );
242- } else {
243- engine .putObject (SUPPRESSION_OBJECT_KEY , ruleList );
244- }
245- }
240+ return baseSuppresssionURL ;
246241 }
247242
248243 /**
@@ -258,31 +253,28 @@ private void loadPackagedSuppressionBaseData(final String packagedFileName, fina
258253 * @param parser The suppression parser to use
259254 */
260255 private void loadHostedSuppressionBaseData (final SuppressionParser parser , final Engine engine ) {
261- final File repoFile ;
262- boolean repoEmpty = false ;
263256 final boolean enabled = getSettings ().getBoolean (Settings .KEYS .HOSTED_SUPPRESSIONS_ENABLED , true );
264257 if (!enabled ) {
265258 return ;
266259 }
267- final boolean autoupdate = getSettings ().getBoolean (Settings .KEYS .AUTO_UPDATE , true );
268- final boolean forceupdate = getSettings ().getBoolean (Settings .KEYS .HOSTED_SUPPRESSIONS_FORCEUPDATE , false );
269260
270261 try {
271262 final String configuredUrl = getSettings ().getString (Settings .KEYS .HOSTED_SUPPRESSIONS_URL ,
272263 HostedSuppressionsDataSource .DEFAULT_SUPPRESSIONS_URL );
273264 final URL url = new URL (configuredUrl );
274265 final String fileName = new File (url .getPath ()).getName ();
275- repoFile = new File (getSettings ().getDataDirectory (), fileName );
276- if (!repoFile .isFile () || repoFile .length () <= 1L ) {
277- repoEmpty = true ;
278- LOGGER .warn ("Hosted Suppressions file is empty or missing - attempting to force the update" );
279- getSettings ().setBoolean (Settings .KEYS .HOSTED_SUPPRESSIONS_FORCEUPDATE , true );
280- }
281- if ((!autoupdate && forceupdate ) || (autoupdate && repoEmpty )) {
282- if (engine == null ) {
283- LOGGER .warn ("Engine was null, this should only happen in tests - skipping forced update" );
284- } else {
285- repoEmpty = forceUpdateHostedSuppressions (engine , repoFile );
266+ final File repoFile = new File (getSettings ().getDataDirectory (), fileName );
267+ boolean repoEmpty = !repoFile .isFile () || repoFile .length () <= 1L ;
268+ if (repoEmpty ) {
269+ // utilize the snapshot hosted suppression file
270+ URL hostedSuppressionSnapshotURL = getPackagedFile (HOSTED_SUPPRESSION_SNAPSHOT_FILE );
271+ try (InputStream in = hostedSuppressionSnapshotURL .openStream ()) {
272+ Files .copy (in , repoFile .toPath (), StandardCopyOption .REPLACE_EXISTING );
273+ repoEmpty = false ;
274+ LOGGER .debug ("Copied hosted suppression snapshot file to {}" , repoFile .toPath ());
275+ } catch (IOException ex ) {
276+ LOGGER .warn ("Unable to copy the hosted suppression snapshot file to {}, results may contain false positives "
277+ + "already resolved by the DependencyCheck project" , repoFile .toPath (), ex );
286278 }
287279 }
288280 if (!repoEmpty ) {
0 commit comments