Coverage Report - org.owasp.dependencycheck.analyzer.NodePackageAnalyzer
 
Classes in this File Line Coverage Branch Coverage Complexity
NodePackageAnalyzer
86%
46/53
64%
9/14
2.429
 
 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) 2015 Institute for Defense Analyses. All Rights Reserved.
 17  
  */
 18  
 package org.owasp.dependencycheck.analyzer;
 19  
 
 20  
 import org.apache.commons.io.FileUtils;
 21  
 import org.owasp.dependencycheck.Engine;
 22  
 import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
 23  
 import org.owasp.dependencycheck.dependency.Confidence;
 24  
 import org.owasp.dependencycheck.dependency.Dependency;
 25  
 import org.owasp.dependencycheck.dependency.EvidenceCollection;
 26  
 import org.owasp.dependencycheck.utils.FileFilterBuilder;
 27  
 import org.owasp.dependencycheck.utils.Settings;
 28  
 import org.slf4j.Logger;
 29  
 import org.slf4j.LoggerFactory;
 30  
 
 31  
 import java.io.File;
 32  
 import java.io.FileFilter;
 33  
 import java.io.IOException;
 34  
 import java.util.Map;
 35  
 import javax.json.Json;
 36  
 import javax.json.JsonException;
 37  
 import javax.json.JsonObject;
 38  
 import javax.json.JsonReader;
 39  
 import javax.json.JsonString;
 40  
 import javax.json.JsonValue;
 41  
 import org.owasp.dependencycheck.exception.InitializationException;
 42  
 
 43  
 /**
 44  
  * Used to analyze Node Package Manager (npm) package.json files, and collect
 45  
  * information that can be used to determine the associated CPE.
 46  
  *
 47  
  * @author Dale Visser
 48  
  */
 49  
 @Experimental
 50  11
 public class NodePackageAnalyzer extends AbstractFileTypeAnalyzer {
 51  
 
 52  
     /**
 53  
      * The logger.
 54  
      */
 55  1
     private static final Logger LOGGER = LoggerFactory.getLogger(NodePackageAnalyzer.class);
 56  
 
 57  
     /**
 58  
      * The name of the analyzer.
 59  
      */
 60  
     private static final String ANALYZER_NAME = "Node.js Package Analyzer";
 61  
 
 62  
     /**
 63  
      * The phase that this analyzer is intended to run in.
 64  
      */
 65  1
     private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
 66  
 
 67  
     /**
 68  
      * The file name to scan.
 69  
      */
 70  
     public static final String PACKAGE_JSON = "package.json";
 71  
     /**
 72  
      * Filter that detects files named "package.json".
 73  
      */
 74  2
     private static final FileFilter PACKAGE_JSON_FILTER = FileFilterBuilder.newInstance()
 75  1
             .addFilenames(PACKAGE_JSON).build();
 76  
 
 77  
     /**
 78  
      * Returns the FileFilter
 79  
      *
 80  
      * @return the FileFilter
 81  
      */
 82  
     @Override
 83  
     protected FileFilter getFileFilter() {
 84  859
         return PACKAGE_JSON_FILTER;
 85  
     }
 86  
 
 87  
     @Override
 88  
     protected void initializeFileTypeAnalyzer() throws InitializationException {
 89  
         // NO-OP
 90  3
     }
 91  
 
 92  
     /**
 93  
      * Returns the name of the analyzer.
 94  
      *
 95  
      * @return the name of the analyzer.
 96  
      */
 97  
     @Override
 98  
     public String getName() {
 99  17
         return ANALYZER_NAME;
 100  
     }
 101  
 
 102  
     /**
 103  
      * Returns the phase that the analyzer is intended to run in.
 104  
      *
 105  
      * @return the phase that the analyzer is intended to run in.
 106  
      */
 107  
     @Override
 108  
     public AnalysisPhase getAnalysisPhase() {
 109  6
         return ANALYSIS_PHASE;
 110  
     }
 111  
 
 112  
     /**
 113  
      * Returns the key used in the properties file to reference the analyzer's
 114  
      * enabled property.
 115  
      *
 116  
      * @return the analyzer's enabled property setting key
 117  
      */
 118  
     @Override
 119  
     protected String getAnalyzerEnabledSettingKey() {
 120  5
         return Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED;
 121  
     }
 122  
 
 123  
     @Override
 124  
     protected void analyzeDependency(Dependency dependency, Engine engine)
 125  
             throws AnalysisException {
 126  1
         final File file = dependency.getActualFile();
 127  
         JsonReader jsonReader;
 128  
         try {
 129  1
             jsonReader = Json.createReader(FileUtils.openInputStream(file));
 130  0
         } catch (IOException e) {
 131  0
             throw new AnalysisException(
 132  
                     "Problem occurred while reading dependency file.", e);
 133  1
         }
 134  
         try {
 135  1
             final JsonObject json = jsonReader.readObject();
 136  1
             final EvidenceCollection productEvidence = dependency.getProductEvidence();
 137  1
             final EvidenceCollection vendorEvidence = dependency.getVendorEvidence();
 138  1
             if (json.containsKey("name")) {
 139  1
                 final Object value = json.get("name");
 140  1
                 if (value instanceof JsonString) {
 141  1
                     final String valueString = ((JsonString) value).getString();
 142  1
                     productEvidence.addEvidence(PACKAGE_JSON, "name", valueString, Confidence.HIGHEST);
 143  1
                     vendorEvidence.addEvidence(PACKAGE_JSON, "name_project", String.format("%s_project", valueString), Confidence.LOW);
 144  1
                 } else {
 145  0
                     LOGGER.warn("JSON value not string as expected: {}", value);
 146  
                 }
 147  
             }
 148  1
             addToEvidence(json, productEvidence, "description");
 149  1
             addToEvidence(json, vendorEvidence, "author");
 150  1
             addToEvidence(json, dependency.getVersionEvidence(), "version");
 151  1
             dependency.setDisplayFileName(String.format("%s/%s", file.getParentFile().getName(), file.getName()));
 152  0
         } catch (JsonException e) {
 153  0
             LOGGER.warn("Failed to parse package.json file.", e);
 154  
         } finally {
 155  1
             jsonReader.close();
 156  1
         }
 157  1
     }
 158  
 
 159  
     /**
 160  
      * Adds information to an evidence collection from the node json
 161  
      * configuration.
 162  
      *
 163  
      * @param json information from node.js
 164  
      * @param collection a set of evidence about a dependency
 165  
      * @param key the key to obtain the data from the json information
 166  
      */
 167  
     private void addToEvidence(JsonObject json, EvidenceCollection collection, String key) {
 168  3
         if (json.containsKey(key)) {
 169  3
             final JsonValue value = json.get(key);
 170  3
             if (value instanceof JsonString) {
 171  2
                 collection.addEvidence(PACKAGE_JSON, key, ((JsonString) value).getString(), Confidence.HIGHEST);
 172  1
             } else if (value instanceof JsonObject) {
 173  1
                 final JsonObject jsonObject = (JsonObject) value;
 174  1
                 for (final Map.Entry<String, JsonValue> entry : jsonObject.entrySet()) {
 175  1
                     final String property = entry.getKey();
 176  1
                     final JsonValue subValue = entry.getValue();
 177  1
                     if (subValue instanceof JsonString) {
 178  2
                         collection.addEvidence(PACKAGE_JSON,
 179  1
                                 String.format("%s.%s", key, property),
 180  1
                                 ((JsonString) subValue).getString(),
 181  
                                 Confidence.HIGHEST);
 182  
                     } else {
 183  0
                         LOGGER.warn("JSON sub-value not string as expected: {}", subValue);
 184  
                     }
 185  1
                 }
 186  1
             } else {
 187  0
                 LOGGER.warn("JSON value not string or JSON object as expected: {}", value);
 188  
             }
 189  
         }
 190  3
     }
 191  
 }