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