NpmCPEAnalyzer.java

  1. /*
  2.  * This file is part of dependency-check-core.
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  *     http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  *
  16.  * Copyright (c) 2020 Jeremy Long. All Rights Reserved.
  17.  */
  18. package org.owasp.dependencycheck.analyzer;

  19. import java.io.IOException;
  20. import java.util.concurrent.TimeUnit;
  21. import javax.annotation.concurrent.ThreadSafe;
  22. import org.apache.lucene.index.CorruptIndexException;
  23. import org.apache.lucene.queryparser.classic.ParseException;
  24. import org.owasp.dependencycheck.Engine;
  25. import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
  26. import org.owasp.dependencycheck.data.cpe.IndexException;
  27. import org.owasp.dependencycheck.data.cpe.NpmCpeMemoryIndex;
  28. import org.owasp.dependencycheck.data.nvdcve.CveDB;
  29. import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
  30. import org.owasp.dependencycheck.dependency.Dependency;
  31. import org.owasp.dependencycheck.utils.Settings;
  32. import org.slf4j.Logger;
  33. import org.slf4j.LoggerFactory;

  34. /**
  35.  * NpmCPEAnalyzer takes a project dependency and attempts to discern if there is
  36.  * an associated CPE. Unlike the CPEAnalyzer, the NpmCPEAnalyzer only includes
  37.  * product and vendor associates known to be related to node from the NVD data
  38.  * set. It uses the evidence contained within the dependency to search the
  39.  * Lucene index.
  40.  *
  41.  * @author Jeremy Long
  42.  */
  43. @ThreadSafe
  44. @Experimental
  45. public class NpmCPEAnalyzer extends CPEAnalyzer {

  46.     /**
  47.      * The Logger.
  48.      */
  49.     private static final Logger LOGGER = LoggerFactory.getLogger(NpmCPEAnalyzer.class);

  50.     /**
  51.      * Returns the analysis phase that this analyzer should run in.
  52.      *
  53.      * @return the analysis phase that this analyzer should run in.
  54.      */
  55.     @Override
  56.     public AnalysisPhase getAnalysisPhase() {
  57.         //TODO this is a hack because we use the same singleton CPE Index as the CPE Analyzer
  58.         // thus to filter to just node products we can't run in the same phase.
  59.         // possibly extenend the CPE Index to include an ecosystem and use that
  60.         // as a filter for node..
  61.         return AnalysisPhase.PRE_IDENTIFIER_ANALYSIS;
  62.     }

  63.     /**
  64.      * Returns the name of this analyzer.
  65.      *
  66.      * @return the name of this analyzer.
  67.      */
  68.     @Override
  69.     public String getName() {
  70.         return "NPM CPE Analyzer";
  71.     }

  72.     /**
  73.      * <p>
  74.      * Returns the setting key to determine if the analyzer is enabled.</p>
  75.      *
  76.      * @return the key for the analyzer's enabled property
  77.      */
  78.     @Override
  79.     protected String getAnalyzerEnabledSettingKey() {
  80.         return Settings.KEYS.ANALYZER_NPM_CPE_ENABLED;
  81.     }

  82.     /**
  83.      * Opens the data source.
  84.      *
  85.      * @param cve a reference to the NVD CVE database
  86.      * @throws IOException when the Lucene directory to be queried does not
  87.      * exist or is corrupt.
  88.      * @throws DatabaseException when the database throws an exception. This
  89.      * usually occurs when the database is in use by another process.
  90.      */
  91.     @Override
  92.     public void open(CveDB cve) throws IOException, DatabaseException {
  93.         setCveDB(cve);
  94.         setMemoryIndex(NpmCpeMemoryIndex.getInstance());
  95.         try {
  96.             final long creationStart = System.currentTimeMillis();
  97.             getMemoryIndex().open(cve.getVendorProductListForNode(), this.getSettings());
  98.             final long creationSeconds = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - creationStart);
  99.             LOGGER.info("Created CPE Index ({} seconds)", creationSeconds);
  100.         } catch (IndexException ex) {
  101.             LOGGER.debug("IndexException", ex);
  102.             throw new DatabaseException(ex);
  103.         }
  104.     }

  105.     /**
  106.      * Analyzes a dependency and attempts to determine if there are any CPE
  107.      * identifiers for this dependency.
  108.      *
  109.      * @param dependency The Dependency to analyze.
  110.      * @param engine The analysis engine
  111.      * @throws AnalysisException is thrown if there is an issue analyzing the
  112.      * dependency.
  113.      */
  114.     @Override
  115.     protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
  116.         if (!"npm".equals(dependency.getEcosystem())) {
  117.             return;
  118.         }
  119.         try {
  120.             determineCPE(dependency);
  121.         } catch (CorruptIndexException ex) {
  122.             throw new AnalysisException("CPE Index is corrupt.", ex);
  123.         } catch (IOException ex) {
  124.             throw new AnalysisException("Failure opening the CPE Index.", ex);
  125.         } catch (ParseException ex) {
  126.             throw new AnalysisException("Unable to parse the generated Lucene query for this dependency.", ex);
  127.         }
  128.     }
  129. }