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