View Javadoc
1   /*
2    * This file is part of dependency-check-cli.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   * Copyright (c) 2012 Jeremy Long. All Rights Reserved.
17   */
18  package org.owasp.dependencycheck;
19  
20  import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
21  
22  import java.io.File;
23  import java.io.FileNotFoundException;
24  
25  import org.apache.commons.cli.CommandLine;
26  import org.apache.commons.cli.CommandLineParser;
27  import org.apache.commons.cli.DefaultParser;
28  import org.apache.commons.cli.HelpFormatter;
29  import org.apache.commons.cli.Option;
30  import org.apache.commons.cli.OptionGroup;
31  import org.apache.commons.cli.Options;
32  import org.apache.commons.cli.ParseException;
33  import org.owasp.dependencycheck.reporting.ReportGenerator.Format;
34  import org.owasp.dependencycheck.utils.InvalidSettingException;
35  import org.owasp.dependencycheck.utils.Settings;
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  
39  /**
40   * A utility to parse command line arguments for the DependencyCheck.
41   *
42   * @author Jeremy Long
43   */
44  //suppress hard-coded password rule
45  @SuppressWarnings("squid:S2068")
46  public final class CliParser {
47  
48      /**
49       * The logger.
50       */
51      private static final Logger LOGGER = LoggerFactory.getLogger(CliParser.class);
52      /**
53       * The command line.
54       */
55      private CommandLine line;
56      /**
57       * Indicates whether the arguments are valid.
58       */
59      private boolean isValid = true;
60      /**
61       * The configured settings.
62       */
63      private final Settings settings;
64      /**
65       * The supported reported formats.
66       */
67      private static final String SUPPORTED_FORMATS = "HTML, XML, CSV, JSON, JUNIT, SARIF, JENKINS, GITLAB or ALL";
68  
69      /**
70       * Constructs a new CLI Parser object with the configured settings.
71       *
72       * @param settings the configured settings
73       */
74      public CliParser(Settings settings) {
75          this.settings = settings;
76      }
77  
78      /**
79       * Parses the arguments passed in and captures the results for later use.
80       *
81       * @param args the command line arguments
82       * @throws FileNotFoundException is thrown when a 'file' argument does not
83       * point to a file that exists.
84       * @throws ParseException is thrown when a Parse Exception occurs.
85       */
86      public void parse(String[] args) throws FileNotFoundException, ParseException {
87          line = parseArgs(args);
88  
89          if (line != null) {
90              validateArgs();
91          }
92      }
93  
94      /**
95       * Parses the command line arguments.
96       *
97       * @param args the command line arguments
98       * @return the results of parsing the command line arguments
99       * @throws ParseException if the arguments are invalid
100      */
101     private CommandLine parseArgs(String[] args) throws ParseException {
102         final CommandLineParser parser = new DefaultParser();
103         final Options options = createCommandLineOptions();
104         return parser.parse(options, args);
105     }
106 
107     /**
108      * Validates that the command line arguments are valid.
109      *
110      * @throws FileNotFoundException if there is a file specified by either the
111      * SCAN or CPE command line arguments that does not exist.
112      * @throws ParseException is thrown if there is an exception parsing the
113      * command line.
114      */
115     private void validateArgs() throws FileNotFoundException, ParseException {
116         if (isUpdateOnly() || isRunScan()) {
117 
118             String value = line.getOptionValue(ARGUMENT.NVD_API_VALID_FOR_HOURS);
119             if (value != null) {
120                 try {
121                     final int i = Integer.parseInt(value);
122                     if (i < 0) {
123                         throw new ParseException("Invalid Setting: nvdValidForHours must be a number greater than or equal to 0.");
124                     }
125                 } catch (NumberFormatException ex) {
126                     throw new ParseException("Invalid Setting: nvdValidForHours must be a number greater than or equal to 0.");
127                 }
128             }
129             value = line.getOptionValue(ARGUMENT.NVD_API_MAX_RETRY_COUNT);
130             if (value != null) {
131                 try {
132                     final int i = Integer.parseInt(value);
133                     if (i <= 0) {
134                         throw new ParseException("Invalid Setting: nvdMaxRetryCount must be a number greater than 0.");
135                     }
136                 } catch (NumberFormatException ex) {
137                     throw new ParseException("Invalid Setting: nvdMaxRetryCount must be a number greater than 0.");
138                 }
139             }
140             value = line.getOptionValue(ARGUMENT.NVD_API_DELAY);
141             if (value != null) {
142                 try {
143                     final int i = Integer.parseInt(value);
144                     if (i < 0) {
145                         throw new ParseException("Invalid Setting: nvdApiDelay must be a number greater than or equal to 0.");
146                     }
147                 } catch (NumberFormatException ex) {
148                     throw new ParseException("Invalid Setting: nvdApiDelay must be a number greater than or equal to 0.");
149                 }
150             }
151             value = line.getOptionValue(ARGUMENT.NVD_API_RESULTS_PER_PAGE);
152             if (value != null) {
153                 try {
154                     final int i = Integer.parseInt(value);
155                     if (i <= 0 || i > 2000) {
156                         throw new ParseException("Invalid Setting: nvdApiResultsPerPage must be a number in the range [1, 2000].");
157                     }
158                 } catch (NumberFormatException ex) {
159                     throw new ParseException("Invalid Setting: nvdApiResultsPerPage must be a number in the range [1, 2000].");
160                 }
161             }
162         }
163         if (isRunScan()) {
164             validatePathExists(getScanFiles(), ARGUMENT.SCAN);
165             validatePathExists(getReportDirectory(), ARGUMENT.OUT);
166             final String pathToCore = getStringArgument(ARGUMENT.PATH_TO_CORE);
167             if (pathToCore != null) {
168                 validatePathExists(pathToCore, ARGUMENT.PATH_TO_CORE);
169             }
170             if (line.hasOption(ARGUMENT.OUTPUT_FORMAT)) {
171                 for (String validating : getReportFormat()) {
172                     if (!isValidFormat(validating)
173                             && !isValidFilePath(validating, "format")) {
174                         final String msg = String.format("An invalid 'format' of '%s' was specified. "
175                                         + "Supported output formats are %s, and custom template files.",
176                                 validating, SUPPORTED_FORMATS);
177                         throw new ParseException(msg);
178                     }
179                 }
180             }
181             if (line.hasOption(ARGUMENT.SYM_LINK_DEPTH)) {
182                 try {
183                     final int i = Integer.parseInt(line.getOptionValue(ARGUMENT.SYM_LINK_DEPTH));
184                     if (i < 0) {
185                         throw new ParseException("Symbolic Link Depth (symLink) must be greater than zero.");
186                     }
187                 } catch (NumberFormatException ex) {
188                     throw new ParseException("Symbolic Link Depth (symLink) is not a number.");
189                 }
190             }
191         }
192     }
193 
194     /**
195      * Validates the format to be one of the known Formats.
196      *
197      * @param format the format to validate
198      * @return true, if format is known in Format; false otherwise
199      * @see Format
200      */
201     private boolean isValidFormat(String format) {
202         try {
203             Format.valueOf(format);
204             return true;
205         } catch (IllegalArgumentException ex) {
206             return false;
207         }
208     }
209 
210     /**
211      * Validates the path to point at an existing file.
212      *
213      * @param path the path to validate if it exists
214      * @param argumentName the argument being validated (e.g. scan, out, etc.)
215      * @return true, if path exists; false otherwise
216      */
217     private boolean isValidFilePath(String path, String argumentName) {
218         try {
219             validatePathExists(path, argumentName);
220             return true;
221         } catch (FileNotFoundException ex) {
222             return false;
223         }
224     }
225 
226     /**
227      * Validates whether or not the path(s) points at a file that exists; if the
228      * path(s) does not point to an existing file a FileNotFoundException is
229      * thrown.
230      *
231      * @param paths the paths to validate if they exists
232      * @param optType the option being validated (e.g. scan, out, etc.)
233      * @throws FileNotFoundException is thrown if one of the paths being
234      * validated does not exist.
235      */
236     private void validatePathExists(String[] paths, String optType) throws FileNotFoundException {
237         for (String path : paths) {
238             validatePathExists(path, optType);
239         }
240     }
241 
242     /**
243      * Validates whether or not the path points at a file that exists; if the
244      * path does not point to an existing file a FileNotFoundException is
245      * thrown.
246      *
247      * @param path the paths to validate if they exists
248      * @param argumentName the argument being validated (e.g. scan, out, etc.)
249      * @throws FileNotFoundException is thrown if the path being validated does
250      * not exist.
251      */
252     private void validatePathExists(String path, String argumentName) throws FileNotFoundException {
253         if (path == null) {
254             isValid = false;
255             final String msg = String.format("Invalid '%s' argument: null", argumentName);
256             throw new FileNotFoundException(msg);
257         } else if (!path.contains("*") && !path.contains("?")) {
258             File f = new File(path);
259             final String[] formats = this.getReportFormat();
260             if ("o".equalsIgnoreCase(argumentName.substring(0, 1)) && formats.length == 1 && !"ALL".equalsIgnoreCase(formats[0])) {
261                 final String checkPath = path.toLowerCase();
262                 if (checkPath.endsWith(".html") || checkPath.endsWith(".xml") || checkPath.endsWith(".htm")
263                         || checkPath.endsWith(".csv") || checkPath.endsWith(".json")) {
264                     if (f.getParentFile() == null) {
265                         f = new File(".", path);
266                     }
267                     if (!f.getParentFile().isDirectory()) {
268                         isValid = false;
269                         final String msg = String.format("Invalid '%s' argument: '%s' - directory path does not exist", argumentName, path);
270                         throw new FileNotFoundException(msg);
271                     }
272                 }
273             } else if ("o".equalsIgnoreCase(argumentName.substring(0, 1)) && !f.isDirectory()) {
274                 if (f.getParentFile() != null && f.getParentFile().isDirectory() && !f.mkdir()) {
275                     isValid = false;
276                     final String msg = String.format("Invalid '%s' argument: '%s' - unable to create the output directory", argumentName, path);
277                     throw new FileNotFoundException(msg);
278                 }
279                 if (!f.isDirectory()) {
280                     isValid = false;
281                     final String msg = String.format("Invalid '%s' argument: '%s' - path does not exist", argumentName, path);
282                     throw new FileNotFoundException(msg);
283                 }
284             } else if (!f.exists()) {
285                 isValid = false;
286                 final String msg = String.format("Invalid '%s' argument: '%s' - path does not exist", argumentName, path);
287                 throw new FileNotFoundException(msg);
288             }
289 //        } else if (path.startsWith("//") || path.startsWith("\\\\")) {
290 //            isValid = false;
291 //            final String msg = String.format("Invalid '%s' argument: '%s'%nUnable to scan paths that start with '//'.", argumentName, path);
292 //            throw new FileNotFoundException(msg);
293         } else if ((path.endsWith("/*") && !path.endsWith("**/*")) || (path.endsWith("\\*") && path.endsWith("**\\*"))) {
294             LOGGER.warn("Possibly incorrect path '{}' from argument '{}' because it ends with a slash star; "
295                     + "dependency-check uses ant-style paths", path, argumentName);
296         }
297     }
298 
299     /**
300      * Generates an Options collection that is used to parse the command line
301      * and to display the help message.
302      *
303      * @return the command line options used for parsing the command line
304      */
305     @SuppressWarnings("static-access")
306     private Options createCommandLineOptions() {
307         final Options options = new Options();
308         addStandardOptions(options);
309         addAdvancedOptions(options);
310         addDeprecatedOptions(options);
311         return options;
312     }
313 
314     /**
315      * Adds the standard command line options to the given options collection.
316      *
317      * @param options a collection of command line arguments
318      */
319     @SuppressWarnings("static-access")
320     private void addStandardOptions(final Options options) {
321         //This is an option group because it can be specified more then once.
322 
323         options.addOptionGroup(newOptionGroup(newOptionWithArg(ARGUMENT.SCAN_SHORT, ARGUMENT.SCAN, "path",
324                         "The path to scan - this option can be specified multiple times. Ant style paths are supported (e.g. 'path/**/*.jar'); "
325                                 + "if using Ant style paths it is highly recommended to quote the argument value.")))
326                 .addOptionGroup(newOptionGroup(newOptionWithArg(ARGUMENT.EXCLUDE, "pattern", "Specify an exclusion pattern. This option "
327                         + "can be specified multiple times and it accepts Ant style exclusions.")))
328                 .addOption(newOptionWithArg(ARGUMENT.PROJECT, "name", "The name of the project being scanned."))
329                 .addOption(newOptionWithArg(ARGUMENT.OUT_SHORT, ARGUMENT.OUT, "path",
330                         "The folder to write reports to. This defaults to the current directory. It is possible to set this to a specific "
331                                 + "file name if the format argument is not set to ALL."))
332                 .addOption(newOptionWithArg(ARGUMENT.OUTPUT_FORMAT_SHORT, ARGUMENT.OUTPUT_FORMAT, "format",
333                         "The report format (" + SUPPORTED_FORMATS + "). The default is HTML. Multiple format parameters can be specified."))
334                 .addOption(newOption(ARGUMENT.PRETTY_PRINT, "When specified the JSON and XML report formats will be pretty printed."))
335                 .addOption(newOption(ARGUMENT.VERSION_SHORT, ARGUMENT.VERSION, "Print the version information."))
336                 .addOption(newOption(ARGUMENT.HELP_SHORT, ARGUMENT.HELP, "Print this message."))
337                 .addOption(newOption(ARGUMENT.ADVANCED_HELP, "Print the advanced help message."))
338                 .addOption(newOption(ARGUMENT.DISABLE_AUTO_UPDATE_SHORT, ARGUMENT.DISABLE_AUTO_UPDATE,
339                         "Disables the automatic updating of the NVD-CVE, hosted-suppressions and RetireJS data."))
340                 .addOption(newOptionWithArg(ARGUMENT.VERBOSE_LOG_SHORT, ARGUMENT.VERBOSE_LOG, "file",
341                         "The file path to write verbose logging information."))
342                 .addOptionGroup(newOptionGroup(newOptionWithArg(ARGUMENT.SUPPRESSION_FILES, "file",
343                         "The file path to the suppression XML file. This can be specified more then once to utilize multiple suppression files")))
344                 .addOption(newOption(ARGUMENT.DISABLE_VERSION_CHECK, "Disables the dependency-check version check"))
345                 .addOption(newOption(ARGUMENT.EXPERIMENTAL, "Enables the experimental analyzers."))
346                 .addOption(newOptionWithArg(ARGUMENT.NVD_API_KEY, "apiKey", "The API Key to access the NVD API."))
347                 .addOption(newOptionWithArg(ARGUMENT.FAIL_ON_CVSS, "score",
348                         "Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11; "
349                                 + "since the CVSS scores are 0-10, by default the build will never fail."))
350                 .addOption(newOptionWithArg(ARGUMENT.FAIL_JUNIT_ON_CVSS, "score",
351                         "Specifies the CVSS score that is considered a failure when generating the junit report. The default is 0."));
352     }
353 
354     /**
355      * Adds the advanced command line options to the given options collection.
356      * These are split out for purposes of being able to display two different
357      * help messages.
358      *
359      * @param options a collection of command line arguments
360      */
361     @SuppressWarnings("static-access")
362     private void addAdvancedOptions(final Options options) {
363         options
364                 .addOption(newOption(ARGUMENT.UPDATE_ONLY,
365                         "Only update the local NVD data cache; no scan will be executed."))
366                 .addOption(newOptionWithArg(ARGUMENT.NVD_API_DELAY, "milliseconds",
367                         "Time in milliseconds to wait between downloading from the NVD."))
368                 .addOption(newOptionWithArg(ARGUMENT.NVD_API_RESULTS_PER_PAGE, "count",
369                         "The number records for a single page from NVD API (must be <=2000)."))
370                 .addOption(newOptionWithArg(ARGUMENT.NVD_API_ENDPOINT, "endpoint",
371                         "The NVD API Endpoint - setting this is rare."))
372                 .addOption(newOptionWithArg(ARGUMENT.NVD_API_DATAFEED_URL, "url",
373                         "The URL to the NVD API Datafeed."))
374                 .addOption(newOptionWithArg(ARGUMENT.NVD_API_DATAFEED_USER, "user",
375                         "Credentials for basic authentication to the NVD API Datafeed."))
376                 .addOption(newOptionWithArg(ARGUMENT.NVD_API_DATAFEED_PASSWORD, "password",
377                         "Credentials for basic authentication to the NVD API Datafeed."))
378                 .addOption(newOptionWithArg(ARGUMENT.NVD_API_DATAFEED_BEARER_TOKEN, "token",
379                         "Credentials for bearer authentication to the NVD API Datafeed."))
380                 .addOption(newOptionWithArg(ARGUMENT.SUPPRESSION_FILE_USER, "user",
381                         "Credentials for basic authentication to web-hosted suppression files."))
382                 .addOption(newOptionWithArg(ARGUMENT.SUPPRESSION_FILE_PASSWORD, "password",
383                         "Credentials for basic authentication to web-hosted suppression files."))
384                 .addOption(newOptionWithArg(ARGUMENT.SUPPRESSION_FILE_BEARER_TOKEN, "token",
385                         "Credentials for bearer authentication to web-hosted suppression files."))
386                 .addOption(newOptionWithArg(ARGUMENT.NVD_API_MAX_RETRY_COUNT, "count",
387                         "The maximum number of retry requests for a single call to the NVD API."))
388                 .addOption(newOptionWithArg(ARGUMENT.NVD_API_VALID_FOR_HOURS, "hours",
389                         "The number of hours to wait before checking for new updates from the NVD."))
390                 .addOption(newOptionWithArg(ARGUMENT.PROXY_PORT, "port",
391                         "The proxy port to use when downloading resources."))
392                 .addOption(newOptionWithArg(ARGUMENT.PROXY_SERVER, "server",
393                         "The proxy server to use when downloading resources."))
394                 .addOption(newOptionWithArg(ARGUMENT.PROXY_USERNAME, "user",
395                         "The proxy username to use when downloading resources."))
396                 .addOption(newOptionWithArg(ARGUMENT.PROXY_PASSWORD, "pass",
397                         "The proxy password to use when downloading resources."))
398                 .addOption(newOptionWithArg(ARGUMENT.NON_PROXY_HOSTS, "list",
399                         "The proxy exclusion list: hostnames (or patterns) for which proxy should not be used. "
400                                 + "Use pipe, comma or colon as list separator."))
401                 .addOption(newOptionWithArg(ARGUMENT.CONNECTION_TIMEOUT_SHORT, ARGUMENT.CONNECTION_TIMEOUT, "timeout",
402                         "The connection timeout (in milliseconds) to use when downloading resources."))
403                 .addOption(newOptionWithArg(ARGUMENT.CONNECTION_READ_TIMEOUT, "timeout",
404                         "The read timeout (in milliseconds) to use when downloading resources."))
405                 .addOption(newOptionWithArg(ARGUMENT.CONNECTION_STRING, "connStr",
406                         "The connection string to the database."))
407                 .addOption(newOptionWithArg(ARGUMENT.DB_NAME, "user",
408                         "The username used to connect to the database."))
409                 .addOption(newOptionWithArg(ARGUMENT.DATA_DIRECTORY_SHORT, ARGUMENT.DATA_DIRECTORY, "path",
410                         "The location of the H2 Database file. This option should generally not be set."))
411                 .addOption(newOptionWithArg(ARGUMENT.DB_PASSWORD, "password",
412                         "The password for connecting to the database."))
413                 .addOption(newOptionWithArg(ARGUMENT.DB_DRIVER, "driver",
414                         "The database driver name."))
415                 .addOption(newOptionWithArg(ARGUMENT.DB_DRIVER_PATH, "path",
416                         "The path to the database driver; note, this does not need to be set unless the JAR is "
417                                 + "outside of the classpath."))
418                 .addOption(newOptionWithArg(ARGUMENT.SYM_LINK_DEPTH, "depth",
419                         "Sets how deep nested symbolic links will be followed; 0 indicates symbolic links will not be followed."))
420                 .addOption(newOptionWithArg(ARGUMENT.PATH_TO_BUNDLE_AUDIT, "path",
421                         "The path to bundle-audit for Gem bundle analysis."))
422                 .addOption(newOptionWithArg(ARGUMENT.PATH_TO_BUNDLE_AUDIT_WORKING_DIRECTORY, "path",
423                         "The path to working directory that the bundle-audit command should be executed from when "
424                                 + "doing Gem bundle analysis."))
425                 .addOption(newOptionWithArg(ARGUMENT.CENTRAL_URL, "url",
426                         "Alternative URL for Maven Central Search. If not set the public Sonatype Maven Central will be used."))
427                 .addOption(newOptionWithArg(ARGUMENT.CENTRAL_USERNAME, "username",
428                         "Credentials for basic auth towards the --centralUrl."))
429                 .addOption(newOptionWithArg(ARGUMENT.CENTRAL_PASSWORD, "password",
430                         "Credentials for basic auth towards the --centralUrl"))
431                 .addOption(newOptionWithArg(ARGUMENT.CENTRAL_BEARER_TOKEN, "token",
432                         "Token for bearer auth towards the --centralUrl"))
433                 .addOption(newOptionWithArg(ARGUMENT.OSSINDEX_URL, "url",
434                         "Alternative URL for the OSS Index. If not set the public Sonatype OSS Index will be used."))
435                 .addOption(newOptionWithArg(ARGUMENT.OSSINDEX_USERNAME, "username",
436                         "The username to authenticate to Sonatype's OSS Index. If not set the Sonatype OSS Index "
437                                 + "Analyzer will use an unauthenticated connection."))
438                 .addOption(newOptionWithArg(ARGUMENT.OSSINDEX_PASSWORD, "password", ""
439                         + "The password to authenticate to Sonatype's OSS Index. If not set the Sonatype OSS "
440                         + "Index Analyzer will use an unauthenticated connection."))
441                 .addOption(newOptionWithArg(ARGUMENT.OSSINDEX_WARN_ONLY_ON_REMOTE_ERRORS, "true/false", ""
442                         + "Whether a Sonatype OSS Index remote error should result in a warning only or a failure."))
443                 .addOption(newOption(ARGUMENT.RETIRE_JS_FORCEUPDATE, "Force the RetireJS Analyzer to update "
444                         + "even if autoupdate is disabled"))
445                 .addOption(newOptionWithArg(ARGUMENT.RETIREJS_URL, "url",
446                         "The Retire JS Repository URL"))
447                 .addOption(newOptionWithArg(ARGUMENT.RETIREJS_URL_USER, "username",
448                         "The password to authenticate to Retire JS Repository URL"))
449                 .addOption(newOptionWithArg(ARGUMENT.RETIREJS_URL_PASSWORD, "password",
450                         "The password to authenticate to Retire JS Repository URL"))
451                 .addOption(newOptionWithArg(ARGUMENT.RETIREJS_URL_BEARER_TOKEN, "token",
452                         "The password to authenticate to Retire JS Repository URL"))
453                 .addOption(newOption(ARGUMENT.RETIRE_JS_FILTER_NON_VULNERABLE, "Specifies that the Retire JS "
454                         + "Analyzer should filter out non-vulnerable JS files from the report."))
455                 .addOption(newOptionWithArg(ARGUMENT.ARTIFACTORY_PARALLEL_ANALYSIS, "true/false",
456                         "Whether the Artifactory Analyzer should use parallel analysis."))
457                 .addOption(newOptionWithArg(ARGUMENT.ARTIFACTORY_USES_PROXY, "true/false",
458                         "Whether the Artifactory Analyzer should use the proxy."))
459                 .addOption(newOptionWithArg(ARGUMENT.ARTIFACTORY_USERNAME, "username",
460                         "The Artifactory username for authentication."))
461                 .addOption(newOptionWithArg(ARGUMENT.ARTIFACTORY_API_TOKEN, "token",
462                         "The Artifactory API token."))
463                 .addOption(newOptionWithArg(ARGUMENT.ARTIFACTORY_BEARER_TOKEN, "token",
464                         "The Artifactory bearer token."))
465                 .addOption(newOptionWithArg(ARGUMENT.ARTIFACTORY_URL, "url",
466                         "The Artifactory URL."))
467                 .addOption(newOptionWithArg(ARGUMENT.PATH_TO_GO, "path",
468                         "The path to the `go` executable."))
469                 .addOption(newOptionWithArg(ARGUMENT.PATH_TO_YARN, "path",
470                         "The path to the `yarn` executable."))
471                 .addOption(newOptionWithArg(ARGUMENT.PATH_TO_PNPM, "path",
472                         "The path to the `pnpm` executable."))
473                 .addOption(newOptionWithArg(ARGUMENT.RETIRE_JS_FILTERS, "pattern",
474                         "Specify Retire JS content filter used to exclude files from analysis based on their content; "
475                                 + "most commonly used to exclude based on your applications own copyright line. This "
476                                 + "option can be specified multiple times."))
477                 .addOption(newOptionWithArg(ARGUMENT.NEXUS_URL, "url",
478                         "The url to the Nexus Server's REST API Endpoint (http://domain/nexus/service/local). If not "
479                                 + "set the Nexus Analyzer will be disabled."))
480                 .addOption(newOptionWithArg(ARGUMENT.NEXUS_USERNAME, "username",
481                         "The username to authenticate to the Nexus Server's REST API Endpoint. If not set the Nexus "
482                                 + "Analyzer will use an unauthenticated connection."))
483                 .addOption(newOptionWithArg(ARGUMENT.NEXUS_PASSWORD, "password",
484                         "The password to authenticate to the Nexus Server's REST API Endpoint. If not set the Nexus "
485                                 + "Analyzer will use an unauthenticated connection."))
486                 //TODO remove as this should be covered by non-proxy hosts
487                 .addOption(newOptionWithArg(ARGUMENT.NEXUS_USES_PROXY, "true/false",
488                         "Whether or not the configured proxy should be used when connecting to Nexus."))
489                 .addOption(newOptionWithArg(ARGUMENT.ADDITIONAL_ZIP_EXTENSIONS, "extensions",
490                         "A comma separated list of additional extensions to be scanned as ZIP files (ZIP, EAR, WAR "
491                                 + "are already treated as zip files)"))
492                 .addOption(newOptionWithArg(ARGUMENT.PROP_SHORT, ARGUMENT.PROP, "file", "A property file to load."))
493                 .addOption(newOptionWithArg(ARGUMENT.PATH_TO_CORE, "path", "The path to dotnet core."))
494                 .addOption(newOptionWithArg(ARGUMENT.HINTS_FILE, "file", "The file path to the hints XML file."))
495                 .addOption(newOption(ARGUMENT.RETIRED, "Enables the retired analyzers."))
496                 .addOption(newOption(ARGUMENT.DISABLE_MSBUILD, "Disable the MS Build Analyzer."))
497                 .addOption(newOption(ARGUMENT.DISABLE_JAR, "Disable the Jar Analyzer."))
498                 .addOption(newOption(ARGUMENT.DISABLE_ARCHIVE, "Disable the Archive Analyzer."))
499                 .addOption(newOption(ARGUMENT.DISABLE_KEV, "Disable the Known Exploited Vulnerability Analyzer."))
500                 .addOption(newOptionWithArg(ARGUMENT.KEV_URL, "url", "The url to the CISA Known Exploited Vulnerabilities JSON data feed"))
501                 .addOption(newOptionWithArg(ARGUMENT.KEV_USER, "user", "The user for basic authentication towards the CISA Known Exploited "
502                         + "Vulnerabilities JSON data feed"))
503                 .addOption(newOptionWithArg(ARGUMENT.KEV_PASSWORD, "password", "The password for basic authentication towards the CISA Known "
504                         + "Exploited Vulnerabilities JSON data feed"))
505                 .addOption(newOptionWithArg(ARGUMENT.KEV_BEARER_TOKEN, "token", "The token for bearer authentication towards the CISA Known "
506                         + "Exploited Vulnerabilities JSON data feed"))
507                 .addOption(newOption(ARGUMENT.DISABLE_ASSEMBLY, "Disable the .NET Assembly Analyzer."))
508                 .addOption(newOption(ARGUMENT.DISABLE_PY_DIST, "Disable the Python Distribution Analyzer."))
509                 .addOption(newOption(ARGUMENT.DISABLE_CMAKE, "Disable the Cmake Analyzer."))
510                 .addOption(newOption(ARGUMENT.DISABLE_PY_PKG, "Disable the Python Package Analyzer."))
511                 .addOption(newOption(ARGUMENT.DISABLE_MIX_AUDIT, "Disable the Elixir mix_audit Analyzer."))
512                 .addOption(newOption(ARGUMENT.DISABLE_RUBYGEMS, "Disable the Ruby Gemspec Analyzer."))
513                 .addOption(newOption(ARGUMENT.DISABLE_BUNDLE_AUDIT, "Disable the Ruby Bundler-Audit Analyzer."))
514                 .addOption(newOption(ARGUMENT.DISABLE_FILENAME, "Disable the File Name Analyzer."))
515                 .addOption(newOption(ARGUMENT.DISABLE_AUTOCONF, "Disable the Autoconf Analyzer."))
516                 .addOption(newOption(ARGUMENT.DISABLE_MAVEN_INSTALL, "Disable the Maven install Analyzer."))
517                 .addOption(newOption(ARGUMENT.DISABLE_PE, "Disable the PE Analyzer."))
518                 .addOption(newOption(ARGUMENT.DISABLE_PIP, "Disable the pip Analyzer."))
519                 .addOption(newOption(ARGUMENT.DISABLE_PIPFILE, "Disable the Pipfile Analyzer."))
520                 .addOption(newOption(ARGUMENT.DISABLE_COMPOSER, "Disable the PHP Composer Analyzer."))
521                 .addOption(newOption(ARGUMENT.COMPOSER_LOCK_SKIP_DEV, "Configures the PHP Composer Analyzer to skip packages-dev"))
522                 .addOption(newOption(ARGUMENT.DISABLE_CPAN, "Disable the Perl CPAN file Analyzer."))
523                 .addOption(newOption(ARGUMENT.DISABLE_POETRY, "Disable the Poetry Analyzer."))
524                 .addOption(newOption(ARGUMENT.DISABLE_GOLANG_MOD, "Disable the Golang Mod Analyzer."))
525                 .addOption(newOption(ARGUMENT.DISABLE_DART, "Disable the Dart Analyzer."))
526                 .addOption(newOption(ARGUMENT.DISABLE_OPENSSL, "Disable the OpenSSL Analyzer."))
527                 .addOption(newOption(ARGUMENT.DISABLE_NUSPEC, "Disable the Nuspec Analyzer."))
528                 .addOption(newOption(ARGUMENT.DISABLE_NUGETCONF, "Disable the Nuget packages.config Analyzer."))
529                 .addOption(newOption(ARGUMENT.DISABLE_CENTRAL, "Disable the Central Analyzer. If this analyzer "
530                         + "is disabled it is likely you also want to disable the Nexus Analyzer."))
531                 .addOption(newOption(ARGUMENT.DISABLE_CENTRAL_CACHE, "Disallow the Central Analyzer from caching results"))
532                 .addOption(newOption(ARGUMENT.DISABLE_OSSINDEX, "Disable the Sonatype OSS Index Analyzer."))
533                 .addOption(newOption(ARGUMENT.DISABLE_OSSINDEX_CACHE, "Disallow the OSS Index Analyzer from caching results"))
534                 .addOption(newOption(ARGUMENT.DISABLE_COCOAPODS, "Disable the CocoaPods Analyzer."))
535                 .addOption(newOption(ARGUMENT.DISABLE_CARTHAGE, "Disable the Carthage Analyzer."))
536                 .addOption(newOption(ARGUMENT.DISABLE_SWIFT, "Disable the swift package Analyzer."))
537                 .addOption(newOption(ARGUMENT.DISABLE_SWIFT_RESOLVED, "Disable the swift package resolved Analyzer."))
538                 .addOption(newOption(ARGUMENT.DISABLE_GO_DEP, "Disable the Golang Package Analyzer."))
539                 .addOption(newOption(ARGUMENT.DISABLE_NODE_JS, "Disable the Node.js Package Analyzer."))
540                 .addOption(newOption(ARGUMENT.NODE_PACKAGE_SKIP_DEV_DEPENDENCIES, "Configures the Node Package Analyzer to skip devDependencies"))
541                 .addOption(newOption(ARGUMENT.DISABLE_NODE_AUDIT, "Disable the Node Audit Analyzer."))
542                 .addOption(newOption(ARGUMENT.DISABLE_PNPM_AUDIT, "Disable the Pnpm Audit Analyzer."))
543                 .addOption(newOption(ARGUMENT.DISABLE_YARN_AUDIT, "Disable the Yarn Audit Analyzer."))
544                 .addOption(newOption(ARGUMENT.DISABLE_NODE_AUDIT_CACHE, "Disallow the Node Audit Analyzer from caching results"))
545                 .addOption(newOption(ARGUMENT.DISABLE_NODE_AUDIT_SKIPDEV, "Configures the Node Audit Analyzer to skip devDependencies"))
546                 .addOption(newOption(ARGUMENT.DISABLE_RETIRE_JS, "Disable the RetireJS Analyzer."))
547                 .addOption(newOption(ARGUMENT.ENABLE_NEXUS, "Enable the Nexus Analyzer."))
548                 .addOption(newOption(ARGUMENT.ARTIFACTORY_ENABLED, "Whether the Artifactory Analyzer should be enabled."))
549                 .addOption(newOption(ARGUMENT.PURGE_NVD, "Purges the local NVD data cache"))
550                 .addOption(newOption(ARGUMENT.DISABLE_HOSTED_SUPPRESSIONS, "Disable the usage of the hosted suppressions file"))
551                 .addOption(newOption(ARGUMENT.HOSTED_SUPPRESSIONS_FORCEUPDATE, "Force the hosted suppressions file to update even"
552                         + " if autoupdate is disabled"))
553                 .addOption(newOptionWithArg(ARGUMENT.HOSTED_SUPPRESSIONS_VALID_FOR_HOURS, "hours",
554                         "The number of hours to wait before checking for new updates of the the hosted suppressions file."))
555                 .addOption(newOptionWithArg(ARGUMENT.HOSTED_SUPPRESSIONS_URL, "url",
556                         "The URL for a mirrored hosted suppressions file"))
557                 .addOption(newOptionWithArg(ARGUMENT.HOSTED_SUPPRESSIONS_USER, "user",
558                         "The user for basic auth to a mirrored hosted suppressions file"))
559                 .addOption(newOptionWithArg(ARGUMENT.HOSTED_SUPPRESSIONS_PASSWORD, "password",
560                         "The password for basic auth to a mirrored hosted suppressions file"))
561                 .addOption(newOptionWithArg(ARGUMENT.HOSTED_SUPPRESSIONS_BEARER_TOKEN, "token",
562                         "The token for bearer auth to  a mirrored hosted suppressions file"));
563 
564     }
565 
566     /**
567      * Adds the deprecated command line options to the given options collection.
568      * These are split out for purposes of not including them in the help
569      * message. We need to add the deprecated options so as not to break
570      * existing scripts.
571      *
572      * @param options a collection of command line arguments
573      */
574     @SuppressWarnings({"static-access", "deprecation"})
575     private void addDeprecatedOptions(final Options options) {
576         //not a real option - but enables java debugging via the shell script
577         options.addOption(newOption("debug",
578                 "Used to enable java debugging of the cli via dependency-check.sh."));
579         options.addOption(newOption(ARGUMENT.DISABLE_RETIREJS_DEPRECATED, "Disable the RetireJS Analyzer."));
580         options.addOption(newOption(ARGUMENT.RETIREJS_FILTER_NON_VULNERABLE_DEPRECATED, "Specifies that the Retire JS "
581                 + "Analyzer should filter out non-vulnerable JS files from the report."));
582         options.addOption(newOptionWithArg(ARGUMENT.RETIREJS_FILTERS_DEPRECATED, "pattern",
583                 "Specify Retire JS content filter used to exclude files from analysis based on their content; "
584                         + "most commonly used to exclude based on your applications own copyright line. This "
585                         + "option can be specified multiple times."));
586     }
587 
588     /**
589      * Determines if the 'version' command line argument was passed in.
590      *
591      * @return whether or not the 'version' command line argument was passed in
592      */
593     public boolean isGetVersion() {
594         return (line != null) && line.hasOption(ARGUMENT.VERSION);
595     }
596 
597     /**
598      * Determines if the 'help' command line argument was passed in.
599      *
600      * @return whether or not the 'help' command line argument was passed in
601      */
602     public boolean isGetHelp() {
603         return (line != null) && line.hasOption(ARGUMENT.HELP);
604     }
605 
606     /**
607      * Determines if the 'scan' command line argument was passed in.
608      *
609      * @return whether or not the 'scan' command line argument was passed in
610      */
611     public boolean isRunScan() {
612         return (line != null) && isValid && line.hasOption(ARGUMENT.SCAN);
613     }
614 
615     /**
616      * Returns the symbolic link depth (how deeply symbolic links will be
617      * followed).
618      *
619      * @return the symbolic link depth
620      */
621     public int getSymLinkDepth() {
622         int value = 0;
623         try {
624             value = Integer.parseInt(line.getOptionValue(ARGUMENT.SYM_LINK_DEPTH, "0"));
625             if (value < 0) {
626                 value = 0;
627             }
628         } catch (NumberFormatException ex) {
629             LOGGER.debug("Symbolic link was not a number");
630         }
631         return value;
632     }
633 
634     /**
635      * Utility method to determine if one of the disable options has been set.
636      * If not set, this method will check the currently configured settings for
637      * the current value to return.
638      * <p>
639      * Example given `--disableArchive` on the command line would cause this
640      * method to return true for the disable archive setting.
641      *
642      * @param disableFlag the command line disable option
643      * @param setting the corresponding settings key
644      * @return true if the disable option was set, if not set the currently
645      * configured value will be returned
646      */
647     public boolean isDisabled(String disableFlag, String setting) {
648         if (line == null || !line.hasOption(disableFlag)) {
649             try {
650                 return !settings.getBoolean(setting);
651             } catch (InvalidSettingException ise) {
652                 LOGGER.warn("Invalid property setting '{}' defaulting to false", setting);
653                 return false;
654             }
655         } else {
656             return true;
657         }
658     }
659 
660     /**
661      * Returns true if the disableNodeAudit command line argument was specified.
662      *
663      * @return true if the disableNodeAudit command line argument was specified;
664      * otherwise false
665      */
666     public boolean isNodeAuditDisabled() {
667         return isDisabled(ARGUMENT.DISABLE_NODE_AUDIT, Settings.KEYS.ANALYZER_NODE_AUDIT_ENABLED);
668     }
669 
670     /**
671      * Returns true if the disableYarnAudit command line argument was specified.
672      *
673      * @return true if the disableYarnAudit command line argument was specified;
674      * otherwise false
675      */
676     public boolean isYarnAuditDisabled() {
677         return isDisabled(ARGUMENT.DISABLE_YARN_AUDIT, Settings.KEYS.ANALYZER_YARN_AUDIT_ENABLED);
678     }
679 
680     /**
681      * Returns true if the disablePnpmAudit command line argument was specified.
682      *
683      * @return true if the disablePnpmAudit command line argument was specified;
684      * otherwise false
685      */
686     public boolean isPnpmAuditDisabled() {
687         return isDisabled(ARGUMENT.DISABLE_PNPM_AUDIT, Settings.KEYS.ANALYZER_PNPM_AUDIT_ENABLED);
688     }
689 
690     /**
691      * Returns true if the Nexus Analyzer should use the configured proxy to
692      * connect to Nexus; otherwise false is returned.
693      *
694      * @return true if the Nexus Analyzer should use the configured proxy to
695      * connect to Nexus; otherwise false
696      */
697     public boolean isNexusUsesProxy() {
698         // If they didn't specify whether Nexus needs to use the proxy, we should
699         // still honor the property if it's set.
700         if (line == null || !line.hasOption(ARGUMENT.NEXUS_USES_PROXY)) {
701             try {
702                 return settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY);
703             } catch (InvalidSettingException ise) {
704                 return true;
705             }
706         } else {
707             return Boolean.parseBoolean(line.getOptionValue(ARGUMENT.NEXUS_USES_PROXY));
708         }
709     }
710 
711     /**
712      * Returns the argument boolean value.
713      *
714      * @param argument the argument
715      * @return the argument boolean value
716      */
717     @SuppressFBWarnings(justification = "Accepting that this is a bad practice - used a Boolean as we needed three states",
718             value = {"NP_BOOLEAN_RETURN_NULL"})
719     public Boolean getBooleanArgument(String argument) {
720         if (line != null && line.hasOption(argument)) {
721             final String value = line.getOptionValue(argument);
722             if (value != null) {
723                 return Boolean.parseBoolean(value);
724             }
725         }
726         return null;
727     }
728 
729     /**
730      * Returns the argument value for the given option.
731      *
732      * @param option the option
733      * @return the value of the argument
734      */
735     public String getStringArgument(String option) {
736         return getStringArgument(option, null);
737     }
738 
739     /**
740      * Returns the argument value for the given option.
741      *
742      * @param option the option
743      * @param key the dependency-check settings key for the option.
744      * @return the value of the argument
745      */
746     public String getStringArgument(String option, String key) {
747         if (line != null && line.hasOption(option)) {
748             if (key != null && (option.toLowerCase().endsWith("password")
749                     || option.toLowerCase().endsWith("pass"))) {
750                 LOGGER.warn("{} used on the command line, consider moving the password "
751                         + "to a properties file using the key `{}` and using the "
752                         + "--propertyfile argument instead", option, key);
753             }
754             return line.getOptionValue(option);
755         }
756         return null;
757     }
758 
759     /**
760      * Returns the argument value for the given option.
761      *
762      * @param option the option
763      * @return the value of the argument
764      */
765     public String[] getStringArguments(String option) {
766         if (line != null && line.hasOption(option)) {
767             return line.getOptionValues(option);
768         }
769         return null;
770     }
771 
772     /**
773      * Returns the argument value for the given option.
774      *
775      * @param option the option
776      * @return the value of the argument
777      */
778     public File getFileArgument(String option) {
779         final String path = line.getOptionValue(option);
780         if (path != null) {
781             return new File(path);
782         }
783         return null;
784     }
785 
786     /**
787      * Displays the command line help message to the standard output.
788      */
789     public void printHelp() {
790         final HelpFormatter formatter = new HelpFormatter();
791         final Options options = new Options();
792         addStandardOptions(options);
793         if (line != null && line.hasOption(ARGUMENT.ADVANCED_HELP)) {
794             addAdvancedOptions(options);
795         }
796         final String helpMsg = String.format("%n%s"
797                         + " can be used to identify if there are any known CVE vulnerabilities in libraries utilized by an application. "
798                         + "%s will automatically update required data from the Internet, such as the CVE and CPE data files from nvd.nist.gov.%n%n",
799                 settings.getString(Settings.KEYS.APPLICATION_NAME, "DependencyCheck"),
800                 settings.getString(Settings.KEYS.APPLICATION_NAME, "DependencyCheck"));
801 
802         formatter.printHelp(settings.getString(Settings.KEYS.APPLICATION_NAME, "DependencyCheck"),
803                 helpMsg,
804                 options,
805                 "",
806                 true);
807     }
808 
809     /**
810      * Retrieves the file command line parameter(s) specified for the 'scan'
811      * argument.
812      *
813      * @return the file paths specified on the command line for scan
814      */
815     public String[] getScanFiles() {
816         return line.getOptionValues(ARGUMENT.SCAN);
817     }
818 
819     /**
820      * Retrieves the list of excluded file patterns specified by the 'exclude'
821      * argument.
822      *
823      * @return the excluded file patterns
824      */
825     public String[] getExcludeList() {
826         return line.getOptionValues(ARGUMENT.EXCLUDE);
827     }
828 
829     /**
830      * Retrieves the list of retire JS content filters used to exclude JS files
831      * by content.
832      *
833      * @return the retireJS filters
834      */
835     public String[] getRetireJsFilters() {
836         final String[] values = line.getOptionValues(ARGUMENT.RETIRE_JS_FILTERS);
837         return values != null ? values : line.getOptionValues(ARGUMENT.RETIREJS_FILTERS_DEPRECATED);
838     }
839 
840     /**
841      * Returns whether or not the retireJS analyzer should exclude
842      * non-vulnerable JS from the report.
843      *
844      * @return <code>true</code> if non-vulnerable JS should be filtered in the
845      * RetireJS Analyzer; otherwise <code>null</code>
846      */
847     @SuppressFBWarnings(justification = "Accepting that this is a bad practice - but made more sense in this use case",
848             value = {"NP_BOOLEAN_RETURN_NULL"})
849     public Boolean isRetireJsFilterNonVulnerable() {
850         return (line != null && (line.hasOption(ARGUMENT.RETIRE_JS_FILTER_NON_VULNERABLE)
851                 || line.hasOption(ARGUMENT.RETIREJS_FILTER_NON_VULNERABLE_DEPRECATED))) ? true : null;
852     }
853 
854     /**
855      * Returns the directory to write the reports to specified on the command
856      * line.
857      *
858      * @return the path to the reports directory.
859      */
860     public String getReportDirectory() {
861         return line.getOptionValue(ARGUMENT.OUT, ".");
862     }
863 
864     /**
865      * Returns the output format specified on the command line. Defaults to HTML
866      * if no format was specified.
867      *
868      * @return the output format name.
869      */
870     public String[] getReportFormat() {
871         if (line.hasOption(ARGUMENT.OUTPUT_FORMAT)) {
872             return line.getOptionValues(ARGUMENT.OUTPUT_FORMAT);
873         }
874         return new String[]{"HTML"};
875     }
876 
877     /**
878      * Returns the application name specified on the command line.
879      *
880      * @return the application name.
881      */
882     public String getProjectName() {
883         String name = line.getOptionValue(ARGUMENT.PROJECT);
884         if (name == null) {
885             name = "";
886         }
887         return name;
888     }
889 
890     /**
891      * <p>
892      * Prints the manifest information to standard output.</p>
893      * <ul><li>Implementation-Title: ${pom.name}</li>
894      * <li>Implementation-Version: ${pom.version}</li></ul>
895      */
896     public void printVersionInfo() {
897         final String version = String.format("%s version %s",
898                 settings.getString(Settings.KEYS.APPLICATION_NAME, "dependency-check"),
899                 settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown"));
900         System.out.println(version);
901     }
902 
903     /**
904      * Checks if the update only flag has been set.
905      *
906      * @return <code>true</code> if the update only flag has been set; otherwise
907      * <code>false</code>.
908      */
909     public boolean isUpdateOnly() {
910         return line != null && line.hasOption(ARGUMENT.UPDATE_ONLY);
911     }
912 
913     /**
914      * Checks if the purge NVD flag has been set.
915      *
916      * @return <code>true</code> if the purge nvd flag has been set; otherwise
917      * <code>false</code>.
918      */
919     public boolean isPurge() {
920         return line != null && line.hasOption(ARGUMENT.PURGE_NVD);
921     }
922 
923     /**
924      * Returns the database driver name if specified; otherwise null is
925      * returned.
926      *
927      * @return the database driver name if specified; otherwise null is returned
928      */
929     public String getDatabaseDriverName() {
930         return line.getOptionValue(ARGUMENT.DB_DRIVER);
931     }
932 
933     /**
934      * Returns the argument value.
935      *
936      * @param argument the argument
937      * @return the value of the argument
938      */
939     public Integer getIntegerValue(String argument) {
940         final String v = line.getOptionValue(argument);
941         if (v != null) {
942             return Integer.parseInt(v);
943         }
944         return null;
945     }
946 
947     /**
948      * Checks if the option is present. If present it will return
949      * <code>true</code>; otherwise <code>false</code>.
950      *
951      * @param option the option to check
952      * @return <code>true</code> if auto-update is allowed; otherwise
953      * <code>null</code>
954      */
955     @SuppressFBWarnings(justification = "Accepting that this is a bad practice - but made more sense in this use case",
956             value = {"NP_BOOLEAN_RETURN_NULL"})
957     public Boolean hasOption(String option) {
958         return (line != null && line.hasOption(option)) ? true : null;
959     }
960 
961     /**
962      * Returns the CVSS value to fail on.
963      *
964      * @return 11 if nothing is set. Otherwise it returns the int passed from
965      * the command line arg
966      */
967     public float getFailOnCVSS() {
968         if (line.hasOption(ARGUMENT.FAIL_ON_CVSS)) {
969             final String value = line.getOptionValue(ARGUMENT.FAIL_ON_CVSS);
970             try {
971                 return Float.parseFloat(value);
972             } catch (NumberFormatException nfe) {
973                 return 11;
974             }
975         } else {
976             return 11;
977         }
978     }
979 
980     /**
981      * Returns the float argument for the given option.
982      *
983      * @param option the option
984      * @param defaultValue the value if the option is not present
985      * @return the value of the argument if present; otherwise the defaultValue
986      */
987     public float getFloatArgument(String option, float defaultValue) {
988         if (line.hasOption(option)) {
989             final String value = line.getOptionValue(option);
990             try {
991                 return Integer.parseInt(value);
992             } catch (NumberFormatException nfe) {
993                 return defaultValue;
994             }
995         } else {
996             return defaultValue;
997         }
998     }
999 
1000     /**
1001      * Builds a new option.
1002      *
1003      * @param name the long name
1004      * @param description the description
1005      * @return a new option
1006      */
1007     private Option newOption(String name, String description) {
1008         return Option.builder().longOpt(name).desc(description).build();
1009     }
1010 
1011     /**
1012      * Builds a new option.
1013      *
1014      * @param shortName the short name
1015      * @param name the long name
1016      * @param description the description
1017      * @return a new option
1018      */
1019     private Option newOption(String shortName, String name, String description) {
1020         return Option.builder(shortName).longOpt(name).desc(description).build();
1021     }
1022 
1023     /**
1024      * Builds a new option.
1025      *
1026      * @param name the long name
1027      * @param arg the argument name
1028      * @param description the description
1029      * @return a new option
1030      */
1031     private Option newOptionWithArg(String name, String arg, String description) {
1032         return Option.builder().longOpt(name).argName(arg).hasArg().desc(description).build();
1033     }
1034 
1035     /**
1036      * Builds a new option.
1037      *
1038      * @param shortName the short name
1039      * @param name the long name
1040      * @param arg the argument name
1041      * @param description the description
1042      * @return a new option
1043      */
1044     private Option newOptionWithArg(String shortName, String name, String arg, String description) {
1045         return Option.builder(shortName).longOpt(name).argName(arg).hasArg().desc(description).build();
1046     }
1047 
1048     /**
1049      * Builds a new option group so that an option can be specified multiple
1050      * times on the command line.
1051      *
1052      * @param option the option to add to the group
1053      * @return a new option group
1054      */
1055     private OptionGroup newOptionGroup(Option option) {
1056         final OptionGroup group = new OptionGroup();
1057         group.addOption(option);
1058         return group;
1059     }
1060 
1061     /**
1062      * A collection of static final strings that represent the possible command
1063      * line arguments.
1064      */
1065     public static class ARGUMENT {
1066 
1067         /**
1068          * The long CLI argument name specifying the directory/file to scan.
1069          */
1070         public static final String SCAN = "scan";
1071         /**
1072          * The short CLI argument name specifying the directory/file to scan.
1073          */
1074         public static final String SCAN_SHORT = "s";
1075         /**
1076          * The long CLI argument name specifying that the CPE/CVE/etc. data
1077          * should not be automatically updated.
1078          */
1079         public static final String DISABLE_AUTO_UPDATE = "noupdate";
1080         /**
1081          * The long CLI argument name specifying that the version check should
1082          * not be performed.
1083          */
1084         public static final String DISABLE_VERSION_CHECK = "disableVersionCheck";
1085         /**
1086          * The short CLI argument name specifying that the CPE/CVE/etc. data
1087          * should not be automatically updated.
1088          */
1089         public static final String DISABLE_AUTO_UPDATE_SHORT = "n";
1090         /**
1091          * The long CLI argument name specifying that only the update phase
1092          * should be executed; no scan should be run.
1093          */
1094         public static final String UPDATE_ONLY = "updateonly";
1095         /**
1096          * The long CLI argument name specifying that only the update phase
1097          * should be executed; no scan should be run.
1098          */
1099         public static final String PURGE_NVD = "purge";
1100         /**
1101          * The long CLI argument name specifying the directory to write the
1102          * reports to.
1103          */
1104         public static final String OUT = "out";
1105         /**
1106          * The short CLI argument name specifying the directory to write the
1107          * reports to.
1108          */
1109         public static final String OUT_SHORT = "o";
1110         /**
1111          * The long CLI argument name specifying the output format to write the
1112          * reports to.
1113          */
1114         public static final String OUTPUT_FORMAT = "format";
1115         /**
1116          * The short CLI argument name specifying the output format to write the
1117          * reports to.
1118          */
1119         public static final String OUTPUT_FORMAT_SHORT = "f";
1120         /**
1121          * The long CLI argument name specifying the name of the project to be
1122          * scanned.
1123          */
1124         public static final String PROJECT = "project";
1125         /**
1126          * The long CLI argument name asking for help.
1127          */
1128         public static final String HELP = "help";
1129         /**
1130          * The long CLI argument name asking for advanced help.
1131          */
1132         public static final String ADVANCED_HELP = "advancedHelp";
1133         /**
1134          * The short CLI argument name asking for help.
1135          */
1136         public static final String HELP_SHORT = "h";
1137         /**
1138          * The long CLI argument name asking for the version.
1139          */
1140         public static final String VERSION_SHORT = "v";
1141         /**
1142          * The short CLI argument name asking for the version.
1143          */
1144         public static final String VERSION = "version";
1145         /**
1146          * The CLI argument name indicating the proxy port.
1147          */
1148         public static final String PROXY_PORT = "proxyport";
1149         /**
1150          * The CLI argument name indicating the proxy server.
1151          */
1152         public static final String PROXY_SERVER = "proxyserver";
1153         /**
1154          * The CLI argument name indicating the proxy username.
1155          */
1156         public static final String PROXY_USERNAME = "proxyuser";
1157         /**
1158          * The CLI argument name indicating the proxy password.
1159          */
1160         public static final String PROXY_PASSWORD = "proxypass";
1161         /**
1162          * The CLI argument name indicating the proxy proxy exclusion list.
1163          */
1164         public static final String NON_PROXY_HOSTS = "nonProxyHosts";
1165         /**
1166          * The short CLI argument name indicating the connection timeout.
1167          */
1168         public static final String CONNECTION_TIMEOUT_SHORT = "c";
1169         /**
1170          * The CLI argument name indicating the connection timeout.
1171          */
1172         public static final String CONNECTION_TIMEOUT = "connectiontimeout";
1173         /**
1174          * The CLI argument name indicating the connection read timeout.
1175          */
1176         public static final String CONNECTION_READ_TIMEOUT = "readtimeout";
1177         /**
1178          * The short CLI argument name for setting the location of an additional
1179          * properties file.
1180          */
1181         public static final String PROP_SHORT = "P";
1182         /**
1183          * The CLI argument name for setting the location of an additional
1184          * properties file.
1185          */
1186         public static final String PROP = "propertyfile";
1187         /**
1188          * The CLI argument name for setting the location of the data directory.
1189          */
1190         public static final String DATA_DIRECTORY = "data";
1191         /**
1192          * The CLI argument name for setting the URL for the NVD API Endpoint.
1193          */
1194         public static final String NVD_API_ENDPOINT = "nvdApiEndpoint";
1195         /**
1196          * The CLI argument name for setting the URL for the NVD API Key.
1197          */
1198         public static final String NVD_API_KEY = "nvdApiKey";
1199         /**
1200          * The CLI argument name for setting the maximum number of retry
1201          * requests for a single call to the NVD API.
1202          */
1203         public static final String NVD_API_MAX_RETRY_COUNT = "nvdMaxRetryCount";
1204         /**
1205          * The CLI argument name for setting the number of hours to wait before
1206          * checking for new updates from the NVD.
1207          */
1208         public static final String NVD_API_VALID_FOR_HOURS = "nvdValidForHours";
1209         /**
1210          * The CLI argument name for the NVD API Data Feed URL.
1211          */
1212         public static final String NVD_API_DATAFEED_URL = "nvdDatafeed";
1213         /**
1214          * The username for basic auth to the CVE data.
1215          */
1216         public static final String NVD_API_DATAFEED_USER = "nvdUser";
1217         /**
1218          * The password for basic auth to the CVE data.
1219          */
1220         public static final String NVD_API_DATAFEED_PASSWORD = "nvdPassword";
1221         /**
1222          * The token for bearer auth to the CVE data.
1223          */
1224         public static final String NVD_API_DATAFEED_BEARER_TOKEN = "nvdBearerToken";
1225         /**
1226          * The username for basic auth to web-hosted suppression files.
1227          */
1228         public static final String SUPPRESSION_FILE_USER = "suppressionUser";
1229         /**
1230          * The passwored for basic auth to web-hosted suppression files.
1231          */
1232         public static final String SUPPRESSION_FILE_PASSWORD = "suppressionPassword";
1233         /**
1234          * The toke for bearer auth to web-hosted suppression files.
1235          */
1236         public static final String SUPPRESSION_FILE_BEARER_TOKEN = "suppressionBearerToken";
1237         /**
1238          * The time in milliseconds to wait between downloading NVD API data.
1239          */
1240         public static final String NVD_API_DELAY = "nvdApiDelay";
1241         /**
1242          * The number records for a single page from NVD API.
1243          */
1244         public static final String NVD_API_RESULTS_PER_PAGE = "nvdApiResultsPerPage";
1245         /**
1246          * The short CLI argument name for setting the location of the data
1247          * directory.
1248          */
1249         public static final String DATA_DIRECTORY_SHORT = "d";
1250         /**
1251          * The CLI argument name for setting the location of the data directory.
1252          */
1253         public static final String VERBOSE_LOG = "log";
1254         /**
1255          * The short CLI argument name for setting the location of the data
1256          * directory.
1257          */
1258         public static final String VERBOSE_LOG_SHORT = "l";
1259         /**
1260          * The CLI argument name for setting the depth of symbolic links that
1261          * will be followed.
1262          */
1263         public static final String SYM_LINK_DEPTH = "symLink";
1264         /**
1265          * The CLI argument name for setting the location of the suppression
1266          * file(s).
1267          */
1268         public static final String SUPPRESSION_FILES = "suppression";
1269         /**
1270          * The CLI argument name for setting the location of the hint file.
1271          */
1272         public static final String HINTS_FILE = "hints";
1273         /**
1274          * Disables the Jar Analyzer.
1275          */
1276         public static final String DISABLE_JAR = "disableJar";
1277         /**
1278          * Disable the MS Build Analyzer.
1279          */
1280         public static final String DISABLE_MSBUILD = "disableMSBuild";
1281         /**
1282          * Disables the Archive Analyzer.
1283          */
1284         public static final String DISABLE_ARCHIVE = "disableArchive";
1285         /**
1286          * Disables the Known Exploited Analyzer.
1287          */
1288         public static final String DISABLE_KEV = "disableKnownExploited";
1289         /**
1290          * The URL to the CISA Known Exploited Vulnerability JSON datafeed.
1291          */
1292         public static final String KEV_URL = "kevURL";
1293         /**
1294          * The user for basic auth towards a CISA Known Exploited Vulnerability JSON datafeed mirror.
1295          */
1296         public static final String KEV_USER = "kevUser";
1297         /**
1298          * The password for basic auth towards a CISA Known Exploited Vulnerability JSON datafeed mirror.
1299          */
1300         public static final String KEV_PASSWORD = "kevPassword";
1301         /**
1302          * The token for bearer auth towards a CISA Known Exploited Vulnerability JSON datafeed mirror.
1303          */
1304         public static final String KEV_BEARER_TOKEN = "kevBearerToken";
1305         /**
1306          * Disables the Python Distribution Analyzer.
1307          */
1308         public static final String DISABLE_PY_DIST = "disablePyDist";
1309         /**
1310          * Disables the Python Package Analyzer.
1311          */
1312         public static final String DISABLE_PY_PKG = "disablePyPkg";
1313         /**
1314          * Disables the Elixir mix audit Analyzer.
1315          */
1316         public static final String DISABLE_MIX_AUDIT = "disableMixAudit";
1317         /**
1318          * Disables the Golang Dependency Analyzer.
1319          */
1320         public static final String DISABLE_GO_DEP = "disableGolangDep";
1321         /**
1322          * Disables the PHP Composer Analyzer.
1323          */
1324         public static final String DISABLE_COMPOSER = "disableComposer";
1325         /**
1326          * Whether the PHP Composer Analyzer skips dev packages.
1327          */
1328         public static final String COMPOSER_LOCK_SKIP_DEV = "composerSkipDev";
1329         /**
1330          * Disables the Perl CPAN File Analyzer.
1331          */
1332         public static final String DISABLE_CPAN = "disableCpan";
1333         /**
1334          * Disables the Golang Mod Analyzer.
1335          */
1336         public static final String DISABLE_GOLANG_MOD = "disableGolangMod";
1337         /**
1338          * Disables the Dart Analyzer.
1339          */
1340         public static final String DISABLE_DART = "disableDart";
1341         /**
1342          * The CLI argument name for setting the path to `go`.
1343          */
1344         public static final String PATH_TO_GO = "go";
1345         /**
1346          * The CLI argument name for setting the path to `yarn`.
1347          */
1348         public static final String PATH_TO_YARN = "yarn";
1349         /**
1350          * The CLI argument name for setting the path to `pnpm`.
1351          */
1352         public static final String PATH_TO_PNPM = "pnpm";
1353         /**
1354          * Disables the Ruby Gemspec Analyzer.
1355          */
1356         public static final String DISABLE_RUBYGEMS = "disableRubygems";
1357         /**
1358          * Disables the Autoconf Analyzer.
1359          */
1360         public static final String DISABLE_AUTOCONF = "disableAutoconf";
1361         /**
1362          * Disables the Maven install Analyzer.
1363          */
1364         public static final String DISABLE_MAVEN_INSTALL = "disableMavenInstall";
1365         /**
1366          * Disables the pip Analyzer.
1367          */
1368         public static final String DISABLE_PIP = "disablePip";
1369         /**
1370          * Disables the Pipfile Analyzer.
1371          */
1372         public static final String DISABLE_PIPFILE = "disablePipfile";
1373         /**
1374          * Disables the Poetry Analyzer.
1375          */
1376         public static final String DISABLE_POETRY = "disablePoetry";
1377         /**
1378          * Disables the Cmake Analyzer.
1379          */
1380         public static final String DISABLE_CMAKE = "disableCmake";
1381         /**
1382          * Disables the cocoapods analyzer.
1383          */
1384         public static final String DISABLE_COCOAPODS = "disableCocoapodsAnalyzer";
1385         /**
1386          * Disables the Carthage analyzer.
1387          */
1388         public static final String DISABLE_CARTHAGE = "disableCarthageAnalyzer";
1389         /**
1390          * Disables the swift package manager analyzer.
1391          */
1392         public static final String DISABLE_SWIFT = "disableSwiftPackageManagerAnalyzer";
1393         /**
1394          * Disables the swift package resolved analyzer.
1395          */
1396         public static final String DISABLE_SWIFT_RESOLVED = "disableSwiftPackageResolvedAnalyzer";
1397         /**
1398          * Disables the Assembly Analyzer.
1399          */
1400         public static final String DISABLE_ASSEMBLY = "disableAssembly";
1401         /**
1402          * Disables the PE Analyzer.
1403          */
1404         public static final String DISABLE_PE = "disablePE";
1405         /**
1406          * Disables the Ruby Bundler Audit Analyzer.
1407          */
1408         public static final String DISABLE_BUNDLE_AUDIT = "disableBundleAudit";
1409         /**
1410          * Disables the File Name Analyzer.
1411          */
1412         public static final String DISABLE_FILENAME = "disableFileName";
1413         /**
1414          * Disables the Nuspec Analyzer.
1415          */
1416         public static final String DISABLE_NUSPEC = "disableNuspec";
1417         /**
1418          * Disables the Nuget packages.config Analyzer.
1419          */
1420         public static final String DISABLE_NUGETCONF = "disableNugetconf";
1421         /**
1422          * Disables the Central Analyzer.
1423          */
1424         public static final String DISABLE_CENTRAL = "disableCentral";
1425         /**
1426          * Disables the Central Analyzer's ability to cache results locally.
1427          */
1428         public static final String DISABLE_CENTRAL_CACHE = "disableCentralCache";
1429         /**
1430          * The alternative URL for Maven Central Search.
1431          */
1432         public static final String CENTRAL_URL = "centralUrl";
1433         /**
1434          * The username for basic authentication to the alternative Maven Central Search.
1435          */
1436         public static final String CENTRAL_USERNAME = "centralUsername";
1437         /**
1438          * The password for basic authentication to the alternative Maven Central Search.
1439          */
1440         public static final String CENTRAL_PASSWORD = "centralPassword";
1441         /**
1442          * The token for bearer authentication to the alternative Maven Central Search.
1443          */
1444         public static final String CENTRAL_BEARER_TOKEN = "centralBearerToken";
1445         /**
1446          * Disables the Nexus Analyzer.
1447          */
1448         public static final String ENABLE_NEXUS = "enableNexus";
1449         /**
1450          * Disables the Sonatype OSS Index Analyzer.
1451          */
1452         public static final String DISABLE_OSSINDEX = "disableOssIndex";
1453         /**
1454          * Disables the Sonatype OSS Index Analyzer's ability to cache results
1455          * locally.
1456          */
1457         public static final String DISABLE_OSSINDEX_CACHE = "disableOssIndexCache";
1458         /**
1459          * The alternative URL for the Sonatype OSS Index.
1460          */
1461         public static final String OSSINDEX_URL = "ossIndexUrl";
1462         /**
1463          * The username for the Sonatype OSS Index.
1464          */
1465         public static final String OSSINDEX_USERNAME = "ossIndexUsername";
1466         /**
1467          * The password for the Sonatype OSS Index.
1468          */
1469         public static final String OSSINDEX_PASSWORD = "ossIndexPassword";
1470         /**
1471          * The password for the Sonatype OSS Index.
1472          */
1473         public static final String OSSINDEX_WARN_ONLY_ON_REMOTE_ERRORS = "ossIndexRemoteErrorWarnOnly";
1474         /**
1475          * Disables the OpenSSL Analyzer.
1476          */
1477         public static final String DISABLE_OPENSSL = "disableOpenSSL";
1478         /**
1479          * Disables the Node.js Package Analyzer.
1480          */
1481         public static final String DISABLE_NODE_JS = "disableNodeJS";
1482         /**
1483          * Skips dev dependencies in Node Package Analyzer.
1484          */
1485         public static final String NODE_PACKAGE_SKIP_DEV_DEPENDENCIES = "nodePackageSkipDevDependencies";
1486         /**
1487          * Disables the Node Audit Analyzer.
1488          */
1489         public static final String DISABLE_NODE_AUDIT = "disableNodeAudit";
1490         /**
1491          * Disables the Yarn Audit Analyzer.
1492          */
1493         public static final String DISABLE_YARN_AUDIT = "disableYarnAudit";
1494         /**
1495          * Disables the Pnpm Audit Analyzer.
1496          */
1497         public static final String DISABLE_PNPM_AUDIT = "disablePnpmAudit";
1498         /**
1499          * Disables the Node Audit Analyzer's ability to cache results locally.
1500          */
1501         public static final String DISABLE_NODE_AUDIT_CACHE = "disableNodeAuditCache";
1502         /**
1503          * Configures the Node Audit Analyzer to skip the dev dependencies.
1504          */
1505         public static final String DISABLE_NODE_AUDIT_SKIPDEV = "nodeAuditSkipDevDependencies";
1506         /**
1507          * Disables the RetireJS Analyzer.
1508          * @deprecated Use {@link #DISABLE_RETIRE_JS} instead.
1509          */
1510         @Deprecated
1511         public static final String DISABLE_RETIREJS_DEPRECATED = "disableRetireJS";
1512         /**
1513          * Disables the RetireJS Analyzer.
1514          */
1515         public static final String DISABLE_RETIRE_JS = "disableRetireJs";
1516         /**
1517          * Whether the RetireJS Analyzer will update regardless of the
1518          * `autoupdate` setting.
1519          */
1520         public static final String RETIRE_JS_FORCEUPDATE = "retireJsForceUpdate";
1521         /**
1522          * The URL to the retire JS repository.
1523          */
1524         public static final String RETIREJS_URL = "retireJsUrl";
1525         /**
1526          * The username for basic auth to the retire JS repository.
1527          */
1528         public static final String RETIREJS_URL_USER = "retireJsUrlUser";
1529         /**
1530          * The password for basic auth to the retire JS repository.
1531          */
1532         public static final String RETIREJS_URL_PASSWORD = "retireJsUrlPass";
1533         /**
1534          * The token for bearer auth to the retire JS repository.
1535          */
1536         public static final String RETIREJS_URL_BEARER_TOKEN = "retireJsUrlBearerToken";
1537         /**
1538          * The URL of the nexus server.
1539          */
1540         public static final String NEXUS_URL = "nexus";
1541         /**
1542          * The username for the nexus server.
1543          */
1544         public static final String NEXUS_USERNAME = "nexusUser";
1545         /**
1546          * The password for the nexus server.
1547          */
1548         public static final String NEXUS_PASSWORD = "nexusPass";
1549         /**
1550          * Whether or not the defined proxy should be used when connecting to
1551          * Nexus.
1552          */
1553         public static final String NEXUS_USES_PROXY = "nexusUsesProxy";
1554         /**
1555          * The CLI argument name for setting the connection string.
1556          */
1557         public static final String CONNECTION_STRING = "connectionString";
1558         /**
1559          * The CLI argument name for setting the database user name.
1560          */
1561         public static final String DB_NAME = "dbUser";
1562         /**
1563          * The CLI argument name for setting the database password.
1564          */
1565         public static final String DB_PASSWORD = "dbPassword";
1566         /**
1567          * The CLI argument name for setting the database driver name.
1568          */
1569         public static final String DB_DRIVER = "dbDriverName";
1570         /**
1571          * The CLI argument name for setting the path to the database driver; in
1572          * case it is not on the class path.
1573          */
1574         public static final String DB_DRIVER_PATH = "dbDriverPath";
1575         /**
1576          * The CLI argument name for setting the path to dotnet core.
1577          */
1578         public static final String PATH_TO_CORE = "dotnet";
1579         /**
1580          * The CLI argument name for setting extra extensions.
1581          */
1582         public static final String ADDITIONAL_ZIP_EXTENSIONS = "zipExtensions";
1583         /**
1584          * Exclude path argument.
1585          */
1586         public static final String EXCLUDE = "exclude";
1587         /**
1588          * The CLI argument name for setting the path to bundle-audit for Ruby
1589          * bundle analysis.
1590          */
1591         public static final String PATH_TO_BUNDLE_AUDIT = "bundleAudit";
1592         /**
1593          * The CLI argument name for setting the path that should be used as the
1594          * working directory that the bundle-audit command used for Ruby bundle
1595          * analysis should be executed from. This will allow for the usage of
1596          * rbenv
1597          */
1598         public static final String PATH_TO_BUNDLE_AUDIT_WORKING_DIRECTORY = "bundleAuditWorkingDirectory";
1599         /**
1600          * The CLI argument name for setting the path to mix_audit for Elixir
1601          * analysis.
1602          */
1603         public static final String PATH_TO_MIX_AUDIT = "mixAudit";
1604         /**
1605          * The CLI argument to enable the experimental analyzers.
1606          */
1607         public static final String EXPERIMENTAL = "enableExperimental";
1608         /**
1609          * The CLI argument to enable the retired analyzers.
1610          */
1611         public static final String RETIRED = "enableRetired";
1612         /**
1613          * The CLI argument for the retire js content filters.
1614          * @deprecated Use {@link #RETIRE_JS_FILTERS} instead.
1615          */
1616         @Deprecated
1617         public static final String RETIREJS_FILTERS_DEPRECATED = "retirejsFilter";
1618         /**
1619          * The CLI argument for the retire JS content filters.
1620          */
1621         public static final String RETIRE_JS_FILTERS = "retireJsFilter";
1622         /**
1623          * The CLI argument for the retire js content filters.
1624          * @deprecated Use {@link #RETIRE_JS_FILTER_NON_VULNERABLE} instead.
1625          */
1626         @Deprecated
1627         public static final String RETIREJS_FILTER_NON_VULNERABLE_DEPRECATED = "retirejsFilterNonVulnerable";
1628         /**
1629          * The CLI argument for the retire JS content filter for non-vulnerable.
1630          */
1631         public static final String RETIRE_JS_FILTER_NON_VULNERABLE = "retireJsFilterNonVulnerable";
1632         /**
1633          * The CLI argument for indicating if the Artifactory analyzer should be
1634          * enabled.
1635          */
1636         public static final String ARTIFACTORY_ENABLED = "enableArtifactory";
1637         /**
1638          * The CLI argument for indicating if the Artifactory analyzer should
1639          * use the proxy.
1640          */
1641         public static final String ARTIFACTORY_URL = "artifactoryUrl";
1642         /**
1643          * The CLI argument for indicating the Artifactory username.
1644          */
1645         public static final String ARTIFACTORY_USERNAME = "artifactoryUsername";
1646         /**
1647          * The CLI argument for indicating the Artifactory API token.
1648          */
1649         public static final String ARTIFACTORY_API_TOKEN = "artifactoryApiToken";
1650         /**
1651          * The CLI argument for indicating the Artifactory bearer token.
1652          */
1653         public static final String ARTIFACTORY_BEARER_TOKEN = "artifactoryBearerToken";
1654         /**
1655          * The CLI argument for indicating if the Artifactory analyzer should
1656          * use the proxy.
1657          */
1658         public static final String ARTIFACTORY_USES_PROXY = "artifactoryUseProxy";
1659         /**
1660          * The CLI argument for indicating if the Artifactory analyzer should
1661          * use the parallel analysis.
1662          */
1663         public static final String ARTIFACTORY_PARALLEL_ANALYSIS = "artifactoryParallelAnalysis";
1664         /**
1665          * The CLI argument to configure when the execution should be considered
1666          * a failure.
1667          */
1668         public static final String FAIL_ON_CVSS = "failOnCVSS";
1669         /**
1670          * The CLI argument to configure if the XML and JSON reports should be
1671          * pretty printed.
1672          */
1673         public static final String PRETTY_PRINT = "prettyPrint";
1674         /**
1675          * The CLI argument to set the threshold that is considered a failure
1676          * when generating the JUNIT report format.
1677          */
1678         public static final String FAIL_JUNIT_ON_CVSS = "junitFailOnCVSS";
1679         /**
1680          * The CLI argument to set the number of hours to wait before
1681          * re-checking hosted suppressions file for updates.
1682          */
1683         public static final String DISABLE_HOSTED_SUPPRESSIONS = "disableHostedSuppressions";
1684         /**
1685          * The CLI argument to set the number of hours to wait before
1686          * re-checking hosted suppressions file for updates.
1687          */
1688         public static final String HOSTED_SUPPRESSIONS_VALID_FOR_HOURS = "hostedSuppressionsValidForHours";
1689         /**
1690          * The CLI argument to set Whether the hosted suppressions file will
1691          * update regardless of the `noupdate` argument.
1692          */
1693         public static final String HOSTED_SUPPRESSIONS_FORCEUPDATE = "hostedSuppressionsForceUpdate";
1694         /**
1695          * The CLI argument to set the location of a mirrored hosted
1696          * suppressions file .
1697          */
1698         public static final String HOSTED_SUPPRESSIONS_URL = "hostedSuppressionsUrl";
1699         /**
1700          * The username for basic auth to a mirrored hosted suppressions file.
1701          */
1702         public static final String HOSTED_SUPPRESSIONS_USER = "hostedSuppressionsUser";
1703         /**
1704          * The passwored for basic auth to a mirrored hosted suppressions file.
1705          */
1706         public static final String HOSTED_SUPPRESSIONS_PASSWORD = "hostedSuppressionsPassword";
1707         /**
1708          * The toke for bearer auth to  a mirrored hosted suppressions file.
1709          */
1710         public static final String HOSTED_SUPPRESSIONS_BEARER_TOKEN = "hostedSuppressionsBearerToken";
1711     }
1712 }