1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.owasp.dependencycheck.maven;
19
20 import java.io.BufferedOutputStream;
21 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.FileNotFoundException;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.ObjectInputStream;
28 import java.io.ObjectOutputStream;
29 import java.io.OutputStream;
30 import java.util.List;
31 import java.util.Locale;
32 import java.util.logging.Level;
33 import java.util.logging.Logger;
34 import org.apache.maven.artifact.Artifact;
35 import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
36 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
37 import org.apache.maven.artifact.repository.ArtifactRepository;
38 import org.apache.maven.artifact.versioning.ArtifactVersion;
39 import org.apache.maven.doxia.sink.Sink;
40 import org.apache.maven.plugin.AbstractMojo;
41 import org.apache.maven.plugin.MojoExecutionException;
42 import org.apache.maven.plugin.MojoFailureException;
43 import org.apache.maven.plugins.annotations.Component;
44 import org.apache.maven.plugins.annotations.Parameter;
45 import org.apache.maven.project.MavenProject;
46 import org.apache.maven.reporting.MavenReport;
47 import org.apache.maven.reporting.MavenReportException;
48 import org.apache.maven.settings.Proxy;
49 import org.owasp.dependencycheck.data.nexus.MavenArtifact;
50 import org.owasp.dependencycheck.data.nvdcve.CveDB;
51 import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
52 import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
53 import org.owasp.dependencycheck.dependency.Confidence;
54 import org.owasp.dependencycheck.dependency.Dependency;
55 import org.owasp.dependencycheck.dependency.Identifier;
56 import org.owasp.dependencycheck.dependency.Vulnerability;
57 import org.owasp.dependencycheck.reporting.ReportGenerator;
58 import org.owasp.dependencycheck.utils.DependencyVersion;
59 import org.owasp.dependencycheck.utils.LogUtils;
60 import org.owasp.dependencycheck.utils.Settings;
61
62
63
64
65
66 public abstract class BaseDependencyCheckMojo extends AbstractMojo implements MavenReport {
67
68
69
70
71
72 private static final Logger LOGGER = Logger.getLogger(BaseDependencyCheckMojo.class.getName());
73
74
75
76 private static final String PROPERTIES_FILE = "mojo.properties";
77
78
79
80 private static final String LOG_PROPERTIES_FILE = "log.properties";
81
82
83
84 private static final String NEW_LINE = System.getProperty("line.separator", "\n").intern();
85
86
87
88 @Parameter(property = "metaFileName", defaultValue = "dependency-check.ser", required = true)
89 private String dataFileName;
90
91
92
93
94
95
96 @Component
97 private MavenProject project;
98
99
100
101 @Component
102 private ArtifactMetadataSource metadataSource;
103
104
105
106 @Parameter(property = "localRepository", readonly = true)
107 private ArtifactRepository localRepository;
108
109
110
111 @Parameter(property = "project.remoteArtifactRepositories", readonly = true)
112 private List<ArtifactRepository> remoteRepositories;
113
114
115
116 @Parameter(readonly = true, required = true, property = "reactorProjects")
117 private List<MavenProject> reactorProjects;
118
119
120
121 @SuppressWarnings("CanBeFinal")
122 @Parameter(property = "logFile", defaultValue = "")
123 private String logFile = null;
124
125
126
127
128
129 @Parameter(defaultValue = "${project.build.directory}", required = true)
130 private File outputDirectory;
131
132
133
134
135 @Parameter(property = "project.reporting.outputDirectory", required = true)
136 private File reportOutputDirectory;
137
138
139
140
141 @SuppressWarnings("CanBeFinal")
142 @Parameter(property = "failBuildOnCVSS", defaultValue = "11", required = true)
143 private float failBuildOnCVSS = 11;
144
145
146
147
148 @SuppressWarnings("CanBeFinal")
149 @Parameter(property = "autoupdate", defaultValue = "true", required = true)
150 private boolean autoUpdate = true;
151
152
153
154
155
156 @Parameter(property = "aggregate", defaultValue = "false")
157 @Deprecated
158 private boolean aggregate;
159
160
161
162
163 @SuppressWarnings("CanBeFinal")
164 @Parameter(property = "format", defaultValue = "HTML", required = true)
165 private String format = "HTML";
166
167
168
169 @Parameter(property = "mavenSettings", defaultValue = "${settings}", required = false)
170 private org.apache.maven.settings.Settings mavenSettings;
171
172
173
174
175 @SuppressWarnings("CanBeFinal")
176 @Parameter(property = "mavenSettingsProxyId", required = false)
177 private String mavenSettingsProxyId;
178
179
180
181
182 @SuppressWarnings("CanBeFinal")
183 @Parameter(property = "connectionTimeout", defaultValue = "", required = false)
184 private String connectionTimeout = null;
185
186
187
188 @SuppressWarnings("CanBeFinal")
189 @Parameter(property = "suppressionFile", defaultValue = "", required = false)
190 private String suppressionFile = null;
191
192
193
194 @SuppressWarnings("CanBeFinal")
195 @Parameter(property = "showSummary", defaultValue = "true", required = false)
196 private boolean showSummary = true;
197
198
199
200
201 @SuppressWarnings("CanBeFinal")
202 @Parameter(property = "jarAnalyzerEnabled", defaultValue = "true", required = false)
203 private boolean jarAnalyzerEnabled = true;
204
205
206
207
208 @SuppressWarnings("CanBeFinal")
209 @Parameter(property = "archiveAnalyzerEnabled", defaultValue = "true", required = false)
210 private boolean archiveAnalyzerEnabled = true;
211
212
213
214
215 @SuppressWarnings("CanBeFinal")
216 @Parameter(property = "assemblyAnalyzerEnabled", defaultValue = "true", required = false)
217 private boolean assemblyAnalyzerEnabled = true;
218
219
220
221
222 @SuppressWarnings("CanBeFinal")
223 @Parameter(property = "nuspecAnalyzerEnabled", defaultValue = "true", required = false)
224 private boolean nuspecAnalyzerEnabled = true;
225
226
227
228
229 @SuppressWarnings("CanBeFinal")
230 @Parameter(property = "centralAnalyzerEnabled", defaultValue = "true", required = false)
231 private boolean centralAnalyzerEnabled = true;
232
233
234
235
236 @SuppressWarnings("CanBeFinal")
237 @Parameter(property = "nexusAnalyzerEnabled", defaultValue = "true", required = false)
238 private boolean nexusAnalyzerEnabled = true;
239
240
241
242
243 @Parameter(property = "nexusUrl", defaultValue = "", required = false)
244 private String nexusUrl;
245
246
247
248 @Parameter(property = "nexusUsesProxy", defaultValue = "true", required = false)
249 private boolean nexusUsesProxy = true;
250
251
252
253 @Parameter(property = "connectionString", defaultValue = "", required = false)
254 private String connectionString;
255
256
257
258 @Parameter(property = "databaseDriverName", defaultValue = "", required = false)
259 private String databaseDriverName;
260
261
262
263 @Parameter(property = "databaseDriverPath", defaultValue = "", required = false)
264 private String databaseDriverPath;
265
266
267
268 @Parameter(property = "databaseUser", defaultValue = "", required = false)
269 private String databaseUser;
270
271
272
273 @Parameter(property = "databasePassword", defaultValue = "", required = false)
274 private String databasePassword;
275
276
277
278 @Parameter(property = "zipExtensions", required = false)
279 private String zipExtensions;
280
281
282
283 @SuppressWarnings("CanBeFinal")
284 @Parameter(property = "skipTestScope", defaultValue = "true", required = false)
285 private boolean skipTestScope = true;
286
287
288
289 @SuppressWarnings("CanBeFinal")
290 @Parameter(property = "skipRuntimeScope", defaultValue = "false", required = false)
291 private boolean skipRuntimeScope = false;
292
293
294
295 @SuppressWarnings("CanBeFinal")
296 @Parameter(property = "skipProvidedScope", defaultValue = "false", required = false)
297 private boolean skipProvidedScope = false;
298
299
300
301 @Parameter(property = "dataDirectory", defaultValue = "", required = false)
302 private String dataDirectory;
303
304
305
306 @Parameter(property = "cveUrl12Modified", defaultValue = "", required = false)
307 private String cveUrl12Modified;
308
309
310
311 @Parameter(property = "cveUrl20Modified", defaultValue = "", required = false)
312 private String cveUrl20Modified;
313
314
315
316 @Parameter(property = "cveUrl12Base", defaultValue = "", required = false)
317 private String cveUrl12Base;
318
319
320
321 @Parameter(property = "cveUrl20Base", defaultValue = "", required = false)
322 private String cveUrl20Base;
323
324
325
326
327 @Parameter(property = "pathToMono", defaultValue = "", required = false)
328 private String pathToMono;
329
330
331
332
333
334
335 @SuppressWarnings("CanBeFinal")
336 @Parameter(property = "proxyUrl", defaultValue = "", required = false)
337 @Deprecated
338 private String proxyUrl = null;
339
340
341
342
343
344 @SuppressWarnings("CanBeFinal")
345 @Parameter(property = "externalReport")
346 @Deprecated
347 private String externalReport = null;
348
349
350
351
352
353
354
355
356
357 @Override
358 public void execute() throws MojoExecutionException, MojoFailureException {
359 validateAggregate();
360 project.setContextValue(getOutputDirectoryContextKey(), this.outputDirectory);
361 runCheck();
362 }
363
364
365
366
367
368
369
370 private void validateAggregate() throws MojoExecutionException {
371 if (aggregate) {
372 final String msg = "Aggregate configuration detected - as of dependency-check 1.2.8 this no longer supported. "
373 + "Please use the aggregate goal instead.";
374 throw new MojoExecutionException(msg);
375 }
376 }
377
378
379
380
381
382
383
384
385
386 @Deprecated
387 public final void generate(@SuppressWarnings("deprecation") org.codehaus.doxia.sink.Sink sink, Locale locale) throws MavenReportException {
388 generate((Sink) sink, locale);
389 }
390
391
392
393
394
395
396
397
398 public void generate(Sink sink, Locale locale) throws MavenReportException {
399 try {
400 validateAggregate();
401 } catch (MojoExecutionException ex) {
402 throw new MavenReportException(ex.getMessage());
403 }
404 project.setContextValue(getOutputDirectoryContextKey(), getReportOutputDirectory());
405 try {
406 runCheck();
407 } catch (MojoExecutionException ex) {
408 throw new MavenReportException(ex.getMessage(), ex);
409 } catch (MojoFailureException ex) {
410 LOGGER.warning("Vulnerabilities were identifies that exceed the CVSS threshold for failing the build");
411 }
412 }
413
414
415
416
417
418
419
420 protected File getCorrectOutputDirectory() throws MojoExecutionException {
421 return getCorrectOutputDirectory(this.project);
422 }
423
424
425
426
427
428
429
430 protected File getCorrectOutputDirectory(MavenProject current) {
431 final Object obj = current.getContextValue(getOutputDirectoryContextKey());
432 if (obj != null && obj instanceof File) {
433 return (File) obj;
434 }
435 File target = new File(current.getBuild().getDirectory());
436 if (target.getParentFile() != null && "target".equals(target.getParentFile().getName())) {
437 target = target.getParentFile();
438 }
439 return target;
440 }
441
442
443
444
445
446
447
448 protected File getDataFile(MavenProject current) {
449 LOGGER.fine(String.format("Getting data filefor %s using key '%s'", current.getName(), getDataFileContextKey()));
450 final Object obj = current.getContextValue(getDataFileContextKey());
451 if (obj != null) {
452 if (obj instanceof File) {
453 return (File) obj;
454 }
455 } else {
456 LOGGER.fine("Context value not found");
457 }
458 return null;
459 }
460
461
462
463
464
465
466
467 protected void scanArtifacts(MavenProject project, Engine engine) {
468 for (Artifact a : project.getArtifacts()) {
469 if (excludeFromScan(a)) {
470 continue;
471 }
472 final List<Dependency> deps = engine.scan(a.getFile().getAbsoluteFile());
473 if (deps != null) {
474 if (deps.size() == 1) {
475 final Dependency d = deps.get(0);
476 if (d != null) {
477 final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion());
478 d.addAsEvidence("pom", ma, Confidence.HIGHEST);
479 d.addProjectReference(project.getName());
480 LOGGER.fine(String.format("Adding project reference %s on dependency %s", project.getName(),
481 d.getDisplayFileName()));
482 if (metadataSource != null) {
483 try {
484 final DependencyVersion currentVersion = new DependencyVersion(a.getVersion());
485 final List<ArtifactVersion> versions = metadataSource.retrieveAvailableVersions(a,
486 localRepository, remoteRepositories);
487 for (ArtifactVersion av : versions) {
488 final DependencyVersion newVersion = new DependencyVersion(av.toString());
489 if (currentVersion.compareTo(newVersion) < 0) {
490 d.addAvailableVersion(av.toString());
491 }
492 }
493 } catch (ArtifactMetadataRetrievalException ex) {
494 LOGGER.log(Level.WARNING,
495 "Unable to check for new versions of dependencies; see the log for more details.");
496 LOGGER.log(Level.FINE, null, ex);
497 } catch (Throwable t) {
498 LOGGER.log(Level.WARNING,
499 "Unexpected error occured checking for new versions; see the log for more details.");
500 LOGGER.log(Level.FINE, "", t);
501 }
502 }
503 }
504 } else {
505 final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s:%s:%s'",
506 a.getGroupId(), a.getArtifactId(), a.getVersion());
507 LOGGER.fine(msg);
508 }
509 }
510 }
511 }
512
513
514
515
516
517
518
519 public abstract void runCheck() throws MojoExecutionException, MojoFailureException;
520
521
522
523
524
525
526 @Override
527 public void setReportOutputDirectory(File directory) {
528 reportOutputDirectory = directory;
529 }
530
531
532
533
534
535
536 @Override
537 public File getReportOutputDirectory() {
538 return reportOutputDirectory;
539 }
540
541
542
543
544
545
546 public File getOutputDirectory() {
547 return outputDirectory;
548 }
549
550
551
552
553
554
555 @Override
556 public final boolean isExternalReport() {
557 return true;
558 }
559
560
561
562
563
564
565 public String getOutputName() {
566 if ("HTML".equalsIgnoreCase(this.format) || "ALL".equalsIgnoreCase(this.format)) {
567 return "dependency-check-report";
568 } else if ("XML".equalsIgnoreCase(this.format)) {
569 return "dependency-check-report.xml#";
570 } else if ("VULN".equalsIgnoreCase(this.format)) {
571 return "dependency-check-vulnerability";
572 } else {
573 LOGGER.log(Level.WARNING, "Unknown report format used during site generation.");
574 return "dependency-check-report";
575 }
576 }
577
578
579
580
581
582
583 public String getCategoryName() {
584 return MavenReport.CATEGORY_PROJECT_REPORTS;
585 }
586
587
588
589
590
591
592
593
594 protected Engine initializeEngine() throws DatabaseException {
595 final InputStream in = BaseDependencyCheckMojo.class
596 .getClassLoader().getResourceAsStream(LOG_PROPERTIES_FILE);
597 LogUtils.prepareLogger(in, logFile);
598
599 populateSettings();
600
601 return new Engine(this.project,
602 this.reactorProjects);
603 }
604
605
606
607
608
609 private void populateSettings() {
610 Settings.initialize();
611 InputStream mojoProperties = null;
612 try {
613 mojoProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
614 Settings.mergeProperties(mojoProperties);
615 } catch (IOException ex) {
616 LOGGER.log(Level.WARNING, "Unable to load the dependency-check ant task.properties file.");
617 LOGGER.log(Level.FINE, null, ex);
618 } finally {
619 if (mojoProperties != null) {
620 try {
621 mojoProperties.close();
622 } catch (IOException ex) {
623 LOGGER.log(Level.FINEST, null, ex);
624 }
625 }
626 }
627
628 Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
629 if (externalReport != null) {
630 LOGGER.warning("The 'externalReport' option was set; this configuration option has been removed. "
631 + "Please update the dependency-check-maven plugin's configuration");
632 }
633
634 if (proxyUrl != null && !proxyUrl.isEmpty()) {
635 LOGGER.warning("Deprecated configuration detected, proxyUrl will be ignored; use the maven settings " + "to configure the proxy instead");
636 }
637 final Proxy proxy = getMavenProxy();
638 if (proxy != null) {
639 Settings.setString(Settings.KEYS.PROXY_SERVER, proxy.getHost());
640 Settings.setString(Settings.KEYS.PROXY_PORT, Integer.toString(proxy.getPort()));
641 final String userName = proxy.getUsername();
642 final String password = proxy.getPassword();
643 if (userName != null) {
644 Settings.setString(Settings.KEYS.PROXY_USERNAME, userName);
645 }
646 if (password != null) {
647 Settings.setString(Settings.KEYS.PROXY_PASSWORD, password);
648 }
649
650 }
651
652 if (connectionTimeout != null && !connectionTimeout.isEmpty()) {
653 Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
654 }
655 if (suppressionFile != null && !suppressionFile.isEmpty()) {
656 Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
657 }
658
659
660
661 Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled);
662
663 Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled);
664
665 Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled);
666
667 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled);
668 if (nexusUrl != null && !nexusUrl.isEmpty()) {
669 Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
670 }
671 Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY, nexusUsesProxy);
672
673 Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled);
674 if (zipExtensions != null && !zipExtensions.isEmpty()) {
675 Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions);
676 }
677
678 Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled);
679 if (pathToMono != null && !pathToMono.isEmpty()) {
680 Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
681 }
682
683
684 if (databaseDriverName != null && !databaseDriverName.isEmpty()) {
685 Settings.setString(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
686 }
687 if (databaseDriverPath != null && !databaseDriverPath.isEmpty()) {
688 Settings.setString(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
689 }
690 if (connectionString != null && !connectionString.isEmpty()) {
691 Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
692 }
693 if (databaseUser != null && !databaseUser.isEmpty()) {
694 Settings.setString(Settings.KEYS.DB_USER, databaseUser);
695 }
696 if (databasePassword != null && !databasePassword.isEmpty()) {
697 Settings.setString(Settings.KEYS.DB_PASSWORD, databasePassword);
698 }
699
700 if (dataDirectory != null && !dataDirectory.isEmpty()) {
701 Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
702 }
703
704
705 Settings.setBoolean(Settings.KEYS.SKIP_TEST_SCOPE, skipTestScope);
706 Settings.setBoolean(Settings.KEYS.SKIP_RUNTIME_SCOPE, skipRuntimeScope);
707 Settings.setBoolean(Settings.KEYS.SKIP_PROVIDED_SCOPE, skipProvidedScope);
708
709
710 if (cveUrl12Modified != null && !cveUrl12Modified.isEmpty()) {
711 Settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified);
712 }
713 if (cveUrl20Modified != null && !cveUrl20Modified.isEmpty()) {
714 Settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified);
715 }
716 if (cveUrl12Base != null && !cveUrl12Base.isEmpty()) {
717 Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base);
718 }
719 if (cveUrl20Base != null && !cveUrl20Base.isEmpty()) {
720 Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base);
721 }
722 }
723
724
725
726
727
728
729 private Proxy getMavenProxy() {
730 if (mavenSettings != null) {
731 final List<Proxy> proxies = mavenSettings.getProxies();
732 if (proxies != null && !proxies.isEmpty()) {
733 if (mavenSettingsProxyId != null) {
734 for (Proxy proxy : proxies) {
735 if (mavenSettingsProxyId.equalsIgnoreCase(proxy.getId())) {
736 return proxy;
737 }
738 }
739 } else if (proxies.size() == 1) {
740 return proxies.get(0);
741 } else {
742 LOGGER.warning("Multiple proxy definitions exist in the Maven settings. In the dependency-check "
743 + "configuration set the mavenSettingsProxyId so that the correct proxy will be used.");
744 throw new IllegalStateException("Ambiguous proxy definition");
745 }
746 }
747 }
748 return null;
749 }
750
751
752
753
754
755
756
757 protected boolean excludeFromScan(Artifact a) {
758 if (skipTestScope && Artifact.SCOPE_TEST.equals(a.getScope())) {
759 return true;
760 }
761 if (skipProvidedScope && Artifact.SCOPE_PROVIDED.equals(a.getScope())) {
762 return true;
763 }
764 if (skipRuntimeScope && !Artifact.SCOPE_RUNTIME.equals(a.getScope())) {
765 return true;
766 }
767 return false;
768 }
769
770
771
772
773
774
775
776
777
778 protected MavenProject getProject() {
779 return project;
780 }
781
782
783
784
785
786
787 protected List<MavenProject> getReactorProjects() {
788 return reactorProjects;
789 }
790
791
792
793
794
795
796 protected String getFormat() {
797 return format;
798 }
799
800
801
802
803
804
805
806
807 protected void writeReports(Engine engine, MavenProject p, File outputDir) {
808 DatabaseProperties prop = null;
809 CveDB cve = null;
810 try {
811 cve = new CveDB();
812 cve.open();
813 prop = cve.getDatabaseProperties();
814 } catch (DatabaseException ex) {
815 LOGGER.log(Level.FINE, "Unable to retrieve DB Properties", ex);
816 } finally {
817 if (cve != null) {
818 cve.close();
819 }
820 }
821 final ReportGenerator r = new ReportGenerator(p.getName(), engine.getDependencies(), engine.getAnalyzers(), prop);
822 try {
823 r.generateReports(outputDir.getAbsolutePath(), format);
824 } catch (IOException ex) {
825 LOGGER.log(Level.SEVERE,
826 "Unexpected exception occurred during analysis; please see the verbose error log for more details.");
827 LOGGER.log(Level.FINE, null, ex);
828 } catch (Throwable ex) {
829 LOGGER.log(Level.SEVERE,
830 "Unexpected exception occurred during analysis; please see the verbose error log for more details.");
831 LOGGER.log(Level.FINE, null, ex);
832 }
833 }
834
835
836
837
838
839
840
841
842
843 protected void checkForFailure(List<Dependency> dependencies) throws MojoFailureException {
844 if (failBuildOnCVSS <= 10) {
845 final StringBuilder ids = new StringBuilder();
846 for (Dependency d : dependencies) {
847 boolean addName = true;
848 for (Vulnerability v : d.getVulnerabilities()) {
849 if (v.getCvssScore() >= failBuildOnCVSS) {
850 if (addName) {
851 addName = false;
852 ids.append(NEW_LINE).append(d.getFileName()).append(": ");
853 ids.append(v.getName());
854 } else {
855 ids.append(", ").append(v.getName());
856 }
857 }
858 }
859 }
860 if (ids.length() > 0) {
861 final String msg = String.format("%n%nDependency-Check Failure:%n"
862 + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n"
863 + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString());
864 throw new MojoFailureException(msg);
865 }
866 }
867 }
868
869
870
871
872
873
874
875 protected void showSummary(MavenProject mp, List<Dependency> dependencies) {
876 if (showSummary) {
877 final StringBuilder summary = new StringBuilder();
878 for (Dependency d : dependencies) {
879 boolean firstEntry = true;
880 final StringBuilder ids = new StringBuilder();
881 for (Vulnerability v : d.getVulnerabilities()) {
882 if (firstEntry) {
883 firstEntry = false;
884 } else {
885 ids.append(", ");
886 }
887 ids.append(v.getName());
888 }
889 if (ids.length() > 0) {
890 summary.append(d.getFileName()).append(" (");
891 firstEntry = true;
892 for (Identifier id : d.getIdentifiers()) {
893 if (firstEntry) {
894 firstEntry = false;
895 } else {
896 summary.append(", ");
897 }
898 summary.append(id.getValue());
899 }
900 summary.append(") : ").append(ids).append(NEW_LINE);
901 }
902 }
903 if (summary.length() > 0) {
904 final String msg = String.format("%n%n" + "One or more dependencies were identified with known vulnerabilities in %s:%n%n%s"
905 + "%n%nSee the dependency-check report for more details.%n%n", mp.getName(), summary.toString());
906 LOGGER.log(Level.WARNING, msg);
907 }
908 }
909 }
910
911
912
913
914
915
916
917
918
919 protected String getDataFileContextKey() {
920 return "dependency-check-path-" + dataFileName;
921 }
922
923
924
925
926
927
928
929 protected String getOutputDirectoryContextKey() {
930 return "dependency-output-dir-" + dataFileName;
931 }
932
933
934
935
936
937
938
939
940 protected void writeDataFile(MavenProject mp, File writeTo, List<Dependency> dependencies) {
941 File file;
942
943 if (mp.getContextValue(this.getDataFileContextKey()) == null) {
944 if (writeTo == null) {
945 file = new File(mp.getBuild().getDirectory());
946 file = new File(file, dataFileName);
947 } else {
948 file = new File(writeTo, dataFileName);
949 }
950 OutputStream os = null;
951 OutputStream bos = null;
952 ObjectOutputStream out = null;
953 try {
954 if (dependencies != null) {
955 os = new FileOutputStream(file);
956 bos = new BufferedOutputStream(os);
957 out = new ObjectOutputStream(bos);
958 out.writeObject(dependencies);
959 out.flush();
960
961
962
963 out.reset();
964 }
965 LOGGER.fine(String.format("Serialized data file written to '%s' for %s, referenced by key %s",
966 file.getAbsolutePath(), mp.getName(), this.getDataFileContextKey()));
967 mp.setContextValue(this.getDataFileContextKey(), file.getAbsolutePath());
968 } catch (IOException ex) {
969 LOGGER.log(Level.WARNING, "Unable to create data file used for report aggregation; "
970 + "if report aggregation is being used the results may be incomplete.");
971 LOGGER.log(Level.FINE, ex.getMessage(), ex);
972 } finally {
973 if (out != null) {
974 try {
975 out.close();
976 } catch (IOException ex) {
977 LOGGER.log(Level.FINEST, "ignore", ex);
978 }
979 }
980 if (bos != null) {
981 try {
982 bos.close();
983 } catch (IOException ex) {
984 LOGGER.log(Level.FINEST, "ignore", ex);
985 }
986 }
987 if (os != null) {
988 try {
989 os.close();
990 } catch (IOException ex) {
991 LOGGER.log(Level.FINEST, "ignore", ex);
992 }
993 }
994 }
995 }
996 }
997
998
999
1000
1001
1002
1003
1004
1005
1006 protected List<Dependency> readDataFile(MavenProject project) {
1007 final Object oPath = project.getContextValue(this.getDataFileContextKey());
1008 if (oPath == null) {
1009 return null;
1010 }
1011 List<Dependency> ret = null;
1012 final String path = (String) oPath;
1013 ObjectInputStream ois = null;
1014 try {
1015 ois = new ObjectInputStream(new FileInputStream(path));
1016 ret = (List<Dependency>) ois.readObject();
1017 } catch (FileNotFoundException ex) {
1018
1019 LOGGER.log(Level.SEVERE, null, ex);
1020 } catch (IOException ex) {
1021 LOGGER.log(Level.SEVERE, null, ex);
1022 } catch (ClassNotFoundException ex) {
1023 LOGGER.log(Level.SEVERE, null, ex);
1024 } finally {
1025 if (ois != null) {
1026 try {
1027 ois.close();
1028 } catch (IOException ex) {
1029 LOGGER.log(Level.SEVERE, null, ex);
1030 }
1031 }
1032 }
1033 return ret;
1034 }
1035
1036 }