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