diff --git a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java index 9761effd3..a7b3b4049 100644 --- a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java +++ b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java @@ -1015,7 +1015,7 @@ public class Check extends Update { * @throws BuildException if the task was not configured correctly. */ private void validateConfiguration() throws BuildException { - if (getPath() == null) { + if (path == null) { throw new BuildException("No project dependencies have been defined to analyze."); } if (failBuildOnCVSS < 0 || failBuildOnCVSS > 11) { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java index d102b752c..1d6cb2ab6 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java @@ -193,11 +193,9 @@ public class Engine implements FileFilter { * * @param dependencies the dependencies */ - public void setDependencies(List dependencies) { - synchronized (this.dependencies) { - this.dependencies.clear(); - this.dependencies.addAll(dependencies); - } + public synchronized void setDependencies(List dependencies) { + this.dependencies.clear(); + this.dependencies.addAll(dependencies); } /** @@ -612,6 +610,7 @@ public class Engine implements FileFilter { } } } catch (InterruptedException e) { + Thread.currentThread().interrupt(); throwFatalExceptionCollection("Analysis has been interrupted.", e, exceptions); } finally { executorService.shutdown(); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java index e161d7c22..be81cac89 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java @@ -138,6 +138,7 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer { try { rc = proc.waitFor(); } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); return; } if (rc == 3) { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.java index bf16a2e23..47fc8b015 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.java @@ -439,6 +439,10 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer { * between the two collections match; otherwise false */ private boolean isShadedJar(Dependency dependency, Dependency nextDependency) { + if (dependency == null || dependency.getFileName() == null + || nextDependency == null || nextDependency.getFileName() == null) { + return false; + } final String mainName = dependency.getFileName().toLowerCase(); final String nextName = nextDependency.getFileName().toLowerCase(); if (mainName.endsWith(".jar") && nextName.endsWith("pom.xml")) { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NspAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NspAnalyzer.java index 0cdf6fca6..5dfa705c1 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NspAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NspAnalyzer.java @@ -266,6 +266,7 @@ public class NspAnalyzer extends AbstractFileTypeAnalyzer { * * @param dependency the Dependency to update * @param jsonObject the jsonObject to parse + * @param depType the dependency type */ private void processPackage(Dependency dependency, JsonObject jsonObject, String depType) { for (int i = 0; i < jsonObject.size(); i++) { @@ -291,7 +292,7 @@ public class NspAnalyzer extends AbstractFileTypeAnalyzer { * dependency will not actually exist but needs to be unique (due to the use of Set in Dependency). * The use of related dependencies is a way to specify the actual software BOM in package.json. */ - Dependency nodeModule = new Dependency(new File(dependency.getActualFile() + "#" + entry.getKey()), true); + final Dependency nodeModule = new Dependency(new File(dependency.getActualFile() + "#" + entry.getKey()), true); nodeModule.setDisplayFileName(entry.getKey()); nodeModule.setIdentifiers(new HashSet<>(Arrays.asList(moduleName, moduleVersion, moduleDepType))); dependency.addRelatedDependency(nodeModule); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.java index e872dd050..ef4b6eea7 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.java @@ -173,6 +173,7 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer { } catch (InterruptedException ex) { setEnabled(false); final String msg = String.format("Bundle-audit process was interrupted. Disabling %s", ANALYZER_NAME); + Thread.currentThread().interrupt(); throw new InitializationException(msg); } if (0 == exitValue) { @@ -291,6 +292,7 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer { try { exitValue = process.waitFor(); } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); throw new AnalysisException("bundle-audit process interrupted", ie); } if (exitValue < 0 || exitValue > 1) { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.java index 7780c7a54..2641bf8f5 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.java @@ -116,21 +116,19 @@ public final class CpeMemoryIndex { * @param cve the data source to retrieve the cpe data * @throws IndexException thrown if there is an error creating the index */ - public void open(CveDB cve) throws IndexException { - synchronized (INSTANCE) { - if (!openState) { - index = new RAMDirectory(); - buildIndex(cve); - try { - indexReader = DirectoryReader.open(index); - } catch (IOException ex) { - throw new IndexException(ex); - } - indexSearcher = new IndexSearcher(indexReader); - searchingAnalyzer = createSearchingAnalyzer(); - queryParser = new QueryParser(LuceneUtils.CURRENT_VERSION, Fields.DOCUMENT_KEY, searchingAnalyzer); - openState = true; + public synchronized void open(CveDB cve) throws IndexException { + if (!openState) { + index = new RAMDirectory(); + buildIndex(cve); + try { + indexReader = DirectoryReader.open(index); + } catch (IOException ex) { + throw new IndexException(ex); } + indexSearcher = new IndexSearcher(indexReader); + searchingAnalyzer = createSearchingAnalyzer(); + queryParser = new QueryParser(LuceneUtils.CURRENT_VERSION, Fields.DOCUMENT_KEY, searchingAnalyzer); + openState = true; } } @@ -162,7 +160,7 @@ public final class CpeMemoryIndex { /** * Closes the CPE Index. */ - public void close() { + public synchronized void close() { if (searchingAnalyzer != null) { searchingAnalyzer.close(); searchingAnalyzer = null; diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/Advisory.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/Advisory.java index d31fcb2bc..8736db13c 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/Advisory.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/Advisory.java @@ -17,9 +17,11 @@ */ package org.owasp.dependencycheck.data.nsp; +import java.util.Arrays; + /** - * The response from NSP check API will respond with 0 or more advisories. - * This class defines the Advisory objects returned. + * The response from NSP check API will respond with 0 or more advisories. This + * class defines the Advisory objects returned. * * @author Steve Springett */ @@ -51,7 +53,8 @@ public class Advisory { private String overview; /** - * Recommendations for mitigation. Typically involves updating to a newer release. + * Recommendations for mitigation. Typically involves updating to a newer + * release. */ private String recommendation; @@ -91,9 +94,8 @@ public class Advisory { private String title; /** - * The linear dependency path that lead to this module. - * [0] is the root with each subsequent array member leading up to the - * final (this) module. + * The linear dependency path that lead to this module. [0] is the root with + * each subsequent array member leading up to the final (this) module. */ private String[] path; @@ -103,7 +105,9 @@ public class Advisory { private String advisory; /** - * Returns the unique ID of the advisory as issued by Node Security Platform. + * Returns the unique ID of the advisory as issued by Node Security + * Platform. + * * @return a unique ID */ public int getId() { @@ -112,6 +116,7 @@ public class Advisory { /** * Sets the unique ID of the advisory as issued by Node Security Platform. + * * @param id a unique ID */ public void setId(int id) { @@ -120,6 +125,7 @@ public class Advisory { /** * Returns the timestamp of the last update to the advisory. + * * @return a timestamp */ public String getUpdatedAt() { @@ -128,6 +134,7 @@ public class Advisory { /** * Sets the timestamp of the last update to the advisory. + * * @param updatedAt a timestamp */ public void setUpdatedAt(String updatedAt) { @@ -136,6 +143,7 @@ public class Advisory { /** * Returns the timestamp of which the advisory was created. + * * @return a timestamp */ public String getCreatedAt() { @@ -144,6 +152,7 @@ public class Advisory { /** * Sets the timestamp of which the advisory was created. + * * @param createdAt a timestamp */ public void setCreatedAt(String createdAt) { @@ -152,6 +161,7 @@ public class Advisory { /** * Returns the timestamp of when the advisory was published. + * * @return a timestamp */ public String getPublishDate() { @@ -160,6 +170,7 @@ public class Advisory { /** * Sets the timestamp of when the advisory was published. + * * @param publishDate a timestamp */ public void setPublishDate(String publishDate) { @@ -168,6 +179,7 @@ public class Advisory { /** * Returns a detailed description of the advisory. + * * @return the overview */ public String getOverview() { @@ -176,6 +188,7 @@ public class Advisory { /** * Sets the detailed description of the advisory. + * * @param overview the overview */ public void setOverview(String overview) { @@ -183,7 +196,9 @@ public class Advisory { } /** - * Returns recommendations for mitigation. Typically involves updating to a newer release. + * Returns recommendations for mitigation. Typically involves updating to a + * newer release. + * * @return recommendations */ public String getRecommendation() { @@ -191,7 +206,9 @@ public class Advisory { } /** - * Sets recommendations for mitigation. Typically involves updating to a newer release. + * Sets recommendations for mitigation. Typically involves updating to a + * newer release. + * * @param recommendation recommendations */ public void setRecommendation(String recommendation) { @@ -200,6 +217,7 @@ public class Advisory { /** * Returns the CVSS vector used to calculate the score. + * * @return the CVSS vector */ public String getCvssVector() { @@ -208,6 +226,7 @@ public class Advisory { /** * Sets the CVSS vector used to calculate the score. + * * @param cvssVector the CVSS vector */ public void setCvssVector(String cvssVector) { @@ -216,6 +235,7 @@ public class Advisory { /** * Returns the CVSS score. + * * @return the CVSS score */ public float getCvssScore() { @@ -224,6 +244,7 @@ public class Advisory { /** * Sets the CVSS score. + * * @param cvssScore the CVSS score */ public void setCvssScore(float cvssScore) { @@ -232,6 +253,7 @@ public class Advisory { /** * Returns the name of the Node module the advisory is for. + * * @return the name of the module */ public String getModule() { @@ -240,6 +262,7 @@ public class Advisory { /** * Sets the name of the Node module the advisory is for. + * * @param module the name of the4 module */ public void setModule(String module) { @@ -248,6 +271,7 @@ public class Advisory { /** * Returns the version of the Node module the advisory is for. + * * @return the module version */ public String getVersion() { @@ -256,6 +280,7 @@ public class Advisory { /** * Sets the version of the Node module the advisory is for. + * * @param version the module version */ public void setVersion(String version) { @@ -263,7 +288,9 @@ public class Advisory { } /** - * Returns a string representation of the versions containing the vulnerability. + * Returns a string representation of the versions containing the + * vulnerability. + * * @return the affected versions */ public String getVulnerableVersions() { @@ -271,7 +298,9 @@ public class Advisory { } /** - * Sets the string representation of the versions containing the vulnerability. + * Sets the string representation of the versions containing the + * vulnerability. + * * @param vulnerableVersions the affected versions */ public void setVulnerableVersions(String vulnerableVersions) { @@ -280,6 +309,7 @@ public class Advisory { /** * Returns a string representation of the versions that have been patched. + * * @return the patched versions */ public String getPatchedVersions() { @@ -288,6 +318,7 @@ public class Advisory { /** * Sets the string representation of the versions that have been patched. + * * @param patchedVersions the patched versions */ public void setPatchedVersions(String patchedVersions) { @@ -296,6 +327,7 @@ public class Advisory { /** * Returns the title/name of the advisory. + * * @return the title/name of the advisory */ public String getTitle() { @@ -304,6 +336,7 @@ public class Advisory { /** * Sets the title/name of the advisory. + * * @param title the title/name of the advisory */ public void setTitle(String title) { @@ -312,22 +345,32 @@ public class Advisory { /** * Returns the linear dependency path that lead to this module. + * * @return the dependency path */ public String[] getPath() { - return path; + if (path == null) { + return null; + } + return Arrays.copyOf(path, path.length); } /** * Sets the linear dependency path that lead to this module. + * * @param path the dependency path */ public void setPath(String[] path) { - this.path = path; + if (path == null) { + this.path = null; + } else { + this.path = Arrays.copyOf(path, path.length); + } } /** * Returns the URL to the advisory. + * * @return the advisory URL */ public String getAdvisory() { @@ -336,6 +379,7 @@ public class Advisory { /** * Sets the URL to the advisory. + * * @param advisory the advisory URL */ public void setAdvisory(String advisory) { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/NspSearch.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/NspSearch.java index 9fa4fbbd0..e3ed19024 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/NspSearch.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/NspSearch.java @@ -82,13 +82,14 @@ public class NspSearch { * * @param packageJson the package.json file retrieved from the Dependency * @return a List of zero or more Advisory object - * @throws AnalysisException if Node Security Platform is unable to analyze the package + * @throws AnalysisException if Node Security Platform is unable to analyze + * the package * @throws IOException if it's unable to connect to Node Security Platform */ public List submitPackage(JsonObject packageJson) throws AnalysisException, IOException { try { - List result = new ArrayList<>(); - byte[] packageDatabytes = packageJson.toString().getBytes(StandardCharsets.UTF_8); + final List result = new ArrayList<>(); + final byte[] packageDatabytes = packageJson.toString().getBytes(StandardCharsets.UTF_8); final HttpURLConnection conn = URLConnectionFactory.createHttpURLConnection(nspCheckUrl, useProxy); conn.setDoOutput(true); @@ -104,48 +105,50 @@ public class NspSearch { os.flush(); } - if (conn.getResponseCode() == 200) { - try (InputStream in = new BufferedInputStream(conn.getInputStream())) { - JsonReader jsonReader = Json.createReader(in); - JsonArray array = jsonReader.readArray(); - if (array != null) { - for (int i = 0; i < array.size(); i++) { - JsonObject object = array.getJsonObject(i); - Advisory advisory = new Advisory(); - advisory.setId(object.getInt("id")); - advisory.setUpdatedAt(object.getString("updated_at", null)); - advisory.setCreatedAt(object.getString("created_at", null)); - advisory.setPublishDate(object.getString("publish_date", null)); - advisory.setOverview(object.getString("overview")); - advisory.setRecommendation(object.getString("recommendation", null)); - advisory.setCvssVector(object.getString("cvss_vector", null)); - advisory.setCvssScore(Float.parseFloat(object.getJsonNumber("cvss_score").toString())); - advisory.setModule(object.getString("module", null)); - advisory.setVersion(object.getString("version", null)); - advisory.setVulnerableVersions(object.getString("vulnerable_versions", null)); - advisory.setPatchedVersions(object.getString("patched_versions", null)); - advisory.setTitle(object.getString("title", null)); - advisory.setAdvisory(object.getString("advisory", null)); + switch (conn.getResponseCode()) { + case 200: + try (InputStream in = new BufferedInputStream(conn.getInputStream()); + JsonReader jsonReader = Json.createReader(in)) { + final JsonArray array = jsonReader.readArray(); + if (array != null) { + for (int i = 0; i < array.size(); i++) { + final JsonObject object = array.getJsonObject(i); + final Advisory advisory = new Advisory(); + advisory.setId(object.getInt("id")); + advisory.setUpdatedAt(object.getString("updated_at", null)); + advisory.setCreatedAt(object.getString("created_at", null)); + advisory.setPublishDate(object.getString("publish_date", null)); + advisory.setOverview(object.getString("overview")); + advisory.setRecommendation(object.getString("recommendation", null)); + advisory.setCvssVector(object.getString("cvss_vector", null)); + advisory.setCvssScore(Float.parseFloat(object.getJsonNumber("cvss_score").toString())); + advisory.setModule(object.getString("module", null)); + advisory.setVersion(object.getString("version", null)); + advisory.setVulnerableVersions(object.getString("vulnerable_versions", null)); + advisory.setPatchedVersions(object.getString("patched_versions", null)); + advisory.setTitle(object.getString("title", null)); + advisory.setAdvisory(object.getString("advisory", null)); - JsonArray jsonPath = object.getJsonArray("path"); - List stringPath = new ArrayList<>(); - for (int j = 0; j < jsonPath.size(); j++) { - stringPath.add(jsonPath.getString(j)); + final JsonArray jsonPath = object.getJsonArray("path"); + final List stringPath = new ArrayList<>(); + for (int j = 0; j < jsonPath.size(); j++) { + stringPath.add(jsonPath.getString(j)); + } + advisory.setPath(stringPath.toArray(new String[stringPath.size()])); + + result.add(advisory); } - advisory.setPath(stringPath.toArray(new String[stringPath.size()])); - - result.add(advisory); } } - } - } else if (conn.getResponseCode() == 400) { - LOGGER.debug("Invalid payload submitted to Node Security Platform. Received response code: {} {}", - conn.getResponseCode(), conn.getResponseMessage()); - throw new AnalysisException("Could not perform NSP analysis. Invalid payload submitted to Node Security Platform."); - } else { - LOGGER.debug("Could not connect to Node Security Platform. Received response code: {} {}", - conn.getResponseCode(), conn.getResponseMessage()); - throw new IOException("Could not connect to Node Security Platform"); + break; + case 400: + LOGGER.debug("Invalid payload submitted to Node Security Platform. Received response code: {} {}", + conn.getResponseCode(), conn.getResponseMessage()); + throw new AnalysisException("Could not perform NSP analysis. Invalid payload submitted to Node Security Platform."); + default: + LOGGER.debug("Could not connect to Node Security Platform. Received response code: {} {}", + conn.getResponseCode(), conn.getResponseMessage()); + throw new IOException("Could not connect to Node Security Platform"); } return result; } catch (IOException ex) { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/SanitizePackage.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/SanitizePackage.java index 4103ea118..26ac4dd16 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/SanitizePackage.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/SanitizePackage.java @@ -27,15 +27,22 @@ import java.util.List; import java.util.Map; /** - * Class used to create a Sanitized version of package.json - * suitable for submission to the nsp/check service. + * Class used to create a Sanitized version of package.json suitable for + * submission to the nsp/check service. * * @author Steve Springett */ -public class SanitizePackage { +public final class SanitizePackage { /** - * Specifies a whitelist of allowable objects that package.json should contain. + * Private constructor for utility class. + */ + private SanitizePackage() { + //empty + } + /** + * Specifies a whitelist of allowable objects that package.json should + * contain. */ private static final List WHITELIST = new ArrayList<>(Arrays.asList( "name", @@ -50,17 +57,17 @@ public class SanitizePackage { )); /** - * The NSP API only accepts a subset of objects typically found in package.json. - * This method accepts a JsonObject of a raw package.json file and returns a - * new 'sanitized' version based on a pre-defined whitelist of allowable object - * NSP accepts. + * The NSP API only accepts a subset of objects typically found in + * package.json. This method accepts a JsonObject of a raw package.json file + * and returns a new 'sanitized' version based on a pre-defined whitelist of + * allowable object NSP accepts. * * @param rawPackage a raw package.json file * @return a sanitized version of the package.json file */ public static JsonObject sanitize(JsonObject rawPackage) { - JsonObjectBuilder builder = Json.createObjectBuilder(); - for (Map.Entry entry: rawPackage.entrySet()) { + final JsonObjectBuilder builder = Json.createObjectBuilder(); + for (Map.Entry entry : rawPackage.entrySet()) { if (WHITELIST.contains(entry.getKey())) { builder.add(entry.getKey(), entry.getValue()); } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java index 802d02076..8d1c63415 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java @@ -561,8 +561,10 @@ public final class CveDB implements AutoCloseable { final Entry matchedCPE = getMatchingSoftware(vulnSoftware, cpe.getVendor(), cpe.getProduct(), detectedVersion); if (matchedCPE != null) { final Vulnerability v = getVulnerability(currentCVE); - v.setMatchedCPE(matchedCPE.getKey(), matchedCPE.getValue() ? "Y" : null); - vulnerabilities.add(v); + if (v != null) { + v.setMatchedCPE(matchedCPE.getKey(), matchedCPE.getValue() ? "Y" : null); + vulnerabilities.add(v); + } } vulnSoftware.clear(); currentCVE = cveId; @@ -577,8 +579,10 @@ public final class CveDB implements AutoCloseable { final Entry matchedCPE = getMatchingSoftware(vulnSoftware, cpe.getVendor(), cpe.getProduct(), detectedVersion); if (matchedCPE != null) { final Vulnerability v = getVulnerability(currentCVE); - v.setMatchedCPE(matchedCPE.getKey(), matchedCPE.getValue() ? "Y" : null); - vulnerabilities.add(v); + if (v != null) { + v.setMatchedCPE(matchedCPE.getKey(), matchedCPE.getValue() ? "Y" : null); + vulnerabilities.add(v); + } } } catch (SQLException ex) { throw new DatabaseException("Exception retrieving vulnerability for " + cpeStr, ex); @@ -666,11 +670,12 @@ public final class CveDB implements AutoCloseable { */ public synchronized void updateVulnerability(Vulnerability vuln) throws DatabaseException { clearCache(); + ResultSet rs = null; try { int vulnerabilityId = 0; final PreparedStatement selectVulnerabilityId = getPreparedStatement(SELECT_VULNERABILITY_ID); selectVulnerabilityId.setString(1, vuln.getName()); - ResultSet rs = selectVulnerabilityId.executeQuery(); + rs = selectVulnerabilityId.executeQuery(); if (rs.next()) { vulnerabilityId = rs.getInt(1); // first delete any existing vulnerability info. We don't know what was updated. yes, slower but atm easier. @@ -789,6 +794,8 @@ public final class CveDB implements AutoCloseable { final String msg = String.format("Error updating '%s'", vuln.getName()); LOGGER.debug(msg, ex); throw new DatabaseException(msg, ex); + } finally { + DBUtils.closeResultSet(rs); } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/NvdCveUpdater.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/NvdCveUpdater.java index 5659a4376..72081e97b 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/NvdCveUpdater.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/NvdCveUpdater.java @@ -115,7 +115,8 @@ public class NvdCveUpdater implements CachedWebDataSource { final File dir = Settings.getDataDirectory(); lockFile = new File(dir, "odc.update.lock"); if (lockFile.isFile() && getFileAge(lockFile) > 5 && !lockFile.delete()) { - LOGGER.warn("An old db update lock file was found but the system was unable to delete the file. Consider manually deleting " + lockFile.getAbsolutePath()); + LOGGER.warn("An old db update lock file was found but the system was unable to delete " + + "the file. Consider manually deleting {}", lockFile.getAbsolutePath()); } int ctr = 0; do { @@ -126,13 +127,19 @@ public class NvdCveUpdater implements CachedWebDataSource { } } catch (IOException ex) { LOGGER.trace("Expected error as another thread has likely locked the file", ex); + } finally { + if (lock==null && ulFile!=null) { + ulFile.close(); + } } if (lock == null || !lock.isValid()) { try { - LOGGER.debug(String.format("Sleeping thread %s for 5 seconds because we could not obtain the update lock.", Thread.currentThread().getName())); + LOGGER.debug(String.format("Sleeping thread %s for 5 seconds because we could not obtain the update lock.", + Thread.currentThread().getName())); Thread.sleep(5000); } catch (InterruptedException ex) { LOGGER.trace("ignorable error, sleep was interrupted.", ex); + Thread.currentThread().interrupt(); } } } while (++ctr < 60 && (lock == null || !lock.isValid())); @@ -328,6 +335,7 @@ public class NvdCveUpdater implements CachedWebDataSource { task = future.get(); } catch (InterruptedException ex) { LOGGER.debug("Thread was interrupted during download", ex); + Thread.currentThread().interrupt(); throw new UpdateException("The download was interrupted", ex); } catch (ExecutionException ex) { LOGGER.debug("Thread was interrupted during download execution", ex); @@ -349,6 +357,7 @@ public class NvdCveUpdater implements CachedWebDataSource { } } catch (InterruptedException ex) { LOGGER.debug("Thread was interrupted during processing", ex); + Thread.currentThread().interrupt(); throw new UpdateException(ex); } catch (ExecutionException ex) { LOGGER.debug("Execution Exception during process", ex); @@ -520,7 +529,10 @@ public class NvdCveUpdater implements CachedWebDataSource { final long timestamp; try { timestamp = timestampFuture.get(60, TimeUnit.SECONDS); - } catch (InterruptedException | ExecutionException | TimeoutException e) { + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new DownloadFailedException(e); + } catch (ExecutionException | TimeoutException e) { throw new DownloadFailedException(e); } lastModifiedDates.put(url, timestamp); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/EvidenceCollection.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/EvidenceCollection.java index fb45480b0..67afa87c0 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/EvidenceCollection.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/EvidenceCollection.java @@ -261,9 +261,12 @@ public class EvidenceCollection implements Serializable, Iterable { for (Evidence e : EvidenceCollection.EVIDENCE_USED.filter(this)) { //TODO consider changing the regex to only compare alpha-numeric (i.e. strip everything else) - final String value = urlCorrection(e.getValue().toLowerCase()).replaceAll("[\\s_-]", ""); - if (value.contains(textToTest)) { - return true; + String item = e.getValue(); + if (item != null) { + final String value = urlCorrection(item.toLowerCase()).replaceAll("[\\s_-]", ""); + if (value.contains(textToTest)) { + return true; + } } } return false; diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Vulnerability.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Vulnerability.java index 98ea466b2..055c65fc8 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Vulnerability.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Vulnerability.java @@ -32,9 +32,18 @@ import org.apache.commons.lang3.builder.CompareToBuilder; */ public class Vulnerability implements Serializable, Comparable { + /** + * An enumeration for the source of vulnerability. + */ public enum Source { - NVD, // National Vulnerability Database - NSP // Node Security Platform + /** + * National Vulnerability Database. + */ + NVD, + /** + * Node Security Platform. + */ + NSP } /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java index 2d82f963e..dd50ed4c2 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java @@ -170,7 +170,8 @@ public class ReportGenerator { * NVD CVE data) * @return the velocity context */ - private VelocityContext createContext(String applicationName, List dependencies, List analyzers, DatabaseProperties properties) { + private VelocityContext createContext(String applicationName, List dependencies, + List analyzers, DatabaseProperties properties) { final DateTime dt = new DateTime(); final DateTimeFormatter dateFormat = DateTimeFormat.forPattern("MMM d, yyyy 'at' HH:mm:ss z"); final DateTimeFormatter dateFormatXML = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); @@ -261,7 +262,6 @@ public class ReportGenerator { // final String templateName = format.toString().toLowerCase() + "Report"; // processTemplate(templateName, outputStream); // } - /** * Determines the report file name based on the give output location and * format. If the output location contains a full file name that has the @@ -371,6 +371,7 @@ public class ReportGenerator { } } } + /** * Validates that the given file's parent directory exists. If the directory * does not exist an attempt to create the necessary path is made; if that @@ -389,6 +390,7 @@ public class ReportGenerator { } } } + /** * Reformats the given JSON file. * diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/ArtifactTypeExcluded.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/ArtifactTypeExcluded.java index 780e1da11..b50307add 100644 --- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/ArtifactTypeExcluded.java +++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/ArtifactTypeExcluded.java @@ -1,5 +1,5 @@ /* - * This file is part of dependency-check-maven. + * This file is part of dependency-check-core. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,6 +12,8 @@ * 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) 2017 The OWASP Foundation. All Rights Reserved. */ package org.owasp.dependencycheck.maven; @@ -19,15 +21,23 @@ import org.apache.commons.lang.StringUtils; import org.owasp.dependencycheck.utils.Filter; /** - * {@link Filter} implementation to exclude artifacts whose type matches a regular expression + * {@link Filter} implementation to exclude artifacts whose type matches a + * regular expression. + * + * @author ercpe */ public class ArtifactTypeExcluded extends Filter { + /** + * The regular expression for the exclusion filter. + */ private final String regex; /** - * Creates a new instance - * @param excludeRegex The regular expression to match the artifacts type against + * Creates a new instance. + * + * @param excludeRegex The regular expression to match the artifacts type + * against */ public ArtifactTypeExcluded(final String excludeRegex) { this.regex = excludeRegex; diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java index 941864d3e..e910be398 100644 --- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java +++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java @@ -691,7 +691,7 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma } if (!isResolved) { getLog().error("Unable to resolve system scoped dependency: " + dependencyNode.toNodeString()); - exCol.addException(new DependencyNotFoundException("Unable to resolve system scoped dependency: " + exCol.addException(new DependencyNotFoundException("Unable to resolve system scoped dependency: " + dependencyNode.toNodeString())); } } else { diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Downloader.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Downloader.java index 41c594d9f..ce4f769f5 100644 --- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Downloader.java +++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Downloader.java @@ -25,6 +25,7 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URISyntaxException; import java.net.URL; @@ -163,9 +164,9 @@ public final class Downloader { } final String encoding = conn.getContentEncoding(); - BufferedOutputStream writer = null; InputStream reader = null; - try { + try (OutputStream out = new FileOutputStream(outputPath); + BufferedOutputStream writer = new BufferedOutputStream(out)) { if (encoding != null && "gzip".equalsIgnoreCase(encoding)) { reader = new GZIPInputStream(conn.getInputStream()); } else if (encoding != null && "deflate".equalsIgnoreCase(encoding)) { @@ -173,8 +174,7 @@ public final class Downloader { } else { reader = conn.getInputStream(); } - - writer = new BufferedOutputStream(new FileOutputStream(outputPath)); + final byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = reader.read(buffer)) > 0) { @@ -191,13 +191,6 @@ public final class Downloader { url.toString(), outputPath.getAbsolutePath(), conn.getConnectTimeout(), encoding); throw new DownloadFailedException(msg, ex); } finally { - if (writer != null) { - try { - writer.close(); - } catch (IOException ex) { - LOGGER.trace("Error closing the writer in Downloader.", ex); - } - } if (reader != null) { try { reader.close();