diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/DependencyCheckMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/DependencyCheckMojo.java deleted file mode 100644 index 50c3ba2bb..000000000 --- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/DependencyCheckMojo.java +++ /dev/null @@ -1,950 +0,0 @@ -/* - * This file is part of dependency-check-maven. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (c) 2013 Jeremy Long. All Rights Reserved. - */ -package org.owasp.dependencycheck.maven; - -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.OutputStream; -import java.util.List; -import java.util.Locale; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.apache.maven.artifact.Artifact; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugin.MojoFailureException; -import org.apache.maven.plugins.annotations.LifecyclePhase; -import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.Parameter; -import org.apache.maven.plugins.annotations.ResolutionScope; -import org.apache.maven.project.MavenProject; -import org.apache.maven.reporting.MavenReport; -import org.apache.maven.reporting.MavenReportException; -import org.apache.maven.settings.Proxy; -import org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer; -import org.owasp.dependencycheck.analyzer.exception.AnalysisException; -import org.owasp.dependencycheck.data.nexus.MavenArtifact; -import org.owasp.dependencycheck.data.nvdcve.DatabaseException; -import org.owasp.dependencycheck.dependency.Confidence; -import org.owasp.dependencycheck.dependency.Dependency; -import org.owasp.dependencycheck.dependency.Identifier; -import org.owasp.dependencycheck.dependency.Vulnerability; -import org.owasp.dependencycheck.utils.LogUtils; -import org.owasp.dependencycheck.utils.Settings; - -/** - * Maven Plugin that checks project dependencies to see if they have any known published vulnerabilities. - * - * @author Jeremy Long - */ -@Mojo( - name = "check", - defaultPhase = LifecyclePhase.COMPILE, - threadSafe = true, - requiresDependencyResolution = ResolutionScope.RUNTIME_PLUS_SYSTEM, - requiresOnline = true -) -public class DependencyCheckMojo extends ReportAggregationMojo { - - // - /** - * Logger field reference. - */ - private static final Logger LOGGER = Logger.getLogger(DependencyCheckMojo.class.getName()); - /** - * The properties file location. - */ - private static final String PROPERTIES_FILE = "mojo.properties"; - /** - * Name of the logging properties file. - */ - private static final String LOG_PROPERTIES_FILE = "log.properties"; - /** - * System specific new line character. - */ - private static final String NEW_LINE = System.getProperty("line.separator", "\n").intern(); - /** - * The dependency-check engine used to scan the project. - */ - private Engine engine = null; - // - - // - /** - * The path to the verbose log. - */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "logFile", defaultValue = "") - private String logFile = null; - /** - * The output directory. This generally maps to "target". - */ - @Parameter(defaultValue = "${project.build.directory}", required = true) - private File outputDirectory; - /** - * Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 - * which means since the CVSS scores are 0-10, by default the build will never fail. - */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "failBuildOnCVSS", defaultValue = "11", required = true) - private float failBuildOnCVSS = 11; - /** - * Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to - * false. Default is true. - */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "autoupdate", defaultValue = "true", required = true) - private boolean autoUpdate = true; - /** - * The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this - * within the Site plug-in unless the externalReport is set to true. Default is HTML. - */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "format", defaultValue = "HTML", required = true) - private String format = "HTML"; - /** - * The Maven settings. - */ - @Parameter(property = "mavenSettings", defaultValue = "${settings}", required = false) - private org.apache.maven.settings.Settings mavenSettings; - - /** - * The maven settings proxy id. - */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "mavenSettingsProxyId", required = false) - private String mavenSettingsProxyId; - - /** - * The Connection Timeout. - */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "connectionTimeout", defaultValue = "", required = false) - private String connectionTimeout = null; - /** - * The path to the suppression file. - */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "suppressionFile", defaultValue = "", required = false) - private String suppressionFile = null; - /** - * Flag indicating whether or not to show a summary in the output. - */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "showSummary", defaultValue = "true", required = false) - private boolean showSummary = true; - - /** - * Whether or not the Jar Analyzer is enabled. - */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "jarAnalyzerEnabled", defaultValue = "true", required = false) - private boolean jarAnalyzerEnabled = true; - - /** - * Whether or not the Archive Analyzer is enabled. - */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "archiveAnalyzerEnabled", defaultValue = "true", required = false) - private boolean archiveAnalyzerEnabled = true; - - /** - * Whether or not the .NET Assembly Analyzer is enabled. - */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "assemblyAnalyzerEnabled", defaultValue = "true", required = false) - private boolean assemblyAnalyzerEnabled = true; - - /** - * Whether or not the .NET Nuspec Analyzer is enabled. - */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "nuspecAnalyzerEnabled", defaultValue = "true", required = false) - private boolean nuspecAnalyzerEnabled = true; - - /** - * Whether or not the Nexus Analyzer is enabled. - */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "nexusAnalyzerEnabled", defaultValue = "true", required = false) - private boolean nexusAnalyzerEnabled = true; - /** - * Whether or not the Nexus Analyzer is enabled. - */ - @Parameter(property = "nexusUrl", defaultValue = "", required = false) - private String nexusUrl; - /** - * Whether or not the configured proxy is used to connect to Nexus. - */ - @Parameter(property = "nexusUsesProxy", defaultValue = "true", required = false) - private boolean nexusUsesProxy = true; - /** - * The database connection string. - */ - @Parameter(property = "connectionString", defaultValue = "", required = false) - private String connectionString; - /** - * The database driver name. An example would be org.h2.Driver. - */ - @Parameter(property = "databaseDriverName", defaultValue = "", required = false) - private String databaseDriverName; - /** - * The path to the database driver if it is not on the class path. - */ - @Parameter(property = "databaseDriverPath", defaultValue = "", required = false) - private String databaseDriverPath; - /** - * The database user name. - */ - @Parameter(property = "databaseUser", defaultValue = "", required = false) - private String databaseUser; - /** - * The password to use when connecting to the database. - */ - @Parameter(property = "databasePassword", defaultValue = "", required = false) - private String databasePassword; - /** - * A comma-separated list of file extensions to add to analysis next to jar, zip, .... - */ - @Parameter(property = "zipExtensions", required = false) - private String zipExtensions; - /** - * Skip Analysis for Test Scope Dependencies. - */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "skipTestScope", defaultValue = "true", required = false) - private boolean skipTestScope = true; - /** - * Skip Analysis for Runtime Scope Dependencies. - */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "skipRuntimeScope", defaultValue = "false", required = false) - private boolean skipRuntimeScope = false; - /** - * Skip Analysis for Provided Scope Dependencies. - */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "skipProvidedScope", defaultValue = "false", required = false) - private boolean skipProvidedScope = false; - /** - * The data directory, hold DC SQL DB. - */ - @Parameter(property = "dataDirectory", defaultValue = "", required = false) - private String dataDirectory; - /** - * Data Mirror URL for CVE 1.2. - */ - @Parameter(property = "cveUrl12Modified", defaultValue = "", required = false) - private String cveUrl12Modified; - /** - * Data Mirror URL for CVE 2.0. - */ - @Parameter(property = "cveUrl20Modified", defaultValue = "", required = false) - private String cveUrl20Modified; - /** - * Base Data Mirror URL for CVE 1.2. - */ - @Parameter(property = "cveUrl12Base", defaultValue = "", required = false) - private String cveUrl12Base; - /** - * Data Mirror URL for CVE 2.0. - */ - @Parameter(property = "cveUrl20Base", defaultValue = "", required = false) - private String cveUrl20Base; - - /** - * The path to mono for .NET Assembly analysis on non-windows systems. - */ - @Parameter(property = "pathToMono", defaultValue = "", required = false) - private String pathToMono; - - /** - * The Proxy URL. - * - * @deprecated Please use mavenSettings instead - */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "proxyUrl", defaultValue = "", required = false) - @Deprecated - private String proxyUrl = null; - /** - * Sets whether or not the external report format should be used. - * - * @deprecated the internal report is no longer supported - */ - @SuppressWarnings("CanBeFinal") - @Parameter(property = "externalReport") - @Deprecated - private String externalReport = null; - - // - /** - * Executes the Dependency-Check on the dependent libraries. - * - * @return the Engine used to scan the dependencies. - * @throws DatabaseException thrown if there is an exception connecting to the database - */ - private Engine executeDependencyCheck() throws DatabaseException { - return executeDependencyCheck(getProject()); - } - - /** - * Executes the Dependency-Check on the dependent libraries. - * - * @param project the project to run dependency-check on - * @return the Engine used to scan the dependencies. - * @throws DatabaseException thrown if there is an exception connecting to the database - */ - private Engine executeDependencyCheck(MavenProject project) throws DatabaseException { - final Engine localEngine; - if (engine == null) { - localEngine = initializeEngine(project); - } else { - localEngine = engine; - } - - final Set artifacts = project.getArtifacts(); - for (Artifact a : artifacts) { - if (excludeFromScan(a)) { - continue; - } - final List deps = localEngine.scan(a.getFile().getAbsoluteFile()); - if (deps != null) { - if (deps.size() == 1) { - final Dependency d = deps.get(0); - if (d != null) { - final MavenArtifact ma = new MavenArtifact(a.getGroupId(), a.getArtifactId(), a.getVersion()); - d.addAsEvidence("pom", ma, Confidence.HIGHEST); - } - } else { - final String msg = String.format("More then 1 dependency was identified in first pass scan of '%s:%s:%s'", - a.getGroupId(), a.getArtifactId(), a.getVersion()); - LOGGER.info(msg); - } - } - } - localEngine.analyzeDependencies(); - - return localEngine; - } - - /** - * Initializes a new Engine that can be used for scanning. - * - * @param project the current MavenProject - * @return a newly instantiated Engine - * @throws DatabaseException thrown if there is a database exception - */ - private Engine initializeEngine(MavenProject project) throws DatabaseException { - populateSettings(); - final Engine localEngine = new Engine(project); - return localEngine; - } - - /** - * Tests is the artifact should be included in the scan (i.e. is the dependency in a scope that is being scanned). - * - * @param a the Artifact to test - * @return true if the artifact is in an excluded scope; otherwise false - */ - private boolean excludeFromScan(Artifact a) { - if (skipTestScope && Artifact.SCOPE_TEST.equals(a.getScope())) { - return true; - } - if (skipProvidedScope && Artifact.SCOPE_PROVIDED.equals(a.getScope())) { - return true; - } - if (skipRuntimeScope && !Artifact.SCOPE_RUNTIME.equals(a.getScope())) { - return true; - } - return false; - } - - // - /** - * Takes the properties supplied and updates the dependency-check settings. Additionally, this sets the system - * properties required to change the proxy url, port, and connection timeout. - */ - private void populateSettings() { - Settings.initialize(); - InputStream mojoProperties = null; - try { - mojoProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE); - Settings.mergeProperties(mojoProperties); - } catch (IOException ex) { - LOGGER.log(Level.WARNING, "Unable to load the dependency-check ant task.properties file."); - LOGGER.log(Level.FINE, null, ex); - } finally { - if (mojoProperties != null) { - try { - mojoProperties.close(); - } catch (IOException ex) { - LOGGER.log(Level.FINEST, null, ex); - } - } - } - - Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate); - if (externalReport != null) { - LOGGER.warning("The 'externalReport' option was set; this configuration option has been removed. " - + "Please update the dependency-check-maven plugin's configuration"); - } - - if (proxyUrl != null && !proxyUrl.isEmpty()) { - LOGGER.warning("Deprecated configuration detected, proxyUrl will be ignored; use the maven settings " + "to configure the proxy instead"); - } - final Proxy proxy = getMavenProxy(); - if (proxy != null) { - Settings.setString(Settings.KEYS.PROXY_SERVER, proxy.getHost()); - Settings.setString(Settings.KEYS.PROXY_PORT, Integer.toString(proxy.getPort())); - final String userName = proxy.getUsername(); - final String password = proxy.getPassword(); - if (userName != null) { - Settings.setString(Settings.KEYS.PROXY_USERNAME, userName); - } - if (password != null) { - Settings.setString(Settings.KEYS.PROXY_PASSWORD, password); - } - - } - - if (connectionTimeout != null && !connectionTimeout.isEmpty()) { - Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout); - } - if (suppressionFile != null && !suppressionFile.isEmpty()) { - Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile); - } - - //File Type Analyzer Settings - //JAR ANALYZER - Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled); - //NUSPEC ANALYZER - Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled); - //NEXUS ANALYZER - Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled); - if (nexusUrl != null && !nexusUrl.isEmpty()) { - Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl); - } - Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY, nexusUsesProxy); - //ARCHIVE ANALYZER - Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled); - if (zipExtensions != null && !zipExtensions.isEmpty()) { - Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions); - } - //ASSEMBLY ANALYZER - Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled); - if (pathToMono != null && !pathToMono.isEmpty()) { - Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono); - } - - //Database configuration - if (databaseDriverName != null && !databaseDriverName.isEmpty()) { - Settings.setString(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName); - } - if (databaseDriverPath != null && !databaseDriverPath.isEmpty()) { - Settings.setString(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath); - } - if (connectionString != null && !connectionString.isEmpty()) { - Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString); - } - if (databaseUser != null && !databaseUser.isEmpty()) { - Settings.setString(Settings.KEYS.DB_USER, databaseUser); - } - if (databasePassword != null && !databasePassword.isEmpty()) { - Settings.setString(Settings.KEYS.DB_PASSWORD, databasePassword); - } - // Data Directory - if (dataDirectory != null && !dataDirectory.isEmpty()) { - Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory); - } - - // Scope Exclusion - Settings.setBoolean(Settings.KEYS.SKIP_TEST_SCOPE, skipTestScope); - Settings.setBoolean(Settings.KEYS.SKIP_RUNTIME_SCOPE, skipRuntimeScope); - Settings.setBoolean(Settings.KEYS.SKIP_PROVIDED_SCOPE, skipProvidedScope); - - // CVE Data Mirroring - if (cveUrl12Modified != null && !cveUrl12Modified.isEmpty()) { - Settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified); - } - if (cveUrl20Modified != null && !cveUrl20Modified.isEmpty()) { - Settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified); - } - if (cveUrl12Base != null && !cveUrl12Base.isEmpty()) { - Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base); - } - if (cveUrl20Base != null && !cveUrl20Base.isEmpty()) { - Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base); - } - } - - /** - * Returns the maven proxy. - * - * @return the maven proxy - */ - private Proxy getMavenProxy() { - if (mavenSettings != null) { - final List proxies = mavenSettings.getProxies(); - if (proxies != null && proxies.size() > 0) { - if (mavenSettingsProxyId != null) { - for (Proxy proxy : proxies) { - if (mavenSettingsProxyId.equalsIgnoreCase(proxy.getId())) { - return proxy; - } - } - } else if (proxies.size() == 1) { - return proxies.get(0); - } else { - LOGGER.warning("Multiple proxy defentiions exist in the Maven settings. In the dependency-check " - + "configuration set the maveSettingsProxyId so that the correct proxy will be used."); - throw new IllegalStateException("Ambiguous proxy definition"); - } - } - } - return null; - } - - // - /** - * Initialize the mojo. - */ - @Override - protected void initialize() { - final InputStream in = DependencyCheckMojo.class.getClassLoader().getResourceAsStream(LOG_PROPERTIES_FILE); - LogUtils.prepareLogger(in, logFile); - } - - /** - * Executes the dependency-check and generates the report. - * - * @throws MojoExecutionException if a maven exception occurs - * @throws MojoFailureException thrown if a CVSS score is found that is higher then the configured level - */ - @Override - protected void performExecute() throws MojoExecutionException, MojoFailureException { - try { - engine = executeDependencyCheck(); - ReportingUtil.generateExternalReports(engine, outputDirectory, getProject().getName(), format); - if (this.showSummary) { - showSummary(engine.getDependencies()); - } - if (this.failBuildOnCVSS <= 10) { - checkForFailure(engine.getDependencies()); - } - } catch (DatabaseException ex) { - LOGGER.log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped"); - LOGGER.log(Level.FINE, "", ex); - } - } - - @Override - protected void postExecute() throws MojoExecutionException, MojoFailureException { - try { - super.postExecute(); - } finally { - cleanupEngine(); - } - } - - @Override - protected void postGenerate() throws MavenReportException { - try { - super.postGenerate(); - } finally { - cleanupEngine(); - } - } - - /** - * Calls engine.cleanup() to release resources. - */ - private void cleanupEngine() { - if (engine != null) { - engine.cleanup(); - engine = null; - } - Settings.cleanup(true); - } - - /** - * Generates the Dependency-Check Site Report. - * - * @param locale the locale to use when generating the report - * @throws MavenReportException if a maven report exception occurs - */ - @Override - protected void executeNonAggregateReport(Locale locale) throws MavenReportException { - final List deps = readDataFile(); - if (deps != null) { - try { - if (engine != null) { - engine = initializeEngine(getProject()); - } - engine.getDependencies().addAll(deps); - } catch (DatabaseException ex) { - final String msg = String.format("An unrecoverable exception with the dependency-check initialization occured while scanning %s", - getProject().getName()); - throw new MavenReportException(msg, ex); - } - } else { - try { - engine = executeDependencyCheck(); - } catch (DatabaseException ex) { - final String msg = String.format("An unrecoverable exception with the dependency-check scan occured while scanning %s", - getProject().getName()); - throw new MavenReportException(msg, ex); - } - } - ReportingUtil.generateExternalReports(engine, getReportOutputDirectory(), getProject().getName(), format); - } - - @Override - protected void executeAggregateReport(MavenProject project, Locale locale) throws MavenReportException { - List deps = readDataFile(project); - if (deps != null) { - try { - if (engine != null) { - engine = initializeEngine(project); - } - engine.getDependencies().addAll(deps); - } catch (DatabaseException ex) { - final String msg = String.format("An unrecoverable exception with the dependency-check initialization occured while scanning %s", - project.getName()); - throw new MavenReportException(msg, ex); - } - } else { - try { - engine = executeDependencyCheck(project); - } catch (DatabaseException ex) { - final String msg = String.format("An unrecoverable exception with the dependency-check scan occured while scanning %s", - project.getName()); - throw new MavenReportException(msg, ex); - } - } - for (MavenProject child : getAllChildren(project)) { - deps = readDataFile(child); - if (deps == null) { - final String msg = String.format("Unable to include information on %s in the dependency-check aggregate report", - child.getName()); - LOGGER.severe(msg); - } else { - engine.getDependencies().addAll(deps); - } - } - final DependencyBundlingAnalyzer bundler = new DependencyBundlingAnalyzer(); - try { - bundler.analyze(null, engine); - } catch (AnalysisException ex) { - LOGGER.log(Level.WARNING, "An error occured grouping the dependencies; duplicate entries may exist in the report", ex); - LOGGER.log(Level.FINE, "Bundling Exception", ex); - } - final File outputDir = getReportOutputDirectory(project); - if (outputDir != null) { - ReportingUtil.generateExternalReports(engine, outputDir, project.getName(), format); - } - } - - // - /** - * Returns the output name. - * - * @return the output name - */ - public String getOutputName() { - if ("HTML".equalsIgnoreCase(this.format) || "ALL".equalsIgnoreCase(this.format)) { - return "dependency-check-report"; - } else if ("XML".equalsIgnoreCase(this.format)) { - return "dependency-check-report.xml#"; - } else if ("VULN".equalsIgnoreCase(this.format)) { - return "dependency-check-vulnerability"; - } else { - LOGGER.log(Level.WARNING, "Unknown report format used during site generation."); - return "dependency-check-report"; - } - } - - /** - * Returns the category name. - * - * @return the category name - */ - public String getCategoryName() { - return MavenReport.CATEGORY_PROJECT_REPORTS; - } - - /** - * Returns the report name. - * - * @param locale the location - * @return the report name - */ - public String getName(Locale locale) { - return "dependency-check"; - } - - /** - * Gets the description of the Dependency-Check report to be displayed in the Maven Generated Reports page. - * - * @param locale The Locale to get the description for - * @return the description - */ - public String getDescription(Locale locale) { - return "A report providing details on any published " - + "vulnerabilities within project dependencies. This report is a best effort but may contain " - + "false positives and false negatives."; - } - - /** - * Returns whether or not a report can be generated. - * - * @return true if a report can be generated; otherwise false - */ - public boolean canGenerateReport() { - if (canGenerateAggregateReport() || (isAggregate() && isMultiModule())) { - return true; - } - if (canGenerateNonAggregateReport()) { - return true; - } else { - final String msg; - if (getProject().getArtifacts().size() > 0) { - msg = "No project dependencies exist in the included scope - dependency-check:check is unable to generate a report."; - } else { - msg = "No project dependencies exist - dependency-check:check is unable to generate a report."; - } - LOGGER.warning(msg); - } - - return false; - } - - /** - * Returns whether or not a non-aggregate report can be generated. - * - * @return true if a non-aggregate report can be generated; otherwise false - */ - @Override - protected boolean canGenerateNonAggregateReport() { - boolean ability = false; - for (Artifact a : getProject().getArtifacts()) { - if (!excludeFromScan(a)) { - ability = true; - break; - } - } - return ability; - } - - /** - * Returns whether or not an aggregate report can be generated. - * - * @return true if an aggregate report can be generated; otherwise false - */ - @Override - protected boolean canGenerateAggregateReport() { - return isAggregate() && isLastProject(); - } - - // - // - /** - * Checks to see if a vulnerability has been identified with a CVSS score that is above the threshold set in the - * configuration. - * - * @param dependencies the list of dependency objects - * @throws MojoFailureException thrown if a CVSS score is found that is higher then the threshold set - */ - private void checkForFailure(List dependencies) throws MojoFailureException { - final StringBuilder ids = new StringBuilder(); - for (Dependency d : dependencies) { - boolean addName = true; - for (Vulnerability v : d.getVulnerabilities()) { - if (v.getCvssScore() >= failBuildOnCVSS) { - if (addName) { - addName = false; - ids.append(NEW_LINE).append(d.getFileName()).append(": "); - ids.append(v.getName()); - } else { - ids.append(", ").append(v.getName()); - } - } - } - } - if (ids.length() > 0) { - final String msg = String.format("%n%nDependency-Check Failure:%n" - + "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n" - + "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString()); - throw new MojoFailureException(msg); - } - } - - /** - * Generates a warning message listing a summary of dependencies and their associated CPE and CVE entries. - * - * @param dependencies a list of dependency objects - */ - private void showSummary(List dependencies) { - final StringBuilder summary = new StringBuilder(); - for (Dependency d : dependencies) { - boolean firstEntry = true; - final StringBuilder ids = new StringBuilder(); - for (Vulnerability v : d.getVulnerabilities()) { - if (firstEntry) { - firstEntry = false; - } else { - ids.append(", "); - } - ids.append(v.getName()); - } - if (ids.length() > 0) { - summary.append(d.getFileName()).append(" ("); - firstEntry = true; - for (Identifier id : d.getIdentifiers()) { - if (firstEntry) { - firstEntry = false; - } else { - summary.append(", "); - } - summary.append(id.getValue()); - } - summary.append(") : ").append(ids).append(NEW_LINE); - } - } - if (summary.length() > 0) { - final String msg = String.format("%n%n" + "One or more dependencies were identified with known vulnerabilities:%n%n%s" - + "%n%nSee the dependency-check report for more details.%n%n", summary.toString()); - LOGGER.log(Level.WARNING, msg); - } - } - - // - // - /** - * Writes the scan data to disk. This is used to serialize the scan data between the "check" and "aggregate" phase. - * - * @return the File object referencing the data file that was written - */ - @Override - protected File writeDataFile() { - File file = null; - if (engine != null && getProject().getContextValue(this.getDataFileContextKey()) == null) { - file = new File(getProject().getBuild().getDirectory(), getDataFileName()); - OutputStream os = null; - OutputStream bos = null; - ObjectOutputStream out = null; - try { - os = new FileOutputStream(file); - bos = new BufferedOutputStream(os); - out = new ObjectOutputStream(bos); - out.writeObject(engine.getDependencies()); - out.flush(); - - //call reset to prevent resource leaks per - //https://www.securecoding.cert.org/confluence/display/java/SER10-J.+Avoid+memory+and+resource+leaks+during+serialization - out.reset(); - - } catch (IOException ex) { - LOGGER.log(Level.WARNING, "Unable to create data file used for report aggregation; " - + "if report aggregation is being used the results may be incomplete."); - LOGGER.log(Level.FINE, ex.getMessage(), ex); - } finally { - if (out != null) { - try { - out.close(); - } catch (IOException ex) { - LOGGER.log(Level.FINEST, "ignore", ex); - } - } - if (bos != null) { - try { - bos.close(); - } catch (IOException ex) { - LOGGER.log(Level.FINEST, "ignore", ex); - } - } - if (os != null) { - try { - os.close(); - } catch (IOException ex) { - LOGGER.log(Level.FINEST, "ignore", ex); - } - } - } - } - return file; - } - - /** - * Reads the serialized scan data from disk. This is used to serialize the scan data between the "check" and - * "aggregate" phase. - * - * @return a Engine object populated with dependencies if the serialized data file exists; otherwise - * null is returned - */ - protected List readDataFile() { - return readDataFile(getProject()); - } - - /** - * Reads the serialized scan data from disk. This is used to serialize the scan data between the "check" and - * "aggregate" phase. - * - * @param project the Maven project to read the data file from - * @return a Engine object populated with dependencies if the serialized data file exists; otherwise - * null is returned - */ - protected List readDataFile(MavenProject project) { - final Object oPath = project.getContextValue(this.getDataFileContextKey()); - if (oPath == null) { - return null; - } - List ret = null; - final String path = (String) oPath; - ObjectInputStream ois = null; - try { - ois = new ObjectInputStream(new FileInputStream(path)); - ret = (List) ois.readObject(); - } catch (FileNotFoundException ex) { - //TODO fix logging - LOGGER.log(Level.SEVERE, null, ex); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, null, ex); - } catch (ClassNotFoundException ex) { - LOGGER.log(Level.SEVERE, null, ex); - } finally { - if (ois != null) { - try { - ois.close(); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, null, ex); - } - } - } - return ret; - } - // - -} diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/ReportAggregationMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/ReportAggregationMojo.java deleted file mode 100644 index c931f7586..000000000 --- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/ReportAggregationMojo.java +++ /dev/null @@ -1,469 +0,0 @@ -/* - * This file is part of dependency-check-maven. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (c) 2014 Jeremy Long. All Rights Reserved. - */ -package org.owasp.dependencycheck.maven; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.logging.Logger; -import org.apache.maven.doxia.sink.Sink; -import org.apache.maven.plugin.AbstractMojo; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugin.MojoFailureException; -import org.apache.maven.plugins.annotations.Component; -import org.apache.maven.plugins.annotations.Parameter; -import org.apache.maven.project.MavenProject; -import org.apache.maven.reporting.MavenReport; -import org.apache.maven.reporting.MavenReportException; - -/** - *

- * This is an abstract reporting mojo that enables report aggregation. Some of the code in the this class was copied - * from the CoberturaReportMojo (http://mojo.codehaus.org/cobertura-maven-plugin/, version 2.6). The authors of the - * CoberturaReportMojo were Will Gwaltney and - * Joakim Erdfelt. There working example of how to do report aggregation was - * invaluable.

- *

- * An important point about using this abstract class is that it is intended for one to write some form of serialized - * data (via the {@link org.owasp.dependencycheck.maven.ReportAggregationMojo#writeDataFile() }; note that the - * writeDataFile() function is called automatically after either {@link org.owasp.dependencycheck.maven.ReportAggregationMojo#executeNonAggregateReport(org.apache.maven.doxia.sink.Sink, - * org.apache.maven.doxia.sink.SinkFactory, java.util.Locale) - * } or {@link org.owasp.dependencycheck.maven.ReportAggregationMojo#executeAggregateReport(org.apache.maven.doxia.sink.Sink, - * org.apache.maven.doxia.sink.SinkFactory, java.util.Locale) - * } are called. When executeAggregateReport() is implemented, one can call {@link org.owasp.dependencycheck.maven.ReportAggregationMojo#getChildDataFiles() - * } to obtain a list of the data files to aggregate.

- * - * - * @author Jeremy Long - */ -public abstract class ReportAggregationMojo extends AbstractMojo implements MavenReport { - - /** - * The Maven Project Object. - */ - @Component - private MavenProject project; - - /** - * Logger field reference. - */ - private static final Logger LOGGER = Logger.getLogger(ReportAggregationMojo.class.getName()); - - /** - * List of Maven project of the current build - */ - @Parameter(readonly = true, required = true, property = "reactorProjects") - private List reactorProjects; - - /** - * Generate aggregate reports in multi-module projects. - */ - @Parameter(property = "aggregate", defaultValue = "false") - private boolean aggregate; - - /** - * Sets whether or not the external report format should be used. - */ - @Parameter(property = "metaFileName", defaultValue = "dependency-check.ser", required = true) - private String dataFileName; - /** - * Specifies the destination directory for the generated Dependency-Check report. This generally maps to - * "target/site". - */ - @Parameter(property = "reportOutputDirectory", defaultValue = "${project.reporting.outputDirectory}", required = true) - private File reportOutputDirectory; - - /** - * Sets the Reporting output directory. - * - * @param directory the output directory - */ - @Override - public void setReportOutputDirectory(File directory) { - reportOutputDirectory = directory; - } - - /** - * Returns the output directory. - * - * @return the output directory - */ - @Override - public File getReportOutputDirectory() { - return reportOutputDirectory; - } - - /** - * Returns the output directory for the given project. - * - * @param project the Maven project to get the output directory for - * @return the output directory for the given project - */ - public File getReportOutputDirectory(MavenProject project) { - final Object o = project.getContextValue(getOutputDirectoryContextKey()); - if (o != null && o instanceof File) { - return (File) o; - } - return null; - } - - /** - * Returns whether this is an external report. This method always returns true. - * - * @return true - */ - @Override - public final boolean isExternalReport() { - return true; - } - - /** - * Initializes the mojo. - */ - protected abstract void initialize(); - - /** - * The collection of child projects. - */ - private final Map> projectChildren = new HashMap>(); - - /** - * Called before execute; allows for any setup that is needed. If this is overridden you must call - * super.preExecute(). - * - * @throws MojoExecutionException thrown if there is an issue executing the mojo - * @throws MojoFailureException thrown if there is an issue executing the mojo - */ - protected void preExecute() throws MojoExecutionException, MojoFailureException { - buildAggregateInfo(); - } - - /** - * Called when the mojo is being executed. - * - * @throws MojoExecutionException thrown if there is an issue executing the mojo - * @throws MojoFailureException thrown if there is an issue executing the mojo - */ - protected abstract void performExecute() throws MojoExecutionException, MojoFailureException; - - /** - * Runs after the mojo has executed. This implementation will call writeDataFile(). As such, it is - * important that if this method is overriden that super.postExecute() is called. - * - * @throws MojoExecutionException thrown if there is an issue executing the mojo - * @throws MojoFailureException thrown if there is an issue executing the mojo - */ - protected void postExecute() throws MojoExecutionException, MojoFailureException { - final File written = writeDataFile(); - if (written != null) { - LOGGER.fine(String.format("Data file written to %s", written.getAbsolutePath())); - project.setContextValue(getDataFileContextKey(), written.getAbsolutePath()); - } - } - - /** - * Returns the key used to store the path to the data file that is saved by writeDataFile(). This key - * is used in the MavenProject.(set|get)ContextValue. - * - * @return the key used to store the path to the data file - */ - protected String getDataFileContextKey() { - return "dependency-check-path-" + this.getDataFileName(); - } - - /** - * Returns the key used to store the path to the output directory. When generating the report in the - * executeAggregateReport() the output directory should be obtained by using this key. - * - * @return the key used to store the path to the output directory - */ - protected String getOutputDirectoryContextKey() { - return "dependency-output-dir-" + this.getDataFileName(); - } - - /** - * Is called by Maven to execute the mojo. - * - * @throws MojoExecutionException thrown if there is an issue executing the mojo - * @throws MojoFailureException thrown if there is an issue executing the mojo - */ - public final void execute() throws MojoExecutionException, MojoFailureException { - try { - initialize(); - preExecute(); - performExecute(); - } finally { - postExecute(); - } - } - - /** - * Runs prior to the site report generation. - * - * @throws MavenReportException if a maven report exception occurs - */ - protected void preGenerate() throws MavenReportException { - buildAggregateInfo(); - - project.setContextValue(getOutputDirectoryContextKey(), getReportOutputDirectory()); - } - - /** - * Executes after the site report has been generated. - * - * @throws MavenReportException if a maven report exception occurs - */ - protected void postGenerate() throws MavenReportException { - final File written = writeDataFile(); - if (written != null) { - project.setContextValue(getDataFileContextKey(), written.getAbsolutePath()); - } - } - - /** - * Generates the non aggregate report. - * - * @param locale the locale to use when generating the report - * @throws MavenReportException if a maven report exception occurs - */ - protected abstract void executeNonAggregateReport(Locale locale) throws MavenReportException; - - /** - * Generates the aggregate Site Report. - * - * @param project the maven project used to generate the aggregate report - * @param locale the locale to use when generating the report - * @throws MavenReportException if a maven report exception occurs - */ - protected abstract void executeAggregateReport(MavenProject project, Locale locale) throws MavenReportException; - - /** - * Generates the Dependency-Check Site Report. - * - * @param sink the sink to write the report to - * @param locale the locale to use when generating the report - * @throws MavenReportException if a maven report exception occurs - * @deprecated use {@link #generate(org.apache.maven.doxia.sink.Sink, java.util.Locale) instead. - */ - @Deprecated - public final void generate(@SuppressWarnings("deprecation") org.codehaus.doxia.sink.Sink sink, Locale locale) throws MavenReportException { - generate((Sink) sink, locale); - } - - /** - * Generates the Dependency-Check Site Report. - * - * @param sink the sink to write the report to - * @param locale the locale to use when generating the report - * @throws MavenReportException if a maven report exception occurs - */ - public final void generate(Sink sink, Locale locale) throws MavenReportException { - try { - initialize(); - preGenerate(); - if (canGenerateNonAggregateReport()) { - executeNonAggregateReport(locale); - } - } finally { - postGenerate(); - } - if (canGenerateAggregateReport()) { - for (MavenProject proj : reactorProjects) { - if (!isMultiModule(proj)) { - continue; - } - executeAggregateReport(proj, locale); - } - } - } - - /** - * Returns whether or not the mojo can generate a non-aggregate report for this project. - * - * @return true if a non-aggregate report can be generated, otherwise false - */ - protected abstract boolean canGenerateNonAggregateReport(); - - /** - * Returns whether or not we can generate any aggregate reports at this time. - * - * @return true if an aggregate report can be generated, otherwise false - */ - protected abstract boolean canGenerateAggregateReport(); - - /** - * Returns the name of the data file that contains the serialized data. - * - * @return the name of the data file that contains the serialized data - */ - protected String getDataFileName() { - return dataFileName; - } - - /** - * Writes the data file to disk in the target directory. - * - * @return the File object referencing the data file that was written - */ - protected abstract File writeDataFile(); - - /** - * Collects the information needed for building aggregate reports. - */ - private void buildAggregateInfo() { - // build parent-child map - for (MavenProject proj : reactorProjects) { - Set depList = projectChildren.get(proj.getParent()); - if (depList == null) { - depList = new HashSet(); - projectChildren.put(proj.getParent(), depList); - } - depList.add(proj); - } - } - - /** - * Returns a list containing all the recursive, non-pom children of the given project, never null. - * - * @return a list of child projects - */ - protected List getAllChildren() { - return getAllChildren(project); - } - - /** - * Returns a list containing all the recursive, non-pom children of the given project, never null. - * - * @param parentProject the parent project to collect the child project references - * @return a list of child projects - */ - protected List getAllChildren(MavenProject parentProject) { - final Set children = projectChildren.get(parentProject); - if (children == null) { - return Collections.emptyList(); - } - - final List result = new ArrayList(); - for (MavenProject child : children) { - if (isMultiModule(child)) { - result.addAll(getAllChildren(child)); - } else { - result.add(child); - } - } - return result; - } - - /** - * Returns a list of data files that were produced by the direct children of the given MavenProject. - * - * @param project the Maven project to obtain the child data files from - * @return a list of the data files - */ - protected List getAllChildDataFiles(MavenProject project) { - final List children = getAllChildren(project); - return getDataFiles(children); - } - - /** - * Returns any existing output files from the given list of projects. - * - * @param projects the list of projects to obtain the output files from - * @return a list of output files - */ - protected List getDataFiles(List projects) { - final List files = new ArrayList(); - for (MavenProject proj : projects) { - final Object path = project.getContextValue(getDataFileContextKey()); - if (path == null) { - final String msg = String.format("Unable to aggregate data for '%s' - aggregate data file was not generated", - proj.getName()); - LOGGER.warning(msg); - } else { - final File outputFile = new File((String) path); - if (outputFile.exists()) { - files.add(outputFile); - } else { - if (!isMultiModule(project)) { - final String msg = String.format("Unable to aggregate data for '%s' - missing data file '%s'", - proj.getName(), outputFile.getPath()); - LOGGER.warning(msg); - } - } - } - } - return files; - } - - /** - * Test if the project has pom packaging - * - * @param mavenProject Project to test - * @return true if it has a pom packaging; otherwise false - */ - protected boolean isMultiModule(MavenProject mavenProject) { - return "pom".equals(mavenProject.getPackaging()); - } - - /** - * Test if the current project has pom packaging - * - * @return true if it has a pom packaging; otherwise false - */ - protected boolean isMultiModule() { - return isMultiModule(project); - } - - /** - * Check whether the current project is the last project in a multi-module build. If the maven build is not a - * multi-module project then this will always return true. - * - * @return true if the current project is the last project in a multi-module build; otherwise - * false - */ - protected boolean isLastProject() { - return project.equals(reactorProjects.get(reactorProjects.size() - 1)); - } - - /** - * Returns whether or not the mojo is configured to perform report aggregation. - * - * @return true if report aggregation is enabled; otherwise false - */ - public boolean isAggregate() { - return aggregate; - } - - /** - * Returns a reference to the current project. This method is used instead of auto-binding the project via component - * annotation in concrete implementations of this. If the child has a @Component MavenProject project; - * defined then the abstract class (i.e. this class) will not have access to the current project (just the way Maven - * works with the binding). - * - * @return returns a reference to the current project - */ - protected MavenProject getProject() { - return project; - } -} diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/ReportingUtil.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/ReportingUtil.java deleted file mode 100644 index e7a081fb9..000000000 --- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/ReportingUtil.java +++ /dev/null @@ -1,455 +0,0 @@ -/* - * This file is part of dependency-check-maven. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (c) 2014 Jeremy Long. All Rights Reserved. - */ -package org.owasp.dependencycheck.maven; - -import java.io.File; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.text.DateFormat; -import java.util.Date; -import java.util.List; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.apache.maven.doxia.sink.Sink; -import org.owasp.dependencycheck.data.nvdcve.CveDB; -import org.owasp.dependencycheck.data.nvdcve.DatabaseException; -import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties; -import org.owasp.dependencycheck.dependency.Dependency; -import org.owasp.dependencycheck.dependency.Evidence; -import org.owasp.dependencycheck.dependency.Identifier; -import org.owasp.dependencycheck.dependency.Reference; -import org.owasp.dependencycheck.dependency.Vulnerability; -import org.owasp.dependencycheck.dependency.VulnerableSoftware; -import org.owasp.dependencycheck.reporting.ReportGenerator; - -/** - * A utility class that encapsulates the report generation for dependency-check-maven. - * - * @author Jeremy Long - */ -final class ReportingUtil { - - /** - * Logger field reference. - */ - private static final Logger LOGGER = Logger.getLogger(ReportingUtil.class.getName()); - - /** - * Empty private constructor for this utility class. - */ - private ReportingUtil() { - } - - /** - * Generates the reports for a given dependency-check engine. - * - * @param engine a dependency-check engine - * @param outDirectory the directory to write the reports to - * @param projectName the name of the project that a report is being generated for - * @param format the format of the report to generate - */ - static void generateExternalReports(Engine engine, File outDirectory, String projectName, String format) { - DatabaseProperties prop = null; - CveDB cve = null; - try { - cve = new CveDB(); - cve.open(); - prop = cve.getDatabaseProperties(); - } catch (DatabaseException ex) { - LOGGER.log(Level.FINE, "Unable to retrieve DB Properties", ex); - } finally { - if (cve != null) { - cve.close(); - } - } - final ReportGenerator r = new ReportGenerator(projectName, engine.getDependencies(), engine.getAnalyzers(), prop); - try { - r.generateReports(outDirectory.getCanonicalPath(), format); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, - "Unexpected exception occurred during analysis; please see the verbose error log for more details."); - LOGGER.log(Level.FINE, null, ex); - } catch (Throwable ex) { - LOGGER.log(Level.SEVERE, - "Unexpected exception occurred during analysis; please see the verbose error log for more details."); - LOGGER.log(Level.FINE, null, ex); - } - } - - /** - * Generates a dependency-check report using the Maven Site format. - * - * @param engine the engine used to scan the dependencies - * @param sink the sink to write the data to - * @param projectName the name of the project - */ - static void generateMavenSiteReport(final Engine engine, Sink sink, String projectName) { - final List dependencies = engine.getDependencies(); - - writeSiteReportHeader(sink, projectName); - writeSiteReportTOC(sink, dependencies); - - int cnt = 0; - for (Dependency d : dependencies) { - writeSiteReportDependencyHeader(sink, d); - cnt = writeSiteReportDependencyEvidenceUsed(d, cnt, sink); - cnt = writeSiteReportDependencyRelatedDependencies(d, cnt, sink); - writeSiteReportDependencyIdentifiers(d, sink); - writeSiteReportDependencyVulnerabilities(d, sink, cnt); - } - sink.body_(); - } - - // - /** - * Writes the vulnerabilities to the site report. - * - * @param d the dependency - * @param sink the sink to write the data to - * @param collapsibleHeaderCount the collapsible header count - */ - private static void writeSiteReportDependencyVulnerabilities(Dependency d, Sink sink, int collapsibleHeaderCount) { - int cnt = collapsibleHeaderCount; - if (d.getVulnerabilities() != null && !d.getVulnerabilities().isEmpty()) { - for (Vulnerability v : d.getVulnerabilities()) { - - sink.paragraph(); - sink.bold(); - try { - sink.link("http://web.nvd.nist.gov/view/vuln/detail?vulnId=" + URLEncoder.encode(v.getName(), "US-ASCII")); - sink.text(v.getName()); - sink.link_(); - sink.bold_(); - } catch (UnsupportedEncodingException ex) { - sink.text(v.getName()); - sink.bold_(); - sink.lineBreak(); - sink.text("http://web.nvd.nist.gov/view/vuln/detail?vulnId=" + v.getName()); - } - sink.paragraph_(); - sink.paragraph(); - sink.text("Severity: "); - if (v.getCvssScore() < 4.0) { - sink.text("Low"); - } else { - if (v.getCvssScore() >= 7.0) { - sink.text("High"); - } else { - sink.text("Medium"); - } - } - sink.lineBreak(); - sink.text("CVSS Score: " + v.getCvssScore()); - if (v.getCwe() != null && !v.getCwe().isEmpty()) { - sink.lineBreak(); - sink.text("CWE: "); - sink.text(v.getCwe()); - } - sink.paragraph_(); - sink.paragraph(); - sink.text(v.getDescription()); - if (v.getReferences() != null && !v.getReferences().isEmpty()) { - sink.list(); - for (Reference ref : v.getReferences()) { - sink.listItem(); - sink.text(ref.getSource()); - sink.text(" - "); - sink.link(ref.getUrl()); - sink.text(ref.getName()); - sink.link_(); - sink.listItem_(); - } - sink.list_(); - } - sink.paragraph_(); - if (v.getVulnerableSoftware() != null && !v.getVulnerableSoftware().isEmpty()) { - sink.paragraph(); - - cnt += 1; - sink.rawText("Vulnerable Software [-]"); - sink.rawText("
"); - sink.list(); - for (VulnerableSoftware vs : v.getVulnerableSoftware()) { - sink.listItem(); - try { - sink.link("http://web.nvd.nist.gov/view/vuln/search-results?cpe=" + URLEncoder.encode(vs.getName(), "US-ASCII")); - sink.text(vs.getName()); - sink.link_(); - if (vs.hasPreviousVersion()) { - sink.text(" and all previous versions."); - } - } catch (UnsupportedEncodingException ex) { - sink.text(vs.getName()); - if (vs.hasPreviousVersion()) { - sink.text(" and all previous versions."); - } - sink.text(" (http://web.nvd.nist.gov/view/vuln/search-results?cpe=" + vs.getName() + ")"); - } - - sink.listItem_(); - } - sink.list_(); - sink.rawText("
"); - sink.paragraph_(); - } - } - } - } - - /** - * Writes the identifiers to the site report. - * - * @param d the dependency - * @param sink the sink to write the data to - */ - private static void writeSiteReportDependencyIdentifiers(Dependency d, Sink sink) { - if (d.getIdentifiers() != null && !d.getIdentifiers().isEmpty()) { - sink.sectionTitle4(); - sink.text("Identifiers"); - sink.sectionTitle4_(); - sink.list(); - for (Identifier i : d.getIdentifiers()) { - sink.listItem(); - sink.text(i.getType()); - sink.text(": "); - if (i.getUrl() != null && i.getUrl().length() > 0) { - sink.link(i.getUrl()); - sink.text(i.getValue()); - sink.link_(); - } else { - sink.text(i.getValue()); - } - if (i.getDescription() != null && i.getDescription().length() > 0) { - sink.lineBreak(); - sink.text(i.getDescription()); - } - sink.listItem_(); - } - sink.list_(); - } - } - - /** - * Writes the related dependencies to the site report. - * - * @param d the dependency - * @param sink the sink to write the data to - * @param collapsibleHeaderCount the collapsible header count - * @return the collapsible header count - */ - private static int writeSiteReportDependencyRelatedDependencies(Dependency d, int collapsibleHeaderCount, Sink sink) { - int cnt = collapsibleHeaderCount; - if (d.getRelatedDependencies() != null && !d.getRelatedDependencies().isEmpty()) { - cnt += 1; - sink.sectionTitle4(); - sink.rawText("Related Dependencies [+]"); - sink.sectionTitle4_(); - sink.rawText("
"); - sink.list(); - for (Dependency r : d.getRelatedDependencies()) { - sink.listItem(); - sink.text(r.getFileName()); - sink.list(); - writeListItem(sink, "File Path: " + r.getFilePath()); - writeListItem(sink, "SHA1: " + r.getSha1sum()); - writeListItem(sink, "MD5: " + r.getMd5sum()); - sink.list_(); - sink.listItem_(); - } - sink.list_(); - sink.rawText("
"); - } - return cnt; - } - - /** - * Writes the evidence used to the site report. - * - * @param d the dependency - * @param sink the sink to write the data to - * @param collapsibleHeaderCount the collapsible header count - * @return the collapsible header count - */ - private static int writeSiteReportDependencyEvidenceUsed(Dependency d, int collapsibleHeaderCount, Sink sink) { - int cnt = collapsibleHeaderCount; - final Set evidence = d.getEvidenceForDisplay(); - if (evidence != null && evidence.size() > 0) { - cnt += 1; - sink.sectionTitle4(); - sink.rawText("Evidence Collected [+]"); - sink.sectionTitle4_(); - sink.rawText("
"); - sink.table(); - sink.tableRow(); - writeTableHeaderCell(sink, "Source"); - writeTableHeaderCell(sink, "Name"); - writeTableHeaderCell(sink, "Value"); - sink.tableRow_(); - for (Evidence e : evidence) { - sink.tableRow(); - writeTableCell(sink, e.getSource()); - writeTableCell(sink, e.getName()); - writeTableCell(sink, e.getValue()); - sink.tableRow_(); - } - sink.table_(); - sink.rawText("
"); - } - return cnt; - } - - /** - * Writes the dependency header to the site report. - * - * @param d the dependency - * @param sink the sink to write the data to - */ - private static void writeSiteReportDependencyHeader(Sink sink, Dependency d) { - sink.sectionTitle2(); - sink.anchor("sha1" + d.getSha1sum()); - sink.text(d.getFileName()); - sink.anchor_(); - sink.sectionTitle2_(); - if (d.getDescription() != null && d.getDescription().length() > 0) { - sink.paragraph(); - sink.bold(); - sink.text("Description: "); - sink.bold_(); - sink.text(d.getDescription()); - sink.paragraph_(); - } - if (d.getLicense() != null && d.getLicense().length() > 0) { - sink.paragraph(); - sink.bold(); - sink.text("License: "); - sink.bold_(); - if (d.getLicense().startsWith("http://") && !d.getLicense().contains(" ")) { - sink.link(d.getLicense()); - sink.text(d.getLicense()); - sink.link_(); - } else { - sink.text(d.getLicense()); - } - sink.paragraph_(); - } - } - - /** - * Adds a list item to the site report. - * - * @param sink the sink to write the data to - * @param text the text to write - */ - private static void writeListItem(Sink sink, String text) { - sink.listItem(); - sink.text(text); - sink.listItem_(); - } - - /** - * Adds a table cell to the site report. - * - * @param sink the sink to write the data to - * @param text the text to write - */ - private static void writeTableCell(Sink sink, String text) { - sink.tableCell(); - sink.text(text); - sink.tableCell_(); - } - - /** - * Adds a table header cell to the site report. - * - * @param sink the sink to write the data to - * @param text the text to write - */ - private static void writeTableHeaderCell(Sink sink, String text) { - sink.tableHeaderCell(); - sink.text(text); - sink.tableHeaderCell_(); - } - - /** - * Writes the TOC for the site report. - * - * @param sink the sink to write the data to - * @param dependencies the dependencies that are being reported on - */ - private static void writeSiteReportTOC(Sink sink, final List dependencies) { - sink.list(); - for (Dependency d : dependencies) { - sink.listItem(); - sink.link("#sha1" + d.getSha1sum()); - sink.text(d.getFileName()); - sink.link_(); - if (!d.getVulnerabilities().isEmpty()) { - sink.rawText(" "); - } - if (!d.getRelatedDependencies().isEmpty()) { - sink.list(); - for (Dependency r : d.getRelatedDependencies()) { - writeListItem(sink, r.getFileName()); - } - sink.list_(); - } - sink.listItem_(); - } - sink.list_(); - } - - /** - * Writes the site report header. - * - * @param sink the sink to write the data to - * @param projectName the name of the project - */ - private static void writeSiteReportHeader(Sink sink, String projectName) { - sink.head(); - sink.title(); - sink.text("Dependency-Check Report: " + projectName); - sink.title_(); - sink.head_(); - sink.body(); - sink.rawText(""); - sink.section1(); - sink.sectionTitle1(); - sink.text("Project: " + projectName); - sink.sectionTitle1_(); - sink.date(); - final Date now = new Date(); - sink.text(DateFormat.getDateTimeInstance().format(now)); - sink.date_(); - sink.section1_(); - } - //
- -}