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 //start changes
573     /**
574      * Whether or not the Ruby Bundle Audit Analyzer is enabled.
575      */
576     private Boolean bundleAuditAnalyzerEnabled;
577 
578     /**
579      * Returns if the Bundle Audit Analyzer is enabled.
580      *
581      * @return if the Bundle Audit Analyzer is enabled.
582      */
583     public Boolean isBundleAuditAnalyzerEnabled() {
584         return bundleAuditAnalyzerEnabled;
585     }
586 
587     /**
588      * Sets if the Bundle Audit Analyzer is enabled.
589      *
590      * @param bundleAuditAnalyzerEnabled whether or not the analyzer should be
591      * enabled
592      */
593     public void setBundleAuditAnalyzerEnabled(Boolean bundleAuditAnalyzerEnabled) {
594         this.bundleAuditAnalyzerEnabled = bundleAuditAnalyzerEnabled;
595     }
596 
597     /**
598      * Sets the path for the bundle-audit binary.
599      */
600     private String bundleAuditPath;
601 
602     /**
603      * Returns the path to the bundle audit executable.
604      *
605      * @return the path to the bundle audit executable
606      */
607     public String getBundleAuditPath() {
608         return bundleAuditPath;
609     }
610 
611     /**
612      * Sets the path to the bundle audit executable.
613      *
614      * @param bundleAuditPath the path to the bundle audit executable
615      */
616     public void setBundleAuditPath(String bundleAuditPath) {
617         this.bundleAuditPath = bundleAuditPath;
618     }
619     /**
620      * Whether or not the CocoaPods Analyzer is enabled.
621      */
622     private Boolean cocoapodsAnalyzerEnabled;
623 
624     /**
625      * Returns if the cocoapods analyyzer is enabled.
626      *
627      * @return if the cocoapods analyyzer is enabled
628      */
629     public boolean isCocoapodsAnalyzerEnabled() {
630         return cocoapodsAnalyzerEnabled;
631     }
632 
633     /**
634      * Sets whether or not the cocoapods analyzer is enabled.
635      *
636      * @param cocoapodsAnalyzerEnabled the state of the cocoapods analyzer
637      */
638     public void setCocoapodsAnalyzerEnabled(Boolean cocoapodsAnalyzerEnabled) {
639         this.cocoapodsAnalyzerEnabled = cocoapodsAnalyzerEnabled;
640     }
641 
642     /**
643      * Whether or not the Swift package Analyzer is enabled.
644      */
645     private Boolean swiftPackageManagerAnalyzerEnabled;
646 
647     /**
648      * Returns whether or not the Swift package Analyzer is enabled.
649      *
650      * @return whether or not the Swift package Analyzer is enabled
651      */
652     public Boolean isSwiftPackageManagerAnalyzerEnabled() {
653         return swiftPackageManagerAnalyzerEnabled;
654     }
655 
656     /**
657      * Sets the enabled state of the swift package manager analyzer.
658      *
659      * @param swiftPackageManagerAnalyzerEnabled the enabled state of the swift
660      * package manager
661      */
662     public void setSwiftPackageManagerAnalyzerEnabled(Boolean swiftPackageManagerAnalyzerEnabled) {
663         this.swiftPackageManagerAnalyzerEnabled = swiftPackageManagerAnalyzerEnabled;
664     }
665 //end changes
666 
667     /**
668      * Whether or not the openssl analyzer is enabled.
669      */
670     private Boolean opensslAnalyzerEnabled;
671 
672     /**
673      * Get the value of opensslAnalyzerEnabled.
674      *
675      * @return the value of opensslAnalyzerEnabled
676      */
677     public Boolean isOpensslAnalyzerEnabled() {
678         return opensslAnalyzerEnabled;
679     }
680 
681     /**
682      * Set the value of opensslAnalyzerEnabled.
683      *
684      * @param opensslAnalyzerEnabled new value of opensslAnalyzerEnabled
685      */
686     public void setOpensslAnalyzerEnabled(Boolean opensslAnalyzerEnabled) {
687         this.opensslAnalyzerEnabled = opensslAnalyzerEnabled;
688     }
689     /**
690      * Whether or not the Node.js Analyzer is enabled.
691      */
692     private Boolean nodeAnalyzerEnabled;
693 
694     /**
695      * Get the value of nodeAnalyzerEnabled.
696      *
697      * @return the value of nodeAnalyzerEnabled
698      */
699     public Boolean isNodeAnalyzerEnabled() {
700         return nodeAnalyzerEnabled;
701     }
702 
703     /**
704      * Set the value of nodeAnalyzerEnabled.
705      *
706      * @param nodeAnalyzerEnabled new value of nodeAnalyzerEnabled
707      */
708     public void setNodeAnalyzerEnabled(Boolean nodeAnalyzerEnabled) {
709         this.nodeAnalyzerEnabled = nodeAnalyzerEnabled;
710     }
711     /**
712      * Whether the ruby gemspec analyzer should be enabled.
713      */
714     private Boolean rubygemsAnalyzerEnabled;
715 
716     /**
717      * Get the value of rubygemsAnalyzerEnabled.
718      *
719      * @return the value of rubygemsAnalyzerEnabled
720      */
721     public Boolean isRubygemsAnalyzerEnabled() {
722         return rubygemsAnalyzerEnabled;
723     }
724 
725     /**
726      * Set the value of rubygemsAnalyzerEnabled.
727      *
728      * @param rubygemsAnalyzerEnabled new value of rubygemsAnalyzerEnabled
729      */
730     public void setRubygemsAnalyzerEnabled(Boolean rubygemsAnalyzerEnabled) {
731         this.rubygemsAnalyzerEnabled = rubygemsAnalyzerEnabled;
732     }
733     /**
734      * Whether the python package analyzer should be enabled.
735      */
736     private Boolean pyPackageAnalyzerEnabled;
737 
738     /**
739      * Get the value of pyPackageAnalyzerEnabled.
740      *
741      * @return the value of pyPackageAnalyzerEnabled
742      */
743     public Boolean isPyPackageAnalyzerEnabled() {
744         return pyPackageAnalyzerEnabled;
745     }
746 
747     /**
748      * Set the value of pyPackageAnalyzerEnabled.
749      *
750      * @param pyPackageAnalyzerEnabled new value of pyPackageAnalyzerEnabled
751      */
752     public void setPyPackageAnalyzerEnabled(Boolean pyPackageAnalyzerEnabled) {
753         this.pyPackageAnalyzerEnabled = pyPackageAnalyzerEnabled;
754     }
755 
756     /**
757      * Whether the python distribution analyzer should be enabled.
758      */
759     private Boolean pyDistributionAnalyzerEnabled;
760 
761     /**
762      * Get the value of pyDistributionAnalyzerEnabled.
763      *
764      * @return the value of pyDistributionAnalyzerEnabled
765      */
766     public Boolean isPyDistributionAnalyzerEnabled() {
767         return pyDistributionAnalyzerEnabled;
768     }
769 
770     /**
771      * Set the value of pyDistributionAnalyzerEnabled.
772      *
773      * @param pyDistributionAnalyzerEnabled new value of
774      * pyDistributionAnalyzerEnabled
775      */
776     public void setPyDistributionAnalyzerEnabled(Boolean pyDistributionAnalyzerEnabled) {
777         this.pyDistributionAnalyzerEnabled = pyDistributionAnalyzerEnabled;
778     }
779 
780     /**
781      * Whether or not the central analyzer is enabled.
782      */
783     private Boolean centralAnalyzerEnabled;
784 
785     /**
786      * Get the value of centralAnalyzerEnabled.
787      *
788      * @return the value of centralAnalyzerEnabled
789      */
790     public Boolean isCentralAnalyzerEnabled() {
791         return centralAnalyzerEnabled;
792     }
793 
794     /**
795      * Set the value of centralAnalyzerEnabled.
796      *
797      * @param centralAnalyzerEnabled new value of centralAnalyzerEnabled
798      */
799     public void setCentralAnalyzerEnabled(Boolean centralAnalyzerEnabled) {
800         this.centralAnalyzerEnabled = centralAnalyzerEnabled;
801     }
802 
803     /**
804      * Whether or not the nexus analyzer is enabled.
805      */
806     private Boolean nexusAnalyzerEnabled;
807 
808     /**
809      * Get the value of nexusAnalyzerEnabled.
810      *
811      * @return the value of nexusAnalyzerEnabled
812      */
813     public Boolean isNexusAnalyzerEnabled() {
814         return nexusAnalyzerEnabled;
815     }
816 
817     /**
818      * Set the value of nexusAnalyzerEnabled.
819      *
820      * @param nexusAnalyzerEnabled new value of nexusAnalyzerEnabled
821      */
822     public void setNexusAnalyzerEnabled(Boolean nexusAnalyzerEnabled) {
823         this.nexusAnalyzerEnabled = nexusAnalyzerEnabled;
824     }
825 
826     /**
827      * The URL of a Nexus server's REST API end point
828      * (http://domain/nexus/service/local).
829      */
830     private String nexusUrl;
831 
832     /**
833      * Get the value of nexusUrl.
834      *
835      * @return the value of nexusUrl
836      */
837     public String getNexusUrl() {
838         return nexusUrl;
839     }
840 
841     /**
842      * Set the value of nexusUrl.
843      *
844      * @param nexusUrl new value of nexusUrl
845      */
846     public void setNexusUrl(String nexusUrl) {
847         this.nexusUrl = nexusUrl;
848     }
849     /**
850      * Whether or not the defined proxy should be used when connecting to Nexus.
851      */
852     private Boolean nexusUsesProxy;
853 
854     /**
855      * Get the value of nexusUsesProxy.
856      *
857      * @return the value of nexusUsesProxy
858      */
859     public Boolean isNexusUsesProxy() {
860         return nexusUsesProxy;
861     }
862 
863     /**
864      * Set the value of nexusUsesProxy.
865      *
866      * @param nexusUsesProxy new value of nexusUsesProxy
867      */
868     public void setNexusUsesProxy(Boolean nexusUsesProxy) {
869         this.nexusUsesProxy = nexusUsesProxy;
870     }
871 
872     /**
873      * Additional ZIP File extensions to add analyze. This should be a
874      * comma-separated list of file extensions to treat like ZIP files.
875      */
876     private String zipExtensions;
877 
878     /**
879      * Get the value of zipExtensions.
880      *
881      * @return the value of zipExtensions
882      */
883     public String getZipExtensions() {
884         return zipExtensions;
885     }
886 
887     /**
888      * Set the value of zipExtensions.
889      *
890      * @param zipExtensions new value of zipExtensions
891      */
892     public void setZipExtensions(String zipExtensions) {
893         this.zipExtensions = zipExtensions;
894     }
895 
896     /**
897      * The path to Mono for .NET assembly analysis on non-windows systems.
898      */
899     private String pathToMono;
900 
901     /**
902      * Get the value of pathToMono.
903      *
904      * @return the value of pathToMono
905      */
906     public String getPathToMono() {
907         return pathToMono;
908     }
909 
910     /**
911      * Set the value of pathToMono.
912      *
913      * @param pathToMono new value of pathToMono
914      */
915     public void setPathToMono(String pathToMono) {
916         this.pathToMono = pathToMono;
917     }
918 
919     @Override
920     public void execute() throws BuildException {
921         dealWithReferences();
922         validateConfiguration();
923         populateSettings();
924         Engine engine = null;
925         try {
926             engine = new Engine(Check.class.getClassLoader());
927             if (isUpdateOnly()) {
928                 log("Deprecated 'UpdateOnly' property set; please use the UpdateTask instead", Project.MSG_WARN);
929                 try {
930                     engine.doUpdates();
931                 } catch (UpdateException ex) {
932                     if (this.isFailOnError()) {
933                         throw new BuildException(ex);
934                     }
935                     log(ex.getMessage(), Project.MSG_ERR);
936                 }
937             } else {
938                 for (Resource resource : path) {
939                     final FileProvider provider = resource.as(FileProvider.class);
940                     if (provider != null) {
941                         final File file = provider.getFile();
942                         if (file != null && file.exists()) {
943                             engine.scan(file);
944                         }
945                     }
946                 }
947 
948                 try {
949                     engine.analyzeDependencies();
950                 } catch (ExceptionCollection ex) {
951                     if (this.isFailOnError()) {
952                         throw new BuildException(ex);
953                     }
954                 }
955                 DatabaseProperties prop = null;
956                 CveDB cve = null;
957                 try {
958                     cve = new CveDB();
959                     cve.open();
960                     prop = cve.getDatabaseProperties();
961                 } catch (DatabaseException ex) {
962                     log("Unable to retrieve DB Properties", ex, Project.MSG_DEBUG);
963                 } finally {
964                     if (cve != null) {
965                         cve.close();
966                     }
967                 }
968                 final ReportGenerator reporter = new ReportGenerator(getProjectName(), engine.getDependencies(), engine.getAnalyzers(), prop);
969                 reporter.generateReports(reportOutputDirectory, reportFormat);
970 
971                 if (this.failBuildOnCVSS <= 10) {
972                     checkForFailure(engine.getDependencies());
973                 }
974                 if (this.showSummary) {
975                     showSummary(engine.getDependencies());
976                 }
977             }
978         } catch (DatabaseException ex) {
979             final String msg = "Unable to connect to the dependency-check database; analysis has stopped";
980             if (this.isFailOnError()) {
981                 throw new BuildException(msg, ex);
982             }
983             log(msg, ex, Project.MSG_ERR);
984         } catch (ReportException ex) {
985             final String msg = "Unable to generate the dependency-check report";
986             if (this.isFailOnError()) {
987                 throw new BuildException(msg, ex);
988             }
989             log(msg, ex, Project.MSG_ERR);
990         } finally {
991             Settings.cleanup(true);
992             if (engine != null) {
993                 engine.cleanup();
994             }
995         }
996     }
997 
998     /**
999      * Validate the configuration to ensure the parameters have been properly
1000      * configured/initialized.
1001      *
1002      * @throws BuildException if the task was not configured correctly.
1003      */
1004     private void validateConfiguration() throws BuildException {
1005         if (path == null) {
1006             throw new BuildException("No project dependencies have been defined to analyze.");
1007         }
1008         if (failBuildOnCVSS < 0 || failBuildOnCVSS > 11) {
1009             throw new BuildException("Invalid configuration, failBuildOnCVSS must be between 0 and 11.");
1010         }
1011     }
1012 
1013     /**
1014      * Takes the properties supplied and updates the dependency-check settings.
1015      * Additionally, this sets the system properties required to change the
1016      * proxy server, port, and connection timeout.
1017      *
1018      * @throws BuildException thrown when an invalid setting is configured.
1019      */
1020     @Override
1021     protected void populateSettings() throws BuildException {
1022         super.populateSettings();
1023         Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate);
1024         Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
1025         Settings.setStringIfNotEmpty(Settings.KEYS.HINTS_FILE, hintsFile);
1026         Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental);
1027         Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled);
1028         Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, pyDistributionAnalyzerEnabled);
1029         Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, pyPackageAnalyzerEnabled);
1030         Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, rubygemsAnalyzerEnabled);
1031         Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, opensslAnalyzerEnabled);
1032         Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CMAKE_ENABLED, cmakeAnalyzerEnabled);
1033         Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED, swiftPackageManagerAnalyzerEnabled);
1034         Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COCOAPODS_ENABLED, cocoapodsAnalyzerEnabled);
1035         Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED, bundleAuditAnalyzerEnabled);
1036         Settings.setStringIfNotNull(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH, bundleAuditPath);
1037         Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, autoconfAnalyzerEnabled);
1038         Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, composerAnalyzerEnabled);
1039         Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, nodeAnalyzerEnabled);
1040         Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled);
1041         Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled);
1042         Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled);
1043         Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled);
1044         Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled);
1045         Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
1046         Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy);
1047         Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions);
1048         Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
1049     }
1050 
1051     /**
1052      * Checks to see if a vulnerability has been identified with a CVSS score
1053      * that is above the threshold set in the configuration.
1054      *
1055      * @param dependencies the list of dependency objects
1056      * @throws BuildException thrown if a CVSS score is found that is higher
1057      * then the threshold set
1058      */
1059     private void checkForFailure(List<Dependency> dependencies) throws BuildException {
1060         final StringBuilder ids = new StringBuilder();
1061         for (Dependency d : dependencies) {
1062             for (Vulnerability v : d.getVulnerabilities()) {
1063                 if (v.getCvssScore() >= failBuildOnCVSS) {
1064                     if (ids.length() == 0) {
1065                         ids.append(v.getName());
1066                     } else {
1067                         ids.append(", ").append(v.getName());
1068                     }
1069                 }
1070             }
1071         }
1072         if (ids.length() > 0) {
1073             final String msg = String.format("%n%nDependency-Check Failure:%n"
1074                     + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n"
1075                     + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString());
1076             throw new BuildException(msg);
1077         }
1078     }
1079 
1080     /**
1081      * Generates a warning message listing a summary of dependencies and their
1082      * associated CPE and CVE entries.
1083      *
1084      * @param dependencies a list of dependency objects
1085      */
1086     private void showSummary(List<Dependency> dependencies) {
1087         final StringBuilder summary = new StringBuilder();
1088         for (Dependency d : dependencies) {
1089             boolean firstEntry = true;
1090             final StringBuilder ids = new StringBuilder();
1091             for (Vulnerability v : d.getVulnerabilities()) {
1092                 if (firstEntry) {
1093                     firstEntry = false;
1094                 } else {
1095                     ids.append(", ");
1096                 }
1097                 ids.append(v.getName());
1098             }
1099             if (ids.length() > 0) {
1100                 summary.append(d.getFileName()).append(" (");
1101                 firstEntry = true;
1102                 for (Identifier id : d.getIdentifiers()) {
1103                     if (firstEntry) {
1104                         firstEntry = false;
1105                     } else {
1106                         summary.append(", ");
1107                     }
1108                     summary.append(id.getValue());
1109                 }
1110                 summary.append(") : ").append(ids).append(NEW_LINE);
1111             }
1112         }
1113         if (summary.length() > 0) {
1114             final String msg = String.format("%n%n"
1115                     + "One or more dependencies were identified with known vulnerabilities:%n%n%s"
1116                     + "%n%nSee the dependency-check report for more details.%n%n", summary.toString());
1117             log(msg, Project.MSG_WARN);
1118         }
1119     }
1120 
1121     /**
1122      * An enumeration of supported report formats: "ALL", "HTML", "XML", "VULN",
1123      * etc..
1124      */
1125     public static class ReportFormats extends EnumeratedAttribute {
1126 
1127         /**
1128          * Returns the list of values for the report format.
1129          *
1130          * @return the list of values for the report format
1131          */
1132         @Override
1133         public String[] getValues() {
1134             int i = 0;
1135             final Format[] formats = Format.values();
1136             final String[] values = new String[formats.length];
1137             for (Format format : formats) {
1138                 values[i++] = format.name();
1139             }
1140             return values;
1141         }
1142     }
1143 }