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