View Javadoc
1   /*
2    * This file is part of dependency-check-ant.
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) 2013 Jeremy Long. All Rights Reserved.
17   */
18  package org.owasp.dependencycheck.taskdefs;
19  
20  import java.io.File;
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.util.List;
24  import java.util.logging.Level;
25  import java.util.logging.Logger;
26  import org.apache.tools.ant.BuildException;
27  import org.apache.tools.ant.Task;
28  import org.apache.tools.ant.types.EnumeratedAttribute;
29  import org.apache.tools.ant.types.Reference;
30  import org.apache.tools.ant.types.Resource;
31  import org.apache.tools.ant.types.ResourceCollection;
32  import org.apache.tools.ant.types.resources.FileProvider;
33  import org.apache.tools.ant.types.resources.Resources;
34  import org.owasp.dependencycheck.Engine;
35  import org.owasp.dependencycheck.data.nvdcve.CveDB;
36  import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
37  import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
38  import org.owasp.dependencycheck.dependency.Dependency;
39  import org.owasp.dependencycheck.dependency.Identifier;
40  import org.owasp.dependencycheck.dependency.Vulnerability;
41  import org.owasp.dependencycheck.reporting.ReportGenerator;
42  import org.owasp.dependencycheck.reporting.ReportGenerator.Format;
43  import org.owasp.dependencycheck.utils.LogUtils;
44  import org.owasp.dependencycheck.utils.Settings;
45  
46  /**
47   * An Ant task definition to execute dependency-check during an Ant build.
48   *
49   * @author Jeremy Long <jeremy.long@owasp.org>
50   */
51  public class DependencyCheckTask extends Task {
52  
53      /**
54       * The properties file location.
55       */
56      private static final String PROPERTIES_FILE = "task.properties";
57      /**
58       * Name of the logging properties file.
59       */
60      private static final String LOG_PROPERTIES_FILE = "log.properties";
61      /**
62       * System specific new line character.
63       */
64      private static final String NEW_LINE = System.getProperty("line.separator", "\n").intern();
65  
66      /**
67       * Construct a new DependencyCheckTask.
68       */
69      public DependencyCheckTask() {
70          super();
71      }
72      //The following code was copied Apache Ant PathConvert
73      //BEGIN COPY from org.apache.tools.ant.taskdefs.PathConvert
74      /**
75       * Path to be converted
76       */
77      private Resources path = null;
78      /**
79       * Reference to path/fileset to convert
80       */
81      private Reference refid = null;
82  
83      /**
84       * Add an arbitrary ResourceCollection.
85       *
86       * @param rc the ResourceCollection to add.
87       * @since Ant 1.7
88       */
89      public void add(ResourceCollection rc) {
90          if (isReference()) {
91              throw new BuildException("Nested elements are not allowed when using the refid attribute.");
92          }
93          getPath().add(rc);
94      }
95  
96      /**
97       * Returns the path. If the path has not been initialized yet, this class is synchronized, and will instantiate the
98       * path object.
99       *
100      * @return the path
101      */
102     private synchronized Resources getPath() {
103         if (path == null) {
104             path = new Resources(getProject());
105             path.setCache(true);
106         }
107         return path;
108     }
109 
110     /**
111      * Learn whether the refid attribute of this element been set.
112      *
113      * @return true if refid is valid.
114      */
115     public boolean isReference() {
116         return refid != null;
117     }
118 
119     /**
120      * Add a reference to a Path, FileSet, DirSet, or FileList defined elsewhere.
121      *
122      * @param r the reference to a path, fileset, dirset or filelist.
123      */
124     public void setRefid(Reference r) {
125         if (path != null) {
126             throw new BuildException("Nested elements are not allowed when using the refid attribute.");
127         }
128         refid = r;
129     }
130 
131     /**
132      * If this is a reference, this method will add the referenced resource collection to the collection of paths.
133      *
134      * @throws BuildException if the reference is not to a resource collection
135      */
136     private void dealWithReferences() throws BuildException {
137         if (isReference()) {
138             final Object o = refid.getReferencedObject(getProject());
139             if (!(o instanceof ResourceCollection)) {
140                 throw new BuildException("refid '" + refid.getRefId()
141                         + "' does not refer to a resource collection.");
142             }
143             getPath().add((ResourceCollection) o);
144         }
145     }
146     // END COPY from org.apache.tools.ant.taskdefs
147     /**
148      * The application name for the report.
149      */
150     private String applicationName = "Dependency-Check";
151 
152     /**
153      * Get the value of applicationName.
154      *
155      * @return the value of applicationName
156      */
157     public String getApplicationName() {
158         return applicationName;
159     }
160 
161     /**
162      * Set the value of applicationName.
163      *
164      * @param applicationName new value of applicationName
165      */
166     public void setApplicationName(String applicationName) {
167         this.applicationName = applicationName;
168     }
169     /**
170      * The location of the data directory that contains
171      */
172     private String dataDirectory = null;
173 
174     /**
175      * Get the value of dataDirectory.
176      *
177      * @return the value of dataDirectory
178      */
179     public String getDataDirectory() {
180         return dataDirectory;
181     }
182 
183     /**
184      * Set the value of dataDirectory.
185      *
186      * @param dataDirectory new value of dataDirectory
187      */
188     public void setDataDirectory(String dataDirectory) {
189         this.dataDirectory = dataDirectory;
190     }
191     /**
192      * Specifies the destination directory for the generated Dependency-Check report.
193      */
194     private String reportOutputDirectory = ".";
195 
196     /**
197      * Get the value of reportOutputDirectory.
198      *
199      * @return the value of reportOutputDirectory
200      */
201     public String getReportOutputDirectory() {
202         return reportOutputDirectory;
203     }
204 
205     /**
206      * Set the value of reportOutputDirectory.
207      *
208      * @param reportOutputDirectory new value of reportOutputDirectory
209      */
210     public void setReportOutputDirectory(String reportOutputDirectory) {
211         this.reportOutputDirectory = reportOutputDirectory;
212     }
213     /**
214      * Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11
215      * which means since the CVSS scores are 0-10, by default the build will never fail and the CVSS score is set to 11.
216      * The valid range for the fail build on CVSS is 0 to 11, where anything above 10 will not cause the build to fail.
217      */
218     private float failBuildOnCVSS = 11;
219 
220     /**
221      * Get the value of failBuildOnCVSS.
222      *
223      * @return the value of failBuildOnCVSS
224      */
225     public float getFailBuildOnCVSS() {
226         return failBuildOnCVSS;
227     }
228 
229     /**
230      * Set the value of failBuildOnCVSS.
231      *
232      * @param failBuildOnCVSS new value of failBuildOnCVSS
233      */
234     public void setFailBuildOnCVSS(float failBuildOnCVSS) {
235         this.failBuildOnCVSS = failBuildOnCVSS;
236     }
237     /**
238      * Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to
239      * false. Default is true.
240      */
241     private boolean autoUpdate = true;
242 
243     /**
244      * Get the value of autoUpdate.
245      *
246      * @return the value of autoUpdate
247      */
248     public boolean isAutoUpdate() {
249         return autoUpdate;
250     }
251 
252     /**
253      * Set the value of autoUpdate.
254      *
255      * @param autoUpdate new value of autoUpdate
256      */
257     public void setAutoUpdate(boolean autoUpdate) {
258         this.autoUpdate = autoUpdate;
259     }
260     /**
261      * The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this
262      * within the Site plugin unless the externalReport is set to true. Default is HTML.
263      */
264     private String reportFormat = "HTML";
265 
266     /**
267      * Get the value of reportFormat.
268      *
269      * @return the value of reportFormat
270      */
271     public String getReportFormat() {
272         return reportFormat;
273     }
274 
275     /**
276      * Set the value of reportFormat.
277      *
278      * @param reportFormat new value of reportFormat
279      */
280     public void setReportFormat(ReportFormats reportFormat) {
281         this.reportFormat = reportFormat.getValue();
282     }
283     /**
284      * The Proxy URL.
285      */
286     private String proxyUrl;
287 
288     /**
289      * Get the value of proxyUrl.
290      *
291      * @return the value of proxyUrl
292      */
293     public String getProxyUrl() {
294         return proxyUrl;
295     }
296 
297     /**
298      * Set the value of proxyUrl.
299      *
300      * @param proxyUrl new value of proxyUrl
301      */
302     public void setProxyUrl(String proxyUrl) {
303         this.proxyUrl = proxyUrl;
304     }
305     /**
306      * The Proxy Port.
307      */
308     private String proxyPort;
309 
310     /**
311      * Get the value of proxyPort.
312      *
313      * @return the value of proxyPort
314      */
315     public String getProxyPort() {
316         return proxyPort;
317     }
318 
319     /**
320      * Set the value of proxyPort.
321      *
322      * @param proxyPort new value of proxyPort
323      */
324     public void setProxyPort(String proxyPort) {
325         this.proxyPort = proxyPort;
326     }
327     /**
328      * The Proxy username.
329      */
330     private String proxyUsername;
331 
332     /**
333      * Get the value of proxyUsername.
334      *
335      * @return the value of proxyUsername
336      */
337     public String getProxyUsername() {
338         return proxyUsername;
339     }
340 
341     /**
342      * Set the value of proxyUsername.
343      *
344      * @param proxyUsername new value of proxyUsername
345      */
346     public void setProxyUsername(String proxyUsername) {
347         this.proxyUsername = proxyUsername;
348     }
349     /**
350      * The Proxy password.
351      */
352     private String proxyPassword;
353 
354     /**
355      * Get the value of proxyPassword.
356      *
357      * @return the value of proxyPassword
358      */
359     public String getProxyPassword() {
360         return proxyPassword;
361     }
362 
363     /**
364      * Set the value of proxyPassword.
365      *
366      * @param proxyPassword new value of proxyPassword
367      */
368     public void setProxyPassword(String proxyPassword) {
369         this.proxyPassword = proxyPassword;
370     }
371     /**
372      * The Connection Timeout.
373      */
374     private String connectionTimeout;
375 
376     /**
377      * Get the value of connectionTimeout.
378      *
379      * @return the value of connectionTimeout
380      */
381     public String getConnectionTimeout() {
382         return connectionTimeout;
383     }
384 
385     /**
386      * Set the value of connectionTimeout.
387      *
388      * @param connectionTimeout new value of connectionTimeout
389      */
390     public void setConnectionTimeout(String connectionTimeout) {
391         this.connectionTimeout = connectionTimeout;
392     }
393     /**
394      * The file path used for verbose logging.
395      */
396     private String logFile = null;
397 
398     /**
399      * Get the value of logFile.
400      *
401      * @return the value of logFile
402      */
403     public String getLogFile() {
404         return logFile;
405     }
406 
407     /**
408      * Set the value of logFile.
409      *
410      * @param logFile new value of logFile
411      */
412     public void setLogFile(String logFile) {
413         this.logFile = logFile;
414     }
415     /**
416      * The path to the suppression file.
417      */
418     private String suppressionFile;
419 
420     /**
421      * Get the value of suppressionFile.
422      *
423      * @return the value of suppressionFile
424      */
425     public String getSuppressionFile() {
426         return suppressionFile;
427     }
428 
429     /**
430      * Set the value of suppressionFile.
431      *
432      * @param suppressionFile new value of suppressionFile
433      */
434     public void setSuppressionFile(String suppressionFile) {
435         this.suppressionFile = suppressionFile;
436     }
437     /**
438      * flag indicating whether or not to show a summary of findings.
439      */
440     private boolean showSummary = true;
441 
442     /**
443      * Get the value of showSummary.
444      *
445      * @return the value of showSummary
446      */
447     public boolean isShowSummary() {
448         return showSummary;
449     }
450 
451     /**
452      * Set the value of showSummary.
453      *
454      * @param showSummary new value of showSummary
455      */
456     public void setShowSummary(boolean showSummary) {
457         this.showSummary = showSummary;
458     }
459 
460     /**
461      * Whether or not the nexus analyzer is enabled.
462      */
463     private boolean nexusAnalyzerEnabled = true;
464 
465     /**
466      * Get the value of nexusAnalyzerEnabled.
467      *
468      * @return the value of nexusAnalyzerEnabled
469      */
470     public boolean isNexusAnalyzerEnabled() {
471         return nexusAnalyzerEnabled;
472     }
473 
474     /**
475      * Set the value of nexusAnalyzerEnabled.
476      *
477      * @param nexusAnalyzerEnabled new value of nexusAnalyzerEnabled
478      */
479     public void setNexusAnalyzerEnabled(boolean nexusAnalyzerEnabled) {
480         this.nexusAnalyzerEnabled = nexusAnalyzerEnabled;
481     }
482 
483     /**
484      * The URL of the Nexus server.
485      */
486     private String nexusUrl;
487 
488     /**
489      * Get the value of nexusUrl.
490      *
491      * @return the value of nexusUrl
492      */
493     public String getNexusUrl() {
494         return nexusUrl;
495     }
496 
497     /**
498      * Set the value of nexusUrl.
499      *
500      * @param nexusUrl new value of nexusUrl
501      */
502     public void setNexusUrl(String nexusUrl) {
503         this.nexusUrl = nexusUrl;
504     }
505     /**
506      * Whether or not the defined proxy should be used when connecting to Nexus.
507      */
508     private boolean nexusUsesProxy = true;
509 
510     /**
511      * Get the value of nexusUsesProxy.
512      *
513      * @return the value of nexusUsesProxy
514      */
515     public boolean isNexusUsesProxy() {
516         return nexusUsesProxy;
517     }
518 
519     /**
520      * Set the value of nexusUsesProxy.
521      *
522      * @param nexusUsesProxy new value of nexusUsesProxy
523      */
524     public void setNexusUsesProxy(boolean nexusUsesProxy) {
525         this.nexusUsesProxy = nexusUsesProxy;
526     }
527 
528     /**
529      * The database driver name; such as org.h2.Driver.
530      */
531     private String databaseDriverName;
532 
533     /**
534      * Get the value of databaseDriverName.
535      *
536      * @return the value of databaseDriverName
537      */
538     public String getDatabaseDriverName() {
539         return databaseDriverName;
540     }
541 
542     /**
543      * Set the value of databaseDriverName.
544      *
545      * @param databaseDriverName new value of databaseDriverName
546      */
547     public void setDatabaseDriverName(String databaseDriverName) {
548         this.databaseDriverName = databaseDriverName;
549     }
550 
551     /**
552      * The path to the database driver JAR file if it is not on the class path.
553      */
554     private String databaseDriverPath;
555 
556     /**
557      * Get the value of databaseDriverPath.
558      *
559      * @return the value of databaseDriverPath
560      */
561     public String getDatabaseDriverPath() {
562         return databaseDriverPath;
563     }
564 
565     /**
566      * Set the value of databaseDriverPath.
567      *
568      * @param databaseDriverPath new value of databaseDriverPath
569      */
570     public void setDatabaseDriverPath(String databaseDriverPath) {
571         this.databaseDriverPath = databaseDriverPath;
572     }
573     /**
574      * The database connection string.
575      */
576     private String connectionString;
577 
578     /**
579      * Get the value of connectionString.
580      *
581      * @return the value of connectionString
582      */
583     public String getConnectionString() {
584         return connectionString;
585     }
586 
587     /**
588      * Set the value of connectionString.
589      *
590      * @param connectionString new value of connectionString
591      */
592     public void setConnectionString(String connectionString) {
593         this.connectionString = connectionString;
594     }
595     /**
596      * The user name for connecting to the database.
597      */
598     private String databaseUser;
599 
600     /**
601      * Get the value of databaseUser.
602      *
603      * @return the value of databaseUser
604      */
605     public String getDatabaseUser() {
606         return databaseUser;
607     }
608 
609     /**
610      * Set the value of databaseUser.
611      *
612      * @param databaseUser new value of databaseUser
613      */
614     public void setDatabaseUser(String databaseUser) {
615         this.databaseUser = databaseUser;
616     }
617 
618     /**
619      * The password to use when connecting to the database.
620      */
621     private String databasePassword;
622 
623     /**
624      * Get the value of databasePassword.
625      *
626      * @return the value of databasePassword
627      */
628     public String getDatabasePassword() {
629         return databasePassword;
630     }
631 
632     /**
633      * Set the value of databasePassword.
634      *
635      * @param databasePassword new value of databasePassword
636      */
637     public void setDatabasePassword(String databasePassword) {
638         this.databasePassword = databasePassword;
639     }
640 
641     /**
642      * Additional ZIP File extensions to add analyze. This should be a comma-separated list of file extensions to treat
643      * like ZIP files.
644      */
645     private String zipExtensions;
646 
647     /**
648      * Get the value of zipExtensions.
649      *
650      * @return the value of zipExtensions
651      */
652     public String getZipExtensions() {
653         return zipExtensions;
654     }
655 
656     /**
657      * Set the value of zipExtensions.
658      *
659      * @param zipExtensions new value of zipExtensions
660      */
661     public void setZipExtensions(String zipExtensions) {
662         this.zipExtensions = zipExtensions;
663     }
664 
665     /**
666      * The url for the modified NVD CVE (1.2 schema).
667      */
668     private String cveUrl12Modified;
669 
670     /**
671      * Get the value of cveUrl12Modified.
672      *
673      * @return the value of cveUrl12Modified
674      */
675     public String getCveUrl12Modified() {
676         return cveUrl12Modified;
677     }
678 
679     /**
680      * Set the value of cveUrl12Modified.
681      *
682      * @param cveUrl12Modified new value of cveUrl12Modified
683      */
684     public void setCveUrl12Modified(String cveUrl12Modified) {
685         this.cveUrl12Modified = cveUrl12Modified;
686     }
687 
688     /**
689      * The url for the modified NVD CVE (2.0 schema).
690      */
691     private String cveUrl20Modified;
692 
693     /**
694      * Get the value of cveUrl20Modified.
695      *
696      * @return the value of cveUrl20Modified
697      */
698     public String getCveUrl20Modified() {
699         return cveUrl20Modified;
700     }
701 
702     /**
703      * Set the value of cveUrl20Modified.
704      *
705      * @param cveUrl20Modified new value of cveUrl20Modified
706      */
707     public void setCveUrl20Modified(String cveUrl20Modified) {
708         this.cveUrl20Modified = cveUrl20Modified;
709     }
710 
711     /**
712      * Base Data Mirror URL for CVE 1.2.
713      */
714     private String cveUrl12Base;
715 
716     /**
717      * Get the value of cveUrl12Base.
718      *
719      * @return the value of cveUrl12Base
720      */
721     public String getCveUrl12Base() {
722         return cveUrl12Base;
723     }
724 
725     /**
726      * Set the value of cveUrl12Base.
727      *
728      * @param cveUrl12Base new value of cveUrl12Base
729      */
730     public void setCveUrl12Base(String cveUrl12Base) {
731         this.cveUrl12Base = cveUrl12Base;
732     }
733 
734     /**
735      * Data Mirror URL for CVE 2.0.
736      */
737     private String cveUrl20Base;
738 
739     /**
740      * Get the value of cveUrl20Base.
741      *
742      * @return the value of cveUrl20Base
743      */
744     public String getCveUrl20Base() {
745         return cveUrl20Base;
746     }
747 
748     /**
749      * Set the value of cveUrl20Base.
750      *
751      * @param cveUrl20Base new value of cveUrl20Base
752      */
753     public void setCveUrl20Base(String cveUrl20Base) {
754         this.cveUrl20Base = cveUrl20Base;
755     }
756     /**
757      * The path to Mono for .NET assembly analysis on non-windows systems.
758      */
759     private String pathToMono;
760 
761     /**
762      * Get the value of pathToMono.
763      *
764      * @return the value of pathToMono
765      */
766     public String getPathToMono() {
767         return pathToMono;
768     }
769 
770     /**
771      * Set the value of pathToMono.
772      *
773      * @param pathToMono new value of pathToMono
774      */
775     public void setPathToMono(String pathToMono) {
776         this.pathToMono = pathToMono;
777     }
778 
779     @Override
780     public void execute() throws BuildException {
781         final InputStream in = DependencyCheckTask.class.getClassLoader().getResourceAsStream(LOG_PROPERTIES_FILE);
782         LogUtils.prepareLogger(in, logFile);
783 
784         dealWithReferences();
785         validateConfiguration();
786         populateSettings();
787 
788         Engine engine = null;
789         try {
790             engine = new Engine();
791 
792             for (Resource resource : path) {
793                 final FileProvider provider = resource.as(FileProvider.class);
794                 if (provider != null) {
795                     final File file = provider.getFile();
796                     if (file != null && file.exists()) {
797                         engine.scan(file);
798                     }
799                 }
800             }
801             try {
802                 engine.analyzeDependencies();
803                 DatabaseProperties prop = null;
804                 CveDB cve = null;
805                 try {
806                     cve = new CveDB();
807                     cve.open();
808                     prop = cve.getDatabaseProperties();
809                 } catch (DatabaseException ex) {
810                     Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, "Unable to retrieve DB Properties", ex);
811                 } finally {
812                     if (cve != null) {
813                         cve.close();
814                     }
815                 }
816                 final ReportGenerator reporter = new ReportGenerator(applicationName, engine.getDependencies(), engine.getAnalyzers(), prop);
817                 reporter.generateReports(reportOutputDirectory, reportFormat);
818 
819                 if (this.failBuildOnCVSS <= 10) {
820                     checkForFailure(engine.getDependencies());
821                 }
822                 if (this.showSummary) {
823                     showSummary(engine.getDependencies());
824                 }
825             } catch (IOException ex) {
826                 Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE,
827                         "Unable to generate dependency-check report", ex);
828                 throw new BuildException("Unable to generate dependency-check report", ex);
829             } catch (Exception ex) {
830                 Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE,
831                         "An exception occurred; unable to continue task", ex);
832                 throw new BuildException("An exception occurred; unable to continue task", ex);
833             }
834         } catch (DatabaseException ex) {
835             Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.SEVERE,
836                     "Unable to connect to the dependency-check database; analysis has stopped");
837             Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, "", ex);
838         } finally {
839             if (engine != null) {
840                 engine.cleanup();
841             }
842         }
843     }
844 
845     /**
846      * Validate the configuration to ensure the parameters have been properly configured/initialized.
847      *
848      * @throws BuildException if the task was not configured correctly.
849      */
850     private void validateConfiguration() throws BuildException {
851         if (path == null) {
852             throw new BuildException("No project dependencies have been defined to analyze.");
853         }
854         if (failBuildOnCVSS < 0 || failBuildOnCVSS > 11) {
855             throw new BuildException("Invalid configuration, failBuildOnCVSS must be between 0 and 11.");
856         }
857     }
858 
859     /**
860      * Takes the properties supplied and updates the dependency-check settings. Additionally, this sets the system
861      * properties required to change the proxy url, port, and connection timeout.
862      */
863     private void populateSettings() {
864         InputStream taskProperties = null;
865         try {
866             taskProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
867             Settings.mergeProperties(taskProperties);
868         } catch (IOException ex) {
869             Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.WARNING, "Unable to load the dependency-check ant task.properties file.");
870             Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, null, ex);
871         } finally {
872             if (taskProperties != null) {
873                 try {
874                     taskProperties.close();
875                 } catch (IOException ex) {
876                     Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINEST, null, ex);
877                 }
878             }
879         }
880         if (dataDirectory != null) {
881             Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
882         } else {
883             final File jarPath = new File(DependencyCheckTask.class.getProtectionDomain().getCodeSource().getLocation().getPath());
884             final File base = jarPath.getParentFile();
885             final String sub = Settings.getString(Settings.KEYS.DATA_DIRECTORY);
886             final File dataDir = new File(base, sub);
887             Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
888         }
889 
890         Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
891 
892         if (proxyUrl != null && !proxyUrl.isEmpty()) {
893             Settings.setString(Settings.KEYS.PROXY_URL, proxyUrl);
894         }
895         if (proxyPort != null && !proxyPort.isEmpty()) {
896             Settings.setString(Settings.KEYS.PROXY_PORT, proxyPort);
897         }
898         if (proxyUsername != null && !proxyUsername.isEmpty()) {
899             Settings.setString(Settings.KEYS.PROXY_USERNAME, proxyUsername);
900         }
901         if (proxyPassword != null && !proxyPassword.isEmpty()) {
902             Settings.setString(Settings.KEYS.PROXY_PASSWORD, proxyPassword);
903         }
904         if (connectionTimeout != null && !connectionTimeout.isEmpty()) {
905             Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
906         }
907         if (suppressionFile != null && !suppressionFile.isEmpty()) {
908             Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
909         }
910         Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled);
911         if (nexusUrl != null && !nexusUrl.isEmpty()) {
912             Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
913         }
914         Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY, nexusUsesProxy);
915         if (databaseDriverName != null && !databaseDriverName.isEmpty()) {
916             Settings.setString(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
917         }
918         if (databaseDriverPath != null && !databaseDriverPath.isEmpty()) {
919             Settings.setString(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
920         }
921         if (connectionString != null && !connectionString.isEmpty()) {
922             Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
923         }
924         if (databaseUser != null && !databaseUser.isEmpty()) {
925             Settings.setString(Settings.KEYS.DB_USER, databaseUser);
926         }
927         if (databasePassword != null && !databasePassword.isEmpty()) {
928             Settings.setString(Settings.KEYS.DB_PASSWORD, databasePassword);
929         }
930         if (zipExtensions != null && !zipExtensions.isEmpty()) {
931             Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions);
932         }
933         if (cveUrl12Modified != null && !cveUrl12Modified.isEmpty()) {
934             Settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified);
935         }
936         if (cveUrl20Modified != null && !cveUrl20Modified.isEmpty()) {
937             Settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified);
938         }
939         if (cveUrl12Base != null && !cveUrl12Base.isEmpty()) {
940             Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base);
941         }
942         if (cveUrl20Base != null && !cveUrl20Base.isEmpty()) {
943             Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base);
944         }
945         if (pathToMono != null && !pathToMono.isEmpty()) {
946             Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
947         }
948     }
949 
950     /**
951      * Checks to see if a vulnerability has been identified with a CVSS score that is above the threshold set in the
952      * configuration.
953      *
954      * @param dependencies the list of dependency objects
955      * @throws BuildException thrown if a CVSS score is found that is higher then the threshold set
956      */
957     private void checkForFailure(List<Dependency> dependencies) throws BuildException {
958         final StringBuilder ids = new StringBuilder();
959         for (Dependency d : dependencies) {
960             for (Vulnerability v : d.getVulnerabilities()) {
961                 if (v.getCvssScore() >= failBuildOnCVSS) {
962                     if (ids.length() == 0) {
963                         ids.append(v.getName());
964                     } else {
965                         ids.append(", ").append(v.getName());
966                     }
967                 }
968             }
969         }
970         if (ids.length() > 0) {
971             final String msg = String.format("%n%nDependency-Check Failure:%n"
972                     + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n"
973                     + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString());
974             throw new BuildException(msg);
975         }
976     }
977 
978     /**
979      * Generates a warning message listing a summary of dependencies and their associated CPE and CVE entries.
980      *
981      * @param dependencies a list of dependency objects
982      */
983     private void showSummary(List<Dependency> dependencies) {
984         final StringBuilder summary = new StringBuilder();
985         for (Dependency d : dependencies) {
986             boolean firstEntry = true;
987             final StringBuilder ids = new StringBuilder();
988             for (Vulnerability v : d.getVulnerabilities()) {
989                 if (firstEntry) {
990                     firstEntry = false;
991                 } else {
992                     ids.append(", ");
993                 }
994                 ids.append(v.getName());
995             }
996             if (ids.length() > 0) {
997                 summary.append(d.getFileName()).append(" (");
998                 firstEntry = true;
999                 for (Identifier id : d.getIdentifiers()) {
1000                     if (firstEntry) {
1001                         firstEntry = false;
1002                     } else {
1003                         summary.append(", ");
1004                     }
1005                     summary.append(id.getValue());
1006                 }
1007                 summary.append(") : ").append(ids).append(NEW_LINE);
1008             }
1009         }
1010         if (summary.length() > 0) {
1011             final String msg = String.format("%n%n"
1012                     + "One or more dependencies were identified with known vulnerabilities:%n%n%s"
1013                     + "%n%nSee the dependency-check report for more details.%n%n", summary.toString());
1014             Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.WARNING, msg);
1015         }
1016     }
1017 
1018     /**
1019      * An enumeration of supported report formats: "ALL", "HTML", "XML", "VULN", etc..
1020      */
1021     public static class ReportFormats extends EnumeratedAttribute {
1022 
1023         /**
1024          * Returns the list of values for the report format.
1025          *
1026          * @return the list of values for the report format
1027          */
1028         @Override
1029         public String[] getValues() {
1030             int i = 0;
1031             final Format[] formats = Format.values();
1032             final String[] values = new String[formats.length];
1033             for (Format format : formats) {
1034                 values[i++] = format.name();
1035             }
1036             return values;
1037         }
1038     }
1039 }