added support for suppression by GAV (issue #124), created base suppression.xml (issue #123), and fixed false positives related to spring security (issue #130)

Former-commit-id: 330134211d022fec336dc1ca39205a94a088ee84
This commit is contained in:
Jeremy Long
2014-06-22 16:34:39 -04:00
parent d2cd406a62
commit 13116c5381
7 changed files with 172 additions and 29 deletions

View File

@@ -98,11 +98,18 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
* @throws SuppressionParseException thrown if the XML cannot be parsed.
*/
private void loadSuppressionData() throws SuppressionParseException {
final SuppressionParser parser = new SuppressionParser();
File file = null;
file = new File(this.getClass().getClassLoader().getResource("dependencycheck-base-suppression.xml").getPath());
try {
rules = parser.parseSuppressionRules(file);
} catch (SuppressionParseException ex) {
LOGGER.log(Level.FINE, "Unable to parse the base suppression data file", ex);
}
final String suppressionFilePath = Settings.getString(Settings.KEYS.SUPPRESSION_FILE);
if (suppressionFilePath == null) {
return;
}
File file = null;
boolean deleteTempFile = false;
try {
final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE);
@@ -132,9 +139,9 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
}
if (file != null) {
final SuppressionParser parser = new SuppressionParser();
try {
rules = parser.parseSuppressionRules(file);
//rules = parser.parseSuppressionRules(file);
rules.addAll(parser.parseSuppressionRules(file));
LOGGER.log(Level.FINE, rules.size() + " suppression rules were loaded.");
} catch (SuppressionParseException ex) {
final String msg = String.format("Unable to parse suppression xml file '%s'", file.getPath());

View File

@@ -54,6 +54,10 @@ public class SuppressionHandler extends DefaultHandler {
* The CWE element name.
*/
public static final String CWE = "cwe";
/**
* The GAV element name.
*/
public static final String GAV = "gav";
/**
* The cvssBelow element name.
*/
@@ -95,13 +99,10 @@ public class SuppressionHandler extends DefaultHandler {
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
currentAttributes = null;
currentAttributes = attributes;
currentText = new StringBuffer();
if (SUPPRESS.equals(qName)) {
rule = new SuppressionRule();
} else if (FILE_PATH.equals(qName)) {
currentAttributes = attributes;
}
}
@@ -123,6 +124,9 @@ public class SuppressionHandler extends DefaultHandler {
rule.setFilePath(pt);
} else if (SHA1.equals(qName)) {
rule.setSha1(currentText.toString());
} else if (GAV.equals(qName)) {
final PropertyType pt = processPropertyType();
rule.setGav(pt);
} else if (CPE.equals(qName)) {
final PropertyType pt = processPropertyType();
rule.addCpe(pt);

View File

@@ -20,6 +20,7 @@ package org.owasp.dependencycheck.suppression;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Identifier;
import org.owasp.dependencycheck.dependency.Vulnerability;
@@ -30,6 +31,10 @@ import org.owasp.dependencycheck.dependency.Vulnerability;
*/
public class SuppressionRule {
/**
* The Logger for use throughout the class
*/
private static final Logger LOGGER = Logger.getLogger(SuppressionRule.class.getName());
/**
* The file path for the suppression.
*/
@@ -280,16 +285,19 @@ public class SuppressionRule {
return;
}
if (gav != null) {
LOGGER.info(this.toString());
final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
boolean hasMatch = false;
boolean gavFound = false;
while (itr.hasNext()) {
final Identifier i = itr.next();
LOGGER.info(String.format("%nChecking %s for gav:%s", i.getValue(), this.gav));
if (identifierMatches("maven", this.gav, i)) {
hasMatch = true;
LOGGER.info("GAV Matched!");
gavFound = true;
break;
}
}
if (!hasMatch) {
if (!gavFound) {
return;
}
}
@@ -298,8 +306,17 @@ public class SuppressionRule {
final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
while (itr.hasNext()) {
final Identifier i = itr.next();
if (this.gav != null) {
LOGGER.info(String.format("%nProcessesing %s", i.getValue()));
}
for (PropertyType c : this.cpe) {
if (this.gav != null) {
LOGGER.info(String.format("%nChecking %s for cpe:%s", i.getValue(), c.getValue()));
}
if (identifierMatches("cpe", c, i)) {
if (this.gav != null) {
LOGGER.info(String.format("%nRemoving %s", i.getValue()));
}
dependency.addSuppressedIdentifier(i);
itr.remove();
break;
@@ -355,7 +372,7 @@ public class SuppressionRule {
boolean cpeHasNoVersion(PropertyType c) {
if (c.isRegex()) {
return false;
} // cpe:/a:jboss:jboss:1.0.0:
} // cpe:/a:jboss:jboss:1.0.0
if (countCharacter(c.getValue(), ':') == 3) {
return true;
}
@@ -390,20 +407,62 @@ public class SuppressionRule {
if (identifierType.equals(identifier.getType())) {
if (suppressionEntry.matches(identifier.getValue())) {
return true;
} else if (cpeHasNoVersion(suppressionEntry)) {
} else if ("cpe".equals(identifierType) && cpeHasNoVersion(suppressionEntry)) {
if (suppressionEntry.isCaseSensitive()) {
if (identifier.getValue().startsWith(suppressionEntry.getValue())) {
return true;
}
return identifier.getValue().startsWith(suppressionEntry.getValue());
} else {
final String id = identifier.getValue().toLowerCase();
final String check = suppressionEntry.getValue().toLowerCase();
if (id.startsWith(check)) {
return true;
}
return id.startsWith(check);
}
}
}
return false;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("SuppressionRule{");
if (filePath != null) {
sb.append("filePath=").append(filePath).append(",");
}
if (sha1 != null) {
sb.append("sha1=").append(sha1).append(",");
}
if (gav != null) {
sb.append("gav=").append(gav).append(",");
}
if (cpe != null && cpe.size() > 0) {
sb.append("cpe={");
for (PropertyType pt : cpe) {
sb.append(pt).append(",");
}
sb.append("}");
}
if (cwe != null && cwe.size() > 0) {
sb.append("cwe={");
for (String s : cwe) {
sb.append(s).append(",");
}
sb.append("}");
}
if (cve != null && cve.size() > 0) {
sb.append("cve={");
for (String s : cve) {
sb.append(s).append(",");
}
sb.append("}");
}
if (cvssBelow != null && cvssBelow.size() > 0) {
sb.append("cvssBelow={");
for (Float s : cvssBelow) {
sb.append(s).append(",");
}
sb.append("}");
}
sb.append("}");
return sb.toString();
}
}

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://www.owasp.org/index.php/OWASP_Dependency_Check_Suppression">
<suppress>
<notes><![CDATA[
This suppresses false positives identified on spring security.
]]></notes>
<gav regex="true">org\.springframework\.security:spring.*</gav>
<cpe>cpe:/a:mod_security:mod_security</cpe>
<cpe>cpe:/a:springsource:spring_framework</cpe>
<cpe>cpe:/a:vmware:springsource_spring_framework</cpe>
</suppress>
</suppressions>