Merge branch 'master' into updateJsonReport

This commit is contained in:
Jeremy Long
2017-05-14 09:26:27 -04:00
13 changed files with 368 additions and 12 deletions

View File

@@ -19,7 +19,9 @@ package org.owasp.dependencycheck.reporting;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Set;
import org.apache.commons.lang3.StringEscapeUtils;
import org.owasp.dependencycheck.dependency.Identifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -94,4 +96,71 @@ public class EscapeTool {
}
return StringEscapeUtils.escapeJson(text);
}
/**
* Formats text for CSV format. This includes trimming whitespace, replace
* line breaks with spaces, and if necessary quotes the text and/or escapes
* contained quotes.
*
* @param text the text to escape and quote
* @return the escaped and quoted text
*/
public String csv(String text) {
if (text == null || text.isEmpty()) {
return text;
}
return StringEscapeUtils.escapeCsv(text.trim().replace("\n", " "));
}
/**
* Takes a set of Identifiers, filters them to none CPE, and formats them
* for display in a CSV.
*
* @param ids the set of identifiers
* @return the formated list of none CPE identifiers
*/
public String csvIdentifiers(Set<Identifier> ids) {
if (ids == null || ids.isEmpty()) {
return "";
}
boolean addComma = false;
StringBuilder sb = new StringBuilder();
for (Identifier id : ids) {
if (!"cpe".equals(id.getType())) {
if (addComma) {
sb.append(", ");
} else {
addComma = true;
}
sb.append(id.getValue());
}
}
return StringEscapeUtils.escapeCsv(sb.toString());
}
/**
* Takes a set of Identifiers, filters them to just CPEs, and formats them
* for display in a CSV.
*
* @param ids the set of identifiers
* @return the formated list of CPE identifiers
*/
public String csvCpe(Set<Identifier> ids) {
if (ids == null || ids.isEmpty()) {
return "";
}
boolean addComma = false;
StringBuilder sb = new StringBuilder();
for (Identifier id : ids) {
if ("cpe".equals(id.getType())) {
if (addComma) {
sb.append(", ");
} else {
addComma = true;
}
sb.append(id.getValue());
}
}
return StringEscapeUtils.escapeCsv(sb.toString());
}
}

View File

