1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.owasp.dependencycheck;
19
20 import java.io.File;
21 import java.io.FileNotFoundException;
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.Set;
26
27 import org.apache.commons.cli.ParseException;
28 import org.apache.tools.ant.DirectoryScanner;
29 import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
30 import org.owasp.dependencycheck.dependency.Dependency;
31 import org.owasp.dependencycheck.dependency.Vulnerability;
32 import org.apache.tools.ant.types.LogLevel;
33 import org.owasp.dependencycheck.data.update.exception.UpdateException;
34 import org.owasp.dependencycheck.exception.ExceptionCollection;
35 import org.owasp.dependencycheck.exception.ReportException;
36 import org.owasp.dependencycheck.utils.Downloader;
37 import org.owasp.dependencycheck.utils.InvalidSettingException;
38 import org.owasp.dependencycheck.utils.Settings;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 import ch.qos.logback.core.FileAppender;
43 import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
44 import ch.qos.logback.classic.filter.ThresholdFilter;
45 import ch.qos.logback.classic.spi.ILoggingEvent;
46 import ch.qos.logback.classic.Level;
47 import ch.qos.logback.classic.LoggerContext;
48 import io.github.jeremylong.jcs3.slf4j.Slf4jAdapter;
49 import java.util.TreeSet;
50 import org.owasp.dependencycheck.utils.SeverityUtil;
51
52
53
54
55
56
57 @SuppressWarnings("squid:S106")
58 public class App {
59
60
61
62
63 private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
64
65
66
67 private static final String ERROR_LOADING_PROPERTIES_FILE = "Error loading properties file";
68
69
70
71 private static final String NEW_LINE = System.getProperty("line.separator", "\n");
72
73
74
75 private final Settings settings;
76
77
78
79
80
81
82 @SuppressWarnings("squid:S4823")
83 public static void main(String[] args) {
84 System.setProperty("jcs.logSystem", "slf4j");
85 if (!LOGGER.isDebugEnabled()) {
86 Slf4jAdapter.muteLogging(true);
87 }
88 final int exitCode;
89 final App app = new App();
90 exitCode = app.run(args);
91 LOGGER.debug("Exit code: {}", exitCode);
92 System.exit(exitCode);
93 }
94
95
96
97
98 public App() {
99 settings = new Settings();
100 }
101
102
103
104
105
106
107 protected App(Settings settings) {
108 this.settings = settings;
109 }
110
111
112
113
114
115
116
117 public int run(String[] args) {
118 int exitCode = 0;
119 final CliParser cli = new CliParser(settings);
120
121 try {
122 cli.parse(args);
123 } catch (FileNotFoundException ex) {
124 System.err.println(ex.getMessage());
125 cli.printHelp();
126 return 1;
127 } catch (ParseException ex) {
128 System.err.println(ex.getMessage());
129 cli.printHelp();
130 return 2;
131 }
132 final String verboseLog = cli.getStringArgument(CliParser.ARGUMENT.VERBOSE_LOG);
133 if (verboseLog != null) {
134 prepareLogger(verboseLog);
135 }
136
137 if (cli.isPurge()) {
138 final String connStr = cli.getStringArgument(CliParser.ARGUMENT.CONNECTION_STRING);
139 if (connStr != null) {
140 LOGGER.error("Unable to purge the database when using a non-default connection string");
141 exitCode = 3;
142 } else {
143 try {
144 populateSettings(cli);
145 Downloader.getInstance().configure(settings);
146 } catch (InvalidSettingException ex) {
147 LOGGER.error(ex.getMessage());
148 LOGGER.debug(ERROR_LOADING_PROPERTIES_FILE, ex);
149 exitCode = 4;
150 return exitCode;
151 }
152 try (Engine engine = new Engine(Engine.Mode.EVIDENCE_PROCESSING, settings)) {
153 if (!engine.purge()) {
154 exitCode = 7;
155 return exitCode;
156 }
157 } finally {
158 settings.cleanup();
159 }
160 }
161 } else if (cli.isGetVersion()) {
162 cli.printVersionInfo();
163 } else if (cli.isUpdateOnly()) {
164 try {
165 populateSettings(cli);
166 settings.setBoolean(Settings.KEYS.AUTO_UPDATE, true);
167 Downloader.getInstance().configure(settings);
168 } catch (InvalidSettingException ex) {
169 LOGGER.error(ex.getMessage());
170 LOGGER.debug(ERROR_LOADING_PROPERTIES_FILE, ex);
171 exitCode = 4;
172 return exitCode;
173 }
174 try {
175 runUpdateOnly();
176 } catch (UpdateException ex) {
177 LOGGER.error(ex.getMessage(), ex);
178 exitCode = 8;
179 } catch (DatabaseException ex) {
180 LOGGER.error(ex.getMessage(), ex);
181 exitCode = 9;
182 } finally {
183 settings.cleanup();
184 }
185 } else if (cli.isRunScan()) {
186 try {
187 populateSettings(cli);
188 Downloader.getInstance().configure(settings);
189 } catch (InvalidSettingException ex) {
190 LOGGER.error(ex.getMessage(), ex);
191 LOGGER.debug(ERROR_LOADING_PROPERTIES_FILE, ex);
192 exitCode = 4;
193 return exitCode;
194 }
195 try {
196 final String[] scanFiles = cli.getScanFiles();
197 if (scanFiles != null) {
198 exitCode = runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getProjectName(), scanFiles,
199 cli.getExcludeList(), cli.getSymLinkDepth(), cli.getFailOnCVSS());
200 } else {
201 LOGGER.error("No scan files configured");
202 }
203 } catch (DatabaseException ex) {
204 LOGGER.error(ex.getMessage());
205 LOGGER.debug("database exception", ex);
206 exitCode = 11;
207 } catch (ReportException ex) {
208 LOGGER.error(ex.getMessage());
209 LOGGER.debug("report exception", ex);
210 exitCode = 12;
211 } catch (ExceptionCollection ex) {
212 if (ex.isFatal()) {
213 exitCode = 13;
214 LOGGER.error("One or more fatal errors occurred");
215 } else {
216 exitCode = 14;
217 }
218 for (Throwable e : ex.getExceptions()) {
219 if (e.getMessage() != null) {
220 LOGGER.error(e.getMessage());
221 LOGGER.debug("unexpected error", e);
222 }
223 }
224 } finally {
225 settings.cleanup();
226 }
227 } else {
228 cli.printHelp();
229 }
230 return exitCode;
231 }
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253 private int runScan(String reportDirectory, String[] outputFormats, String applicationName, String[] files,
254 String[] excludes, int symLinkDepth, float cvssFailScore) throws DatabaseException,
255 ExceptionCollection, ReportException {
256 Engine engine = null;
257 try {
258 final List<String> antStylePaths = getPaths(files);
259 final Set<File> paths = scanAntStylePaths(antStylePaths, symLinkDepth, excludes);
260
261 engine = new Engine(settings);
262 engine.scan(paths);
263
264 ExceptionCollection exCol = null;
265 try {
266 engine.analyzeDependencies();
267 } catch (ExceptionCollection ex) {
268 if (ex.isFatal()) {
269 throw ex;
270 }
271 exCol = ex;
272 }
273
274 try {
275 for (String outputFormat : outputFormats) {
276 engine.writeReports(applicationName, new File(reportDirectory), outputFormat, exCol);
277 }
278 } catch (ReportException ex) {
279 if (exCol != null) {
280 exCol.addException(ex);
281 throw exCol;
282 } else {
283 throw ex;
284 }
285 }
286 if (exCol != null && !exCol.getExceptions().isEmpty()) {
287 throw exCol;
288 }
289 return determineReturnCode(engine, cvssFailScore);
290 } finally {
291 if (engine != null) {
292 engine.close();
293 }
294 }
295 }
296
297
298
299
300
301
302
303
304
305
306 private int determineReturnCode(Engine engine, float cvssFailScore) {
307 int retCode = 0;
308
309 final StringBuilder ids = new StringBuilder();
310 for (Dependency d : engine.getDependencies()) {
311 boolean addName = true;
312 for (Vulnerability v : d.getVulnerabilities()) {
313 final Double cvssV2 = v.getCvssV2() != null && v.getCvssV2().getCvssData() != null
314 && v.getCvssV2().getCvssData().getBaseScore() != null ? v.getCvssV2().getCvssData().getBaseScore() : -1;
315 final Double cvssV3 = v.getCvssV3() != null && v.getCvssV3().getCvssData() != null
316 && v.getCvssV3().getCvssData().getBaseScore() != null ? v.getCvssV3().getCvssData().getBaseScore() : -1;
317 final Double unscoredCvss = v.getUnscoredSeverity() != null ? SeverityUtil.estimateCvssV2(v.getUnscoredSeverity()) : -1;
318
319 if (cvssV2 >= cvssFailScore
320 || cvssV3 >= cvssFailScore
321 || unscoredCvss >= cvssFailScore
322
323 || (cvssFailScore <= 0.0f)) {
324 double score = 0.0;
325 if (cvssV3 >= 0.0) {
326 score = cvssV3;
327 } else if (cvssV2 >= 0.0) {
328 score = cvssV2;
329 } else if (unscoredCvss >= 0.0) {
330 score = unscoredCvss;
331 }
332 if (addName) {
333 addName = false;
334 ids.append(NEW_LINE).append(d.getFileName()).append(": ");
335 ids.append(v.getName()).append('(').append(score).append(')');
336 } else {
337 ids.append(", ").append(v.getName()).append('(').append(score).append(')');
338 }
339 }
340 }
341 }
342 if (ids.length() > 0) {
343 LOGGER.error(
344 String.format("%n%nOne or more dependencies were identified with vulnerabilities that have a CVSS score greater than or "
345 + "equal to '%.1f': %n%s%n%nSee the dependency-check report for more details.%n%n", cvssFailScore, ids)
346 );
347
348 retCode = 15;
349 }
350
351 return retCode;
352 }
353
354
355
356
357
358
359
360
361
362 private Set<File> scanAntStylePaths(List<String> antStylePaths, int symLinkDepth, String[] excludes) {
363 final Set<File> paths = new TreeSet<>();
364 for (String file : antStylePaths) {
365 LOGGER.debug("Scanning {}", file);
366 final DirectoryScanner scanner = new DirectoryScanner();
367 String include = file.replace('\\', '/');
368 final File baseDir;
369 final int pos = getLastFileSeparator(include);
370 final String tmpBase = include.substring(0, pos);
371 final String tmpInclude = include.substring(pos + 1);
372 if (tmpInclude.indexOf('*') >= 0 || tmpInclude.indexOf('?') >= 0
373 || new File(include).isFile()) {
374 baseDir = new File(tmpBase);
375 include = tmpInclude;
376 } else {
377 baseDir = new File(tmpBase, tmpInclude);
378 include = "**/*";
379 }
380 LOGGER.debug("BaseDir: " + baseDir);
381 LOGGER.debug("Include: " + include);
382 scanner.setBasedir(baseDir);
383 final String[] includes = {include};
384 scanner.setIncludes(includes);
385 scanner.setMaxLevelsOfSymlinks(symLinkDepth);
386 if (symLinkDepth <= 0) {
387 scanner.setFollowSymlinks(false);
388 }
389 if (excludes != null && excludes.length > 0) {
390 for (String e : excludes) {
391 LOGGER.debug("Exclude: " + e);
392 }
393 scanner.addExcludes(excludes);
394 }
395 scanner.scan();
396 if (scanner.getIncludedFilesCount() > 0) {
397 for (String s : scanner.getIncludedFiles()) {
398 final File f = new File(baseDir, s);
399 LOGGER.debug("Found file {}", f);
400 paths.add(f);
401 }
402 }
403 }
404 return paths;
405 }
406
407
408
409
410
411
412
413 private List<String> getPaths(String[] files) {
414 final List<String> antStylePaths = new ArrayList<>();
415 for (String file : files) {
416 final String antPath = ensureCanonicalPath(file);
417 antStylePaths.add(antPath);
418 }
419 return antStylePaths;
420 }
421
422
423
424
425
426
427
428
429 private void runUpdateOnly() throws UpdateException, DatabaseException {
430 try (Engine engine = new Engine(settings)) {
431 engine.doUpdates();
432 }
433 }
434
435
436
437
438
439
440
441
442
443
444 protected void populateSettings(CliParser cli) throws InvalidSettingException {
445 final File propertiesFile = cli.getFileArgument(CliParser.ARGUMENT.PROP);
446 if (propertiesFile != null) {
447 try {
448 settings.mergeProperties(propertiesFile);
449 } catch (FileNotFoundException ex) {
450 throw new InvalidSettingException("Unable to find properties file '" + propertiesFile.getPath() + "'", ex);
451 } catch (IOException ex) {
452 throw new InvalidSettingException("Error reading properties file '" + propertiesFile.getPath() + "'", ex);
453 }
454 }
455 final String dataDirectory = cli.getStringArgument(CliParser.ARGUMENT.DATA_DIRECTORY);
456 if (dataDirectory != null) {
457 settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
458 } else if (System.getProperty("basedir") != null) {
459 final File dataDir = new File(System.getProperty("basedir"), "data");
460 settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
461 } else {
462 final File jarPath = new File(App.class
463 .getProtectionDomain().getCodeSource().getLocation().getPath());
464 final File base = jarPath.getParentFile();
465 final String sub = settings.getString(Settings.KEYS.DATA_DIRECTORY);
466 final File dataDir = new File(base, sub);
467 settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
468 }
469 final Boolean autoUpdate = cli.hasOption(CliParser.ARGUMENT.DISABLE_AUTO_UPDATE) != null ? false : null;
470 settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate);
471 settings.setStringIfNotEmpty(Settings.KEYS.PROXY_SERVER,
472 cli.getStringArgument(CliParser.ARGUMENT.PROXY_SERVER));
473 settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PORT,
474 cli.getStringArgument(CliParser.ARGUMENT.PROXY_PORT));
475 settings.setStringIfNotEmpty(Settings.KEYS.PROXY_USERNAME,
476 cli.getStringArgument(CliParser.ARGUMENT.PROXY_USERNAME));
477 settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PASSWORD,
478 cli.getStringArgument(CliParser.ARGUMENT.PROXY_PASSWORD, Settings.KEYS.PROXY_PASSWORD));
479 settings.setStringIfNotEmpty(Settings.KEYS.PROXY_NON_PROXY_HOSTS,
480 cli.getStringArgument(CliParser.ARGUMENT.NON_PROXY_HOSTS));
481 settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT,
482 cli.getStringArgument(CliParser.ARGUMENT.CONNECTION_TIMEOUT));
483 settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_READ_TIMEOUT,
484 cli.getStringArgument(CliParser.ARGUMENT.CONNECTION_READ_TIMEOUT));
485 settings.setStringIfNotEmpty(Settings.KEYS.HINTS_FILE,
486 cli.getStringArgument(CliParser.ARGUMENT.HINTS_FILE));
487 settings.setArrayIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE,
488 cli.getStringArguments(CliParser.ARGUMENT.SUPPRESSION_FILES));
489
490 settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED,
491 cli.hasOption(CliParser.ARGUMENT.EXPERIMENTAL));
492 settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RETIRED_ENABLED,
493 cli.hasOption(CliParser.ARGUMENT.RETIRED));
494 settings.setStringIfNotNull(Settings.KEYS.ANALYZER_GOLANG_PATH,
495 cli.getStringArgument(CliParser.ARGUMENT.PATH_TO_GO));
496 settings.setStringIfNotNull(Settings.KEYS.ANALYZER_YARN_PATH,
497 cli.getStringArgument(CliParser.ARGUMENT.PATH_TO_YARN));
498 settings.setStringIfNotNull(Settings.KEYS.ANALYZER_PNPM_PATH,
499 cli.getStringArgument(CliParser.ARGUMENT.PATH_TO_PNPM));
500 settings.setBooleanIfNotNull(Settings.KEYS.PRETTY_PRINT,
501 cli.hasOption(CliParser.ARGUMENT.PRETTY_PRINT));
502 settings.setStringIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_REPO_JS_URL,
503 cli.getStringArgument(CliParser.ARGUMENT.RETIREJS_URL));
504 settings.setStringIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_REPO_JS_USER,
505 cli.getStringArgument(CliParser.ARGUMENT.RETIREJS_URL_USER));
506 settings.setStringIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_REPO_JS_PASSWORD,
507 cli.getStringArgument(CliParser.ARGUMENT.RETIREJS_URL_PASSWORD));
508 settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_FORCEUPDATE,
509 cli.hasOption(CliParser.ARGUMENT.RETIRE_JS_FORCEUPDATE));
510 settings.setStringIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_FILTERS,
511 cli.getStringArgument(CliParser.ARGUMENT.RETIREJS_FILTERS));
512 settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_FILTER_NON_VULNERABLE,
513 cli.hasOption(CliParser.ARGUMENT.RETIREJS_FILTER_NON_VULNERABLE));
514 settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED,
515 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_JAR, Settings.KEYS.ANALYZER_JAR_ENABLED));
516 settings.setBoolean(Settings.KEYS.ANALYZER_MSBUILD_PROJECT_ENABLED,
517 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_MSBUILD, Settings.KEYS.ANALYZER_MSBUILD_PROJECT_ENABLED));
518 settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED,
519 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_ARCHIVE, Settings.KEYS.ANALYZER_ARCHIVE_ENABLED));
520 settings.setBoolean(Settings.KEYS.ANALYZER_KNOWN_EXPLOITED_ENABLED,
521 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_KEV, Settings.KEYS.ANALYZER_KNOWN_EXPLOITED_ENABLED));
522 settings.setStringIfNotNull(Settings.KEYS.KEV_URL,
523 cli.getStringArgument(CliParser.ARGUMENT.KEV_URL));
524 settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED,
525 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_PY_DIST, Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED));
526 settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED,
527 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_PY_PKG, Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED));
528 settings.setBoolean(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED,
529 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_AUTOCONF, Settings.KEYS.ANALYZER_AUTOCONF_ENABLED));
530 settings.setBoolean(Settings.KEYS.ANALYZER_MAVEN_INSTALL_ENABLED,
531 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_MAVEN_INSTALL, Settings.KEYS.ANALYZER_MAVEN_INSTALL_ENABLED));
532 settings.setBoolean(Settings.KEYS.ANALYZER_PIP_ENABLED,
533 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_PIP, Settings.KEYS.ANALYZER_PIP_ENABLED));
534 settings.setBoolean(Settings.KEYS.ANALYZER_PIPFILE_ENABLED,
535 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_PIPFILE, Settings.KEYS.ANALYZER_PIPFILE_ENABLED));
536 settings.setBoolean(Settings.KEYS.ANALYZER_POETRY_ENABLED,
537 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_POETRY, Settings.KEYS.ANALYZER_POETRY_ENABLED));
538 settings.setBoolean(Settings.KEYS.ANALYZER_CMAKE_ENABLED,
539 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_CMAKE, Settings.KEYS.ANALYZER_CMAKE_ENABLED));
540 settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED,
541 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_NUSPEC, Settings.KEYS.ANALYZER_NUSPEC_ENABLED));
542 settings.setBoolean(Settings.KEYS.ANALYZER_NUGETCONF_ENABLED,
543 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_NUGETCONF, Settings.KEYS.ANALYZER_NUGETCONF_ENABLED));
544 settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED,
545 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_ASSEMBLY, Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED));
546 settings.setBoolean(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED,
547 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_BUNDLE_AUDIT, Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED));
548 settings.setBoolean(Settings.KEYS.ANALYZER_FILE_NAME_ENABLED,
549 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_FILENAME, Settings.KEYS.ANALYZER_FILE_NAME_ENABLED));
550 settings.setBoolean(Settings.KEYS.ANALYZER_MIX_AUDIT_ENABLED,
551 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_MIX_AUDIT, Settings.KEYS.ANALYZER_MIX_AUDIT_ENABLED));
552 settings.setBoolean(Settings.KEYS.ANALYZER_OPENSSL_ENABLED,
553 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_OPENSSL, Settings.KEYS.ANALYZER_OPENSSL_ENABLED));
554 settings.setBoolean(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED,
555 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_COMPOSER, Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED));
556 settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_SKIP_DEV,
557 cli.hasOption(CliParser.ARGUMENT.COMPOSER_LOCK_SKIP_DEV));
558 settings.setBoolean(Settings.KEYS.ANALYZER_CPANFILE_ENABLED,
559 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_CPAN, Settings.KEYS.ANALYZER_CPANFILE_ENABLED));
560 settings.setBoolean(Settings.KEYS.ANALYZER_GOLANG_DEP_ENABLED,
561 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_GO_DEP, Settings.KEYS.ANALYZER_GOLANG_DEP_ENABLED));
562 settings.setBoolean(Settings.KEYS.ANALYZER_GOLANG_MOD_ENABLED,
563 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_GOLANG_MOD, Settings.KEYS.ANALYZER_GOLANG_MOD_ENABLED));
564 settings.setBoolean(Settings.KEYS.ANALYZER_DART_ENABLED,
565 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_DART, Settings.KEYS.ANALYZER_DART_ENABLED));
566 settings.setBoolean(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED,
567 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_NODE_JS, Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED));
568 settings.setBoolean(Settings.KEYS.ANALYZER_NODE_AUDIT_ENABLED,
569 !cli.isNodeAuditDisabled());
570 settings.setBoolean(Settings.KEYS.ANALYZER_YARN_AUDIT_ENABLED,
571 !cli.isYarnAuditDisabled());
572 settings.setBoolean(Settings.KEYS.ANALYZER_PNPM_AUDIT_ENABLED,
573 !cli.isPnpmAuditDisabled());
574 settings.setBoolean(Settings.KEYS.ANALYZER_NODE_AUDIT_USE_CACHE,
575 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_NODE_AUDIT_CACHE, Settings.KEYS.ANALYZER_NODE_AUDIT_USE_CACHE));
576 settings.setBoolean(Settings.KEYS.ANALYZER_RETIREJS_ENABLED,
577 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_RETIRE_JS, Settings.KEYS.ANALYZER_RETIREJS_ENABLED));
578 settings.setBoolean(Settings.KEYS.ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED,
579 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_SWIFT, Settings.KEYS.ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED));
580 settings.setBoolean(Settings.KEYS.ANALYZER_SWIFT_PACKAGE_RESOLVED_ENABLED,
581 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_SWIFT_RESOLVED, Settings.KEYS.ANALYZER_SWIFT_PACKAGE_RESOLVED_ENABLED));
582 settings.setBoolean(Settings.KEYS.ANALYZER_COCOAPODS_ENABLED,
583 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_COCOAPODS, Settings.KEYS.ANALYZER_COCOAPODS_ENABLED));
584 settings.setBoolean(Settings.KEYS.ANALYZER_CARTHAGE_ENABLED,
585 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_CARTHAGE, Settings.KEYS.ANALYZER_CARTHAGE_ENABLED));
586 settings.setBoolean(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED,
587 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_RUBYGEMS, Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED));
588 settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED,
589 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_CENTRAL, Settings.KEYS.ANALYZER_CENTRAL_ENABLED));
590 settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_USE_CACHE,
591 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_CENTRAL_CACHE, Settings.KEYS.ANALYZER_CENTRAL_USE_CACHE));
592 settings.setBoolean(Settings.KEYS.ANALYZER_OSSINDEX_ENABLED,
593 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_OSSINDEX, Settings.KEYS.ANALYZER_OSSINDEX_ENABLED));
594 settings.setBoolean(Settings.KEYS.ANALYZER_OSSINDEX_USE_CACHE,
595 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_OSSINDEX_CACHE, Settings.KEYS.ANALYZER_OSSINDEX_USE_CACHE));
596
597 settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_PACKAGE_SKIPDEV,
598 cli.hasOption(CliParser.ARGUMENT.NODE_PACKAGE_SKIP_DEV_DEPENDENCIES));
599 settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_AUDIT_SKIPDEV,
600 cli.hasOption(CliParser.ARGUMENT.DISABLE_NODE_AUDIT_SKIPDEV));
601 settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_ENABLED,
602 cli.hasOption(CliParser.ARGUMENT.ENABLE_NEXUS));
603 settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_CENTRAL_URL,
604 cli.getStringArgument(CliParser.ARGUMENT.CENTRAL_URL));
605 settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_OSSINDEX_URL,
606 cli.getStringArgument(CliParser.ARGUMENT.OSSINDEX_URL));
607 settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_OSSINDEX_USER,
608 cli.getStringArgument(CliParser.ARGUMENT.OSSINDEX_USERNAME));
609 settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_OSSINDEX_PASSWORD,
610 cli.getStringArgument(CliParser.ARGUMENT.OSSINDEX_PASSWORD, Settings.KEYS.ANALYZER_OSSINDEX_PASSWORD));
611 settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_OSSINDEX_WARN_ONLY_ON_REMOTE_ERRORS,
612 cli.getStringArgument(CliParser.ARGUMENT.OSSINDEX_WARN_ONLY_ON_REMOTE_ERRORS,
613 Settings.KEYS.ANALYZER_OSSINDEX_WARN_ONLY_ON_REMOTE_ERRORS));
614 settings.setFloat(Settings.KEYS.JUNIT_FAIL_ON_CVSS,
615 cli.getFloatArgument(CliParser.ARGUMENT.FAIL_JUNIT_ON_CVSS, 0));
616 settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARTIFACTORY_ENABLED,
617 cli.hasOption(CliParser.ARGUMENT.ARTIFACTORY_ENABLED));
618 settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARTIFACTORY_PARALLEL_ANALYSIS,
619 cli.getBooleanArgument(CliParser.ARGUMENT.ARTIFACTORY_PARALLEL_ANALYSIS));
620 settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARTIFACTORY_USES_PROXY,
621 cli.getBooleanArgument(CliParser.ARGUMENT.ARTIFACTORY_USES_PROXY));
622 settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ARTIFACTORY_URL,
623 cli.getStringArgument(CliParser.ARGUMENT.ARTIFACTORY_URL));
624 settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ARTIFACTORY_API_USERNAME,
625 cli.getStringArgument(CliParser.ARGUMENT.ARTIFACTORY_USERNAME));
626 settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ARTIFACTORY_API_TOKEN,
627 cli.getStringArgument(CliParser.ARGUMENT.ARTIFACTORY_API_TOKEN));
628 settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ARTIFACTORY_BEARER_TOKEN,
629 cli.getStringArgument(CliParser.ARGUMENT.ARTIFACTORY_BEARER_TOKEN));
630 settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_MIX_AUDIT_PATH,
631 cli.getStringArgument(CliParser.ARGUMENT.PATH_TO_MIX_AUDIT));
632 settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH,
633 cli.getStringArgument(CliParser.ARGUMENT.PATH_TO_BUNDLE_AUDIT));
634 settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_WORKING_DIRECTORY,
635 cli.getStringArgument(CliParser.ARGUMENT.PATH_TO_BUNDLE_AUDIT_WORKING_DIRECTORY));
636 settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL,
637 cli.getStringArgument(CliParser.ARGUMENT.NEXUS_URL));
638 settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_USER,
639 cli.getStringArgument(CliParser.ARGUMENT.NEXUS_USERNAME));
640 settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_PASSWORD,
641 cli.getStringArgument(CliParser.ARGUMENT.NEXUS_PASSWORD, Settings.KEYS.ANALYZER_NEXUS_PASSWORD));
642
643 final boolean nexusUsesProxy = cli.isNexusUsesProxy();
644 settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy);
645 settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME,
646 cli.getStringArgument(CliParser.ARGUMENT.DB_DRIVER));
647 settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH,
648 cli.getStringArgument(CliParser.ARGUMENT.DB_DRIVER_PATH));
649 settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING,
650 cli.getStringArgument(CliParser.ARGUMENT.CONNECTION_STRING));
651 settings.setStringIfNotEmpty(Settings.KEYS.DB_USER,
652 cli.getStringArgument(CliParser.ARGUMENT.DB_NAME));
653 settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD,
654 cli.getStringArgument(CliParser.ARGUMENT.DB_PASSWORD, Settings.KEYS.DB_PASSWORD));
655 settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS,
656 cli.getStringArgument(CliParser.ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS));
657 settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_DOTNET_PATH,
658 cli.getStringArgument(CliParser.ARGUMENT.PATH_TO_CORE));
659
660 String key = cli.getStringArgument(CliParser.ARGUMENT.NVD_API_KEY);
661 if (key != null) {
662 if ((key.startsWith("\"") && key.endsWith("\"") || (key.startsWith("'") && key.endsWith("'")))) {
663 key = key.substring(1, key.length() - 1);
664 }
665 settings.setStringIfNotEmpty(Settings.KEYS.NVD_API_KEY, key);
666 }
667 settings.setStringIfNotEmpty(Settings.KEYS.NVD_API_ENDPOINT,
668 cli.getStringArgument(CliParser.ARGUMENT.NVD_API_ENDPOINT));
669 settings.setIntIfNotNull(Settings.KEYS.NVD_API_DELAY, cli.getIntegerValue(CliParser.ARGUMENT.NVD_API_DELAY));
670 settings.setIntIfNotNull(Settings.KEYS.NVD_API_RESULTS_PER_PAGE, cli.getIntegerValue(CliParser.ARGUMENT.NVD_API_RESULTS_PER_PAGE));
671 settings.setStringIfNotEmpty(Settings.KEYS.NVD_API_DATAFEED_URL, cli.getStringArgument(CliParser.ARGUMENT.NVD_API_DATAFEED_URL));
672 settings.setStringIfNotEmpty(Settings.KEYS.NVD_API_DATAFEED_USER, cli.getStringArgument(CliParser.ARGUMENT.NVD_API_DATAFEED_USER));
673 settings.setStringIfNotEmpty(Settings.KEYS.NVD_API_DATAFEED_PASSWORD, cli.getStringArgument(CliParser.ARGUMENT.NVD_API_DATAFEED_PASSWORD));
674 settings.setIntIfNotNull(Settings.KEYS.NVD_API_MAX_RETRY_COUNT, cli.getIntegerValue(CliParser.ARGUMENT.NVD_API_MAX_RETRY_COUNT));
675 settings.setIntIfNotNull(Settings.KEYS.NVD_API_VALID_FOR_HOURS, cli.getIntegerValue(CliParser.ARGUMENT.NVD_API_VALID_FOR_HOURS));
676
677 settings.setStringIfNotNull(Settings.KEYS.HOSTED_SUPPRESSIONS_URL,
678 cli.getStringArgument(CliParser.ARGUMENT.HOSTED_SUPPRESSIONS_URL));
679 settings.setBoolean(Settings.KEYS.HOSTED_SUPPRESSIONS_ENABLED,
680 !cli.isDisabled(CliParser.ARGUMENT.DISABLE_HOSTED_SUPPRESSIONS, Settings.KEYS.HOSTED_SUPPRESSIONS_ENABLED));
681 settings.setBooleanIfNotNull(Settings.KEYS.HOSTED_SUPPRESSIONS_FORCEUPDATE,
682 cli.hasOption(CliParser.ARGUMENT.HOSTED_SUPPRESSIONS_FORCEUPDATE));
683 settings.setIntIfNotNull(Settings.KEYS.HOSTED_SUPPRESSIONS_VALID_FOR_HOURS,
684 cli.getIntegerValue(CliParser.ARGUMENT.HOSTED_SUPPRESSIONS_VALID_FOR_HOURS));
685 }
686
687
688
689
690
691
692
693 private void prepareLogger(String verboseLog) {
694 final LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
695 final PatternLayoutEncoder encoder = new PatternLayoutEncoder();
696 encoder.setPattern("%d %C:%L%n%-5level - %msg%n");
697 encoder.setContext(context);
698 encoder.start();
699 final FileAppender<ILoggingEvent> fa = new FileAppender<>();
700 fa.setAppend(true);
701 fa.setEncoder(encoder);
702 fa.setContext(context);
703 fa.setFile(verboseLog);
704 final File f = new File(verboseLog);
705 String name = f.getName();
706 final int i = name.lastIndexOf('.');
707 if (i > 1) {
708 name = name.substring(0, i);
709 }
710 fa.setName(name);
711 fa.start();
712 final ch.qos.logback.classic.Logger rootLogger = context.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
713 rootLogger.setLevel(Level.DEBUG);
714 final ThresholdFilter filter = new ThresholdFilter();
715 filter.setLevel(LogLevel.INFO.getValue());
716 filter.setContext(context);
717 filter.start();
718 rootLogger.iteratorForAppenders().forEachRemaining(action -> action.addFilter(filter));
719 rootLogger.addAppender(fa);
720 }
721
722
723
724
725
726
727
728
729
730
731 protected String ensureCanonicalPath(String path) {
732 final String basePath;
733 String wildCards = null;
734 final String file = path.replace('\\', '/');
735 if (file.contains("*") || file.contains("?")) {
736
737 int pos = getLastFileSeparator(file);
738 if (pos < 0) {
739 return file;
740 }
741 pos += 1;
742 basePath = file.substring(0, pos);
743 wildCards = file.substring(pos);
744 } else {
745 basePath = file;
746 }
747
748 File f = new File(basePath);
749 try {
750 f = f.getCanonicalFile();
751 if (wildCards != null) {
752 f = new File(f, wildCards);
753 }
754 } catch (IOException ex) {
755 LOGGER.warn("Invalid path '{}' was provided.", path);
756 LOGGER.debug("Invalid path provided", ex);
757 }
758 return f.getAbsolutePath().replace('\\', '/');
759 }
760
761
762
763
764
765
766
767 @SuppressWarnings("ManualMinMaxCalculation")
768 private int getLastFileSeparator(String file) {
769 if (file.contains("*") || file.contains("?")) {
770 int p1 = file.indexOf('*');
771 int p2 = file.indexOf('?');
772 p1 = p1 > 0 ? p1 : file.length();
773 p2 = p2 > 0 ? p2 : file.length();
774 int pos = p1 < p2 ? p1 : p2;
775 pos = file.lastIndexOf('/', pos);
776 return pos;
777 } else {
778 return file.lastIndexOf('/');
779 }
780 }
781 }