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