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