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