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