@@ -81,7 +81,11 @@ public class ReportGenerator {
/**
* Generate JSON report.
*/
JSON
JSON,
/**
* Generate CSV report.
*/
CSV
}
/**
* The Velocity Engine.
@@ -191,6 +195,9 @@ public class ReportGenerator {
if (format == Format.JSON || format == Format.ALL) {
generateReport("JsonReport", outputStream);
}
if (format == Format.CSV || format == Format.ALL) {
generateReport("CsvReport", outputStream);
}
}
/**
@@ -209,6 +216,9 @@ public class ReportGenerator {
generateReport("JsonReport", outputDir + File.separator + "dependency-check-report.json");
pretifyJson(outputDir + File.separator + "dependency-check-report.json");
}
if (format == Format.CSV || format == Format.ALL) {
generateReport("CsvReport", outputDir + File.separator + "dependency-check-report.csv");
}
if (format == Format.HTML || format == Format.ALL) {
generateReport("HtmlReport", outputDir + File.separator + "dependency-check-report.html");
}
@@ -344,6 +354,13 @@ public class ReportGenerator {
generateReports(outputDir, Format.JSON);
}
}
if ("CSV".equalsIgnoreCase(format)) {
if (pathToCheck.endsWith(".csv")) {
generateReport("CsvReport", outputDir);
} else {
generateReports(outputDir, Format.JSON);
}
}
if ("ALL".equalsIgnoreCase(format)) {
generateReports(outputDir, Format.ALL);
}

View File

@@ -1,5 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.1.xsd">
<suppress base="true">
<notes><![CDATA[
This suppresses false positives for EntityFramework.SqlServer.dll.
]]></notes>
<filePath regex="true">.*EntityFramework\.SqlServer*\.dll</filePath>
<cpe>cpe:/a:microsoft:server:6.0.0.0</cpe>
<cpe>cpe:/a:microsoft:sql_server:6.0</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
This suppresses false positives identified on spring security.

View File

@@ -0,0 +1,27 @@
#**
This file is part of Dependency-Check.
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) 2017 Jeremy Long. All Rights Reserved.
@author Jeremy Long <jeremy.long@owasp.org>
@version 1 *###
"Project","ScanDate","DependencyName","DependencyPath","Description","License","Md5","Sha1","Identifiers","CPE","CVE","CWE","Vulnerability","Severity","CVSSv2"
#macro(writeSev $score)#if($score<4.0)"Low"#elseif($score>=7.0)"High"#else"Medium"#end#end
#foreach($dependency in $dependencies)#if($dependency.getVulnerabilities().size()>0)
#foreach($vuln in $dependency.getVulnerabilities())
$enc.csv($applicationName),$enc.csv($scanDate),$enc.csv($dependency.DisplayFileName),#if($dependency.FilePath)$enc.csv($dependency.FilePath)#end,#if($dependency.description)$enc.csv($dependency.description)#end,#if($dependency.license)$enc.csv($dependency.license)#end,#if($dependency.Md5sum)$enc.csv($dependency.Md5sum)#end,#if($dependency.Sha1sum)$enc.csv($dependency.Sha1sum)#end,#if($dependency.identifiers)$enc.csvIdentifiers($dependency.identifiers)#end,#if($dependency.identifiers)$enc.csvCpe($dependency.identifiers)#end,#if($vuln.name)$enc.csv($vuln.name)#end,#if($dependency.cwe)$enc.csv($vuln.cwe)#end,#if($vuln.description)$enc.csv($vuln.description)#end,#writeSev($vuln.cvssScore),$vuln.cvssScore
#end
#end
#end

View File

@@ -0,0 +1,231 @@
/*
* 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.
* 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) 2017 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.reporting;
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
import static org.junit.Assert.*;
import org.owasp.dependencycheck.dependency.Identifier;
/**
*
* @author jerem
*/
public class EscapeToolTest {
/**
* Test of url method, of class EscapeTool.
*/
@Test
public void testUrl() {
String text = null;
EscapeTool instance = new EscapeTool();
String expResult = null;
String result = instance.url(text);
assertEquals(expResult, result);
text = "";
expResult = "";
result = instance.url(text);
assertEquals(expResult, result);
text = " ";
expResult = "+";
result = instance.url(text);
assertEquals(expResult, result);
}
/**
* Test of html method, of class EscapeTool.
*/
@Test
public void testHtml() {
EscapeTool instance = new EscapeTool();
String text = null;
String expResult = null;
String result = instance.html(text);
assertEquals(expResult, result);
text = "";
expResult = "";
result = instance.html(text);
assertEquals(expResult, result);
text = "<div>";
expResult = "&lt;div&gt;";
result = instance.html(text);
assertEquals(expResult, result);
}
/**
* Test of xml method, of class EscapeTool.
*/
@Test
public void testXml() {
EscapeTool instance = new EscapeTool();
String text = null;
String expResult = null;
String result = instance.xml(text);
assertEquals(expResult, result);
text = "";
expResult = "";
result = instance.xml(text);
assertEquals(expResult, result);
text = "<div>";
expResult = "&lt;div&gt;";
result = instance.xml(text);
assertEquals(expResult, result);
}
/**
* Test of json method, of class EscapeTool.
*/
@Test
public void testJson() {
String text = null;
EscapeTool instance = new EscapeTool();
String expResult = null;
String result = instance.json(text);
assertEquals(expResult, result);
text = "";
expResult = "";
result = instance.json(text);
assertEquals(expResult, result);
text = "test \"quote\"\"";
expResult = "test \\\"quote\\\"\\\"";
result = instance.json(text);
assertEquals(expResult, result);
}
/**
* Test of csv method, of class EscapeTool.
*/
@Test
public void testCsv() {
String text = null;
EscapeTool instance = new EscapeTool();
String expResult = null;
String result = instance.csv(text);
assertEquals(expResult, result);
text = "";
expResult = "";
result = instance.csv(text);
assertEquals(expResult, result);
text = "one, two";
expResult = "\"one, two\"";
result = instance.csv(text);
assertEquals(expResult, result);
}
/**
* Test of csvIdentifiers method, of class EscapeTool.
*/
@Test
public void testCsvIdentifiers() {
EscapeTool instance = new EscapeTool();
Set<Identifier> ids = null;
String expResult = "";
String result = instance.csvIdentifiers(ids);
assertEquals(expResult, result);
ids = new HashSet<>();
expResult = "";
result = instance.csvIdentifiers(ids);
assertEquals(expResult, result);
ids = new HashSet<>();
ids.add(new Identifier("cpe", "cpe:/a:somegroup:something:1.0", ""));
expResult = "";
result = instance.csvIdentifiers(ids);
assertEquals(expResult, result);
ids = new HashSet<>();
ids.add(new Identifier("gav", "somegroup:something:1.0", ""));
expResult = "somegroup:something:1.0";
result = instance.csvIdentifiers(ids);
assertEquals(expResult, result);
ids = new HashSet<>();
ids.add(new Identifier("cpe", "cpe:/a:somegroup:something:1.0", ""));
ids.add(new Identifier("gav", "somegroup:something:1.0", ""));
expResult = "somegroup:something:1.0";
result = instance.csvIdentifiers(ids);
assertEquals(expResult, result);
ids = new HashSet<>();
ids.add(new Identifier("cpe", "cpe:/a:somegroup:something:1.0", ""));
ids.add(new Identifier("gav", "somegroup:something:1.0", ""));
ids.add(new Identifier("gav", "somegroup2:something:1.2", ""));
expResult = "\"somegroup:something:1.0, somegroup2:something:1.2\"";
String expResult2 = "\"somegroup2:something:1.2, somegroup:something:1.0\"";
result = instance.csvIdentifiers(ids);
assertTrue(expResult.equals(result) || expResult2.equals(result));
}
/**
* Test of csvCpe method, of class EscapeTool.
*/
@Test
public void testCsvCpe() {
EscapeTool instance = new EscapeTool();
Set<Identifier> ids = null;
String expResult = "";
String result = instance.csvCpe(ids);
assertEquals(expResult, result);
ids = new HashSet<>();
expResult = "";
result = instance.csvCpe(ids);
assertEquals(expResult, result);
ids = new HashSet<>();
ids.add(new Identifier("gav", "somegroup:something:1.0", ""));
expResult = "";
result = instance.csvCpe(ids);
assertEquals(expResult, result);
ids = new HashSet<>();
ids.add(new Identifier("cpe", "cpe:/a:somegroup:something:1.0", ""));
expResult = "cpe:/a:somegroup:something:1.0";
result = instance.csvCpe(ids);
assertEquals(expResult, result);
ids = new HashSet<>();
ids.add(new Identifier("cpe", "cpe:/a:somegroup:something:1.0", ""));
ids.add(new Identifier("gav", "somegroup:something:1.0", ""));
expResult = "cpe:/a:somegroup:something:1.0";
result = instance.csvCpe(ids);
assertEquals(expResult, result);
ids = new HashSet<>();
ids.add(new Identifier("cpe", "cpe:/a:somegroup:something:1.0", ""));
ids.add(new Identifier("gav", "somegroup:something:1.0", ""));
ids.add(new Identifier("cpe", "cpe:/a:somegroup2:something:1.2", ""));
expResult = "\"cpe:/a:somegroup:something:1.0, cpe:/a:somegroup2:something:1.2\"";
String expResult2 = "\"cpe:/a:somegroup2:something:1.2, cpe:/a:somegroup:something:1.0\"";
result = instance.csvCpe(ids);
assertTrue(expResult.equals(result) || expResult2.equals(result));
}
}