1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
45
46
47
48
49 @Experimental
50 public class NodePackageAnalyzer extends AbstractFileTypeAnalyzer {
51
52
53
54
55 private static final Logger LOGGER = LoggerFactory.getLogger(NodePackageAnalyzer.class);
56
57
58
59
60 private static final String ANALYZER_NAME = "Node.js Package Analyzer";
61
62
63
64
65 private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
66
67
68
69
70 public static final String PACKAGE_JSON = "package.json";
71
72
73
74 private static final FileFilter PACKAGE_JSON_FILTER = FileFilterBuilder.newInstance()
75 .addFilenames(PACKAGE_JSON).build();
76
77
78
79
80
81
82 @Override
83 protected FileFilter getFileFilter() {
84 return PACKAGE_JSON_FILTER;
85 }
86
87 @Override
88 protected void initializeFileTypeAnalyzer() throws InitializationException {
89
90 }
91
92
93
94
95
96
97 @Override
98 public String getName() {
99 return ANALYZER_NAME;
100 }
101
102
103
104
105
106
107 @Override
108 public AnalysisPhase getAnalysisPhase() {
109 return ANALYSIS_PHASE;
110 }
111
112
113
114
115
116
117
118 @Override
119 protected String getAnalyzerEnabledSettingKey() {
120 return Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED;
121 }
122
123 @Override
124 protected void analyzeDependency(Dependency dependency, Engine engine)
125 throws AnalysisException {
126 final File file = dependency.getActualFile();
127 JsonReader jsonReader;
128 try {
129 jsonReader = Json.createReader(FileUtils.openInputStream(file));
130 } catch (IOException e) {
131 throw new AnalysisException(
132 "Problem occurred while reading dependency file.", e);
133 }
134 try {
135 final JsonObject json = jsonReader.readObject();
136 final EvidenceCollection productEvidence = dependency.getProductEvidence();
137 final EvidenceCollection vendorEvidence = dependency.getVendorEvidence();
138 if (json.containsKey("name")) {
139 final Object value = json.get("name");
140 if (value instanceof JsonString) {
141 final String valueString = ((JsonString) value).getString();
142 productEvidence.addEvidence(PACKAGE_JSON, "name", valueString, Confidence.HIGHEST);
143 vendorEvidence.addEvidence(PACKAGE_JSON, "name_project", String.format("%s_project", valueString), Confidence.LOW);
144 } else {
145 LOGGER.warn("JSON value not string as expected: {}", value);
146 }
147 }
148 addToEvidence(json, productEvidence, "description");
149 addToEvidence(json, vendorEvidence, "author");
150 addToEvidence(json, dependency.getVersionEvidence(), "version");
151 dependency.setDisplayFileName(String.format("%s/%s", file.getParentFile().getName(), file.getName()));
152 } catch (JsonException e) {
153 LOGGER.warn("Failed to parse package.json file.", e);
154 } finally {
155 jsonReader.close();
156 }
157 }
158
159
160
161
162
163
164
165
166
167 private void addToEvidence(JsonObject json, EvidenceCollection collection, String key) {
168 if (json.containsKey(key)) {
169 final JsonValue value = json.get(key);
170 if (value instanceof JsonString) {
171 collection.addEvidence(PACKAGE_JSON, key, ((JsonString) value).getString(), Confidence.HIGHEST);
172 } else if (value instanceof JsonObject) {
173 final JsonObject jsonObject = (JsonObject) value;
174 for (final Map.Entry<String, JsonValue> entry : jsonObject.entrySet()) {
175 final String property = entry.getKey();
176 final JsonValue subValue = entry.getValue();
177 if (subValue instanceof JsonString) {
178 collection.addEvidence(PACKAGE_JSON,
179 String.format("%s.%s", key, property),
180 ((JsonString) subValue).getString(),
181 Confidence.HIGHEST);
182 } else {
183 LOGGER.warn("JSON sub-value not string as expected: {}", subValue);
184 }
185 }
186 } else {
187 LOGGER.warn("JSON value not string or JSON object as expected: {}", value);
188 }
189 }
190 }
191 }