diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java
new file mode 100644
index 000000000..86a539682
--- /dev/null
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java
@@ -0,0 +1,115 @@
+/*
+ * This file is part of dependency-check-core.
+ *
+ * Dependency-check-core is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Dependency-check-core is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * dependency-check-core. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2013 Jeremy Long. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.analyzer;
+
+import java.io.File;
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.owasp.dependencycheck.suppression.SuppressionParseException;
+import org.owasp.dependencycheck.suppression.SuppressionParser;
+import org.owasp.dependencycheck.suppression.SuppressionRule;
+import org.owasp.dependencycheck.utils.Settings;
+
+/**
+ * Abstract base suppression analyzer that contains methods for parsing the
+ * suppression xml file.
+ *
+ * @author Jeremy Long (jeremy.long@owasp.org)
+ */
+public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
+
+ //
+ /**
+ * Returns a list of file EXTENSIONS supported by this analyzer.
+ *
+ * @return a list of file EXTENSIONS supported by this analyzer.
+ */
+ public Set getSupportedExtensions() {
+ return null;
+ }
+
+ /**
+ * Returns whether or not this analyzer can process the given extension.
+ *
+ * @param extension the file extension to test for support.
+ * @return whether or not the specified file extension is supported by this
+ * analyzer.
+ */
+ @Override
+ public boolean supportsExtension(String extension) {
+ return true;
+ }
+
+ //
+ /**
+ * The initialize method loads the suppression XML file.
+ *
+ * @throws Exception thrown if there is an exception
+ */
+ @Override
+ public void initialize() throws Exception {
+ super.initialize();
+ loadSuppressionData();
+ }
+ /**
+ * The list of suppression rules
+ */
+ private List rules;
+
+ /**
+ * Get the value of rules.
+ *
+ * @return the value of rules
+ */
+ public List getRules() {
+ return rules;
+ }
+
+ /**
+ * Set the value of rules.
+ *
+ * @param rules new value of rules
+ */
+ public void setRules(List rules) {
+ this.rules = rules;
+ }
+
+ /**
+ * Loads the suppression rules file.
+ *
+ * @throws SuppressionParseException thrown if the XML cannot be parsed.
+ */
+ private void loadSuppressionData() throws SuppressionParseException {
+ final File file = Settings.getFile(Settings.KEYS.SUPPRESSION_FILE);
+ if (file != null) {
+ final SuppressionParser parser = new SuppressionParser();
+ try {
+ rules = parser.parseSuppressionRules(file);
+ } catch (SuppressionParseException ex) {
+ final String msg = String.format("Unable to parse suppression xml file '%s'", file.getPath());
+ Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.WARNING, msg);
+ Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.WARNING, ex.getMessage());
+ Logger.getLogger(AbstractSuppressionAnalyzer.class.getName()).log(Level.FINE, null, ex);
+ throw ex;
+ }
+ }
+ }
+}
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CpeSuppressionAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CpeSuppressionAnalyzer.java
new file mode 100644
index 000000000..42c07b044
--- /dev/null
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CpeSuppressionAnalyzer.java
@@ -0,0 +1,76 @@
+/*
+ * This file is part of dependency-check-core.
+ *
+ * Dependency-check-core is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Dependency-check-core is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * dependency-check-core. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2013 Jeremy Long. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.analyzer;
+
+import org.owasp.dependencycheck.Engine;
+import org.owasp.dependencycheck.dependency.Dependency;
+import org.owasp.dependencycheck.suppression.SuppressionRule;
+
+/**
+ * The suppression analyzer processes an externally defined XML document that
+ * complies with the suppressions.xsd schema. Any identified CPE entries within
+ * the dependencies that match will be removed.
+ *
+ * @author Jeremy Long (jeremy.long@owasp.org)
+ */
+public class CpeSuppressionAnalyzer extends AbstractSuppressionAnalyzer {
+
+ //
+ /**
+ * The name of the analyzer.
+ */
+ private static final String ANALYZER_NAME = "Cpe Suppression Analyzer";
+ /**
+ * The phase that this analyzer is intended to run in.
+ */
+ private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.POST_IDENTIFIER_ANALYSIS;
+
+ /**
+ * Returns the name of the analyzer.
+ *
+ * @return the name of the analyzer.
+ */
+ @Override
+ public String getName() {
+ return ANALYZER_NAME;
+ }
+
+ /**
+ * Returns the phase that the analyzer is intended to run in.
+ *
+ * @return the phase that the analyzer is intended to run in.
+ */
+ @Override
+ public AnalysisPhase getAnalysisPhase() {
+ return ANALYSIS_PHASE;
+ }
+ //
+
+ @Override
+ public void analyze(final Dependency dependency, final Engine engine) throws AnalysisException {
+
+ if (getRules() == null || getRules().size() <= 0) {
+ return;
+ }
+
+ for (final SuppressionRule rule : getRules()) {
+ rule.process(dependency);
+ }
+ }
+}
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzer.java
new file mode 100644
index 000000000..65726ad8b
--- /dev/null
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzer.java
@@ -0,0 +1,76 @@
+/*
+ * This file is part of dependency-check-core.
+ *
+ * Dependency-check-core is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Dependency-check-core is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * dependency-check-core. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2013 Jeremy Long. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.analyzer;
+
+import org.owasp.dependencycheck.Engine;
+import org.owasp.dependencycheck.dependency.Dependency;
+import org.owasp.dependencycheck.suppression.SuppressionRule;
+
+/**
+ * The suppression analyzer processes an externally defined XML document that
+ * complies with the suppressions.xsd schema. Any identified Vulnerability
+ * entries within the dependencies that match will be removed.
+ *
+ * @author Jeremy Long (jeremy.long@owasp.org)
+ */
+public class VulnerabilitySuppressionAnalyzer extends AbstractSuppressionAnalyzer {
+
+ //
+ /**
+ * The name of the analyzer.
+ */
+ private static final String ANALYZER_NAME = "Vulnerability Suppression Analyzer";
+ /**
+ * The phase that this analyzer is intended to run in.
+ */
+ private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.POST_FINDING_ANALYSIS;
+
+ /**
+ * Returns the name of the analyzer.
+ *
+ * @return the name of the analyzer.
+ */
+ @Override
+ public String getName() {
+ return ANALYZER_NAME;
+ }
+
+ /**
+ * Returns the phase that the analyzer is intended to run in.
+ *
+ * @return the phase that the analyzer is intended to run in.
+ */
+ @Override
+ public AnalysisPhase getAnalysisPhase() {
+ return ANALYSIS_PHASE;
+ }
+ //
+
+ @Override
+ public void analyze(final Dependency dependency, final Engine engine) throws AnalysisException {
+
+ if (getRules() == null || getRules().size() <= 0) {
+ return;
+ }
+
+ for (final SuppressionRule rule : getRules()) {
+ rule.process(dependency);
+ }
+ }
+}
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/PropertyType.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/PropertyType.java
new file mode 100644
index 000000000..eb3b52050
--- /dev/null
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/PropertyType.java
@@ -0,0 +1,186 @@
+/*
+ * This file is part of dependency-check-core.
+ *
+ * Dependency-check-core is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Dependency-check-core is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * dependency-check-core. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2013 Jeremy Long. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.suppression;
+
+import java.util.regex.Pattern;
+
+/**
+ * A simple PropertyType used to represent a string value that could be used as
+ * a regular expression or could be case insensitive. The equals method has been
+ * over-ridden so that the object will correctly compare to strings.
+ *
+ * @author Jeremy Long (jeremy.long@owasp.org)
+ */
+public class PropertyType {
+
+ //
+ /**
+ * The value.
+ */
+ private String value;
+
+ /**
+ * Gets the value of the value property.
+ *
+ * @return the value of the value property
+ *
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Sets the value of the value property.
+ *
+ * @param value the value of the value property
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+ /**
+ * Whether or not the expression is a regex.
+ */
+ private boolean regex = false;
+
+ /**
+ * Returns whether or not the value is a regex.
+ *
+ * @return true if the value is a regex, otherwise false
+ *
+ */
+ public boolean isRegex() {
+ return regex;
+ }
+
+ /**
+ * Sets whether the value property is a regex.
+ *
+ * @param value true if the value is a regex, otherwise false
+ *
+ */
+ public void setRegex(boolean value) {
+ this.regex = value;
+ }
+ /**
+ * Indicates case sensitivity.
+ */
+ protected boolean caseSensitive = false;
+
+ /**
+ * Gets the value of the caseSensitive property.
+ *
+ * @return true if the value is case sensitive
+ *
+ */
+ public boolean isCaseSensitive() {
+ return caseSensitive;
+ }
+
+ /**
+ * Sets the value of the caseSensitive property.
+ *
+ * @param value whether the value is case sensitive
+ *
+ */
+ public void setCaseSensitive(boolean value) {
+ this.caseSensitive = value;
+ }
+ //
+
+ /**
+ * Uses the object's properties to determine if the supplied string matches
+ * the value of this property.
+ *
+ * @param text the String to validate
+ * @return whether the text supplied is matched by the value of the property
+ */
+ public boolean matches(String text) {
+ if (text == null) {
+ return false;
+ }
+ if (this.regex) {
+ Pattern rx;
+ if (this.caseSensitive) {
+ rx = Pattern.compile(this.value);
+ } else {
+ rx = Pattern.compile(this.value, Pattern.CASE_INSENSITIVE);
+ }
+ return rx.matcher(text).matches();
+ } else {
+ if (this.caseSensitive) {
+ return value.equals(text);
+ } else {
+ return value.equalsIgnoreCase(text);
+ }
+ }
+ }
+
+ //
+ /**
+ * Default implementation of hashCode.
+ *
+ * @return the hash code
+ */
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 59 * hash + (this.value != null ? this.value.hashCode() : 0);
+ hash = 59 * hash + (this.regex ? 1 : 0);
+ hash = 59 * hash + (this.caseSensitive ? 1 : 0);
+ return hash;
+ }
+
+ /**
+ * Default implementation of equals.
+ *
+ * @param obj the object to compare
+ * @return whether the objects are equivalent
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final PropertyType other = (PropertyType) obj;
+ if ((this.value == null) ? (other.value != null) : !this.value.equals(other.value)) {
+ return false;
+ }
+ if (this.regex != other.regex) {
+ return false;
+ }
+ if (this.caseSensitive != other.caseSensitive) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Default implementation of toString().
+ *
+ * @return the string representation of the object
+ */
+ @Override
+ public String toString() {
+ return "PropertyType{" + "value=" + value + ", regex=" + regex + ", caseSensitive=" + caseSensitive + '}';
+ }
+ //
+}
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionErrorHandler.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionErrorHandler.java
new file mode 100644
index 000000000..cfc2710b8
--- /dev/null
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionErrorHandler.java
@@ -0,0 +1,79 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.owasp.dependencycheck.suppression;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+/**
+ * An XML parsing error handler.
+ *
+ * @author Jeremy Long (jeremy.long@owasp.org)
+ */
+public class SuppressionErrorHandler implements ErrorHandler {
+
+ /**
+ * Builds a prettier exception message.
+ *
+ * @param ex the SAXParseException
+ * @return an easier to read exception message
+ */
+ private String getPrettyParseExceptionInfo(SAXParseException ex) {
+
+ final StringBuffer sb = new StringBuffer();
+
+ if (ex.getSystemId() != null) {
+ sb.append("systemId=").append(ex.getSystemId()).append(", ");
+ }
+ if (ex.getPublicId() != null) {
+ sb.append("publicId=").append(ex.getPublicId()).append(", ");
+ }
+ if (ex.getLineNumber() > 0) {
+ sb.append("Line=").append(ex.getLineNumber());
+ }
+ if (ex.getColumnNumber() > 0) {
+ sb.append(", Column=").append(ex.getColumnNumber());
+ }
+ sb.append(": ").append(ex.getMessage());
+
+ return sb.toString();
+ }
+
+ /**
+ * Logs warnings.
+ *
+ * @param ex the warning to log
+ * @throws SAXException is never thrown
+ */
+ @Override
+ public void warning(SAXParseException ex) throws SAXException {
+ Logger.getLogger(SuppressionErrorHandler.class.getName()).log(Level.FINE, null, ex);
+ }
+
+ /**
+ * Handles errors.
+ *
+ * @param ex the error to handle
+ * @throws SAXException is always thrown
+ */
+ @Override
+ public void error(SAXParseException ex) throws SAXException {
+ throw new SAXException(getPrettyParseExceptionInfo(ex));
+ }
+
+ /**
+ * Handles fatal exceptions.
+ *
+ * @param ex a fatal exception
+ * @throws SAXException is always
+ */
+ @Override
+ public void fatalError(SAXParseException ex) throws SAXException {
+ throw new SAXException(getPrettyParseExceptionInfo(ex));
+ }
+}
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionHandler.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionHandler.java
new file mode 100644
index 000000000..2acab08f7
--- /dev/null
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionHandler.java
@@ -0,0 +1,173 @@
+/*
+ * This file is part of dependency-check-core.
+ *
+ * Dependency-check-core is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Dependency-check-core is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * dependency-check-core. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2013 Jeremy Long. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.suppression;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * A handler to load suppression rules.
+ *
+ * @author Jeremy Long (jeremy.long@owasp.org)
+ */
+public class SuppressionHandler extends DefaultHandler {
+
+ /**
+ * The suppress node, indicates the start of a new rule.
+ */
+ public static final String SUPPRESS = "suppress";
+ /**
+ * The file path element name.
+ */
+ public static final String FILE_PATH = "filePath";
+ /**
+ * The sha1 hash element name.
+ */
+ public static final String SHA1 = "sha1";
+ /**
+ * The CVE element name.
+ */
+ public static final String CVE = "cve";
+ /**
+ * The CPE element name.
+ */
+ public static final String CPE = "cpe";
+ /**
+ * The CWE element name.
+ */
+ public static final String CWE = "cwe";
+ /**
+ * The cvssBelow element name.
+ */
+ public static final String CVSS_BELOW = "cvssBelow";
+ /**
+ * A list of suppression rules.
+ */
+ private List supressionRules = new ArrayList();
+
+ /**
+ * Get the value of supressionRules
+ *
+ * @return the value of supressionRules
+ */
+ public List getSupressionRules() {
+ return supressionRules;
+ }
+ /**
+ * The current rule being read.
+ */
+ private SuppressionRule rule;
+ /**
+ * The attributes of the node being read.
+ */
+ private Attributes currentAttributes;
+ /**
+ * The current node text being extracted from the element.
+ */
+ private StringBuffer currentText;
+
+ /**
+ * Handles the start element event.
+ *
+ * @param uri the uri of the element being processed
+ * @param localName the local name of the element being processed
+ * @param qName the qName of the element being processed
+ * @param attributes the attributes of the element being processed
+ * @throws SAXException thrown if there is an exception processing
+ */
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+ currentAttributes = null;
+ currentText = new StringBuffer();
+
+ if (SUPPRESS.equals(qName)) {
+ rule = new SuppressionRule();
+ } else if (FILE_PATH.equals(qName)) {
+ currentAttributes = attributes;
+ }
+ }
+
+ /**
+ * Handles the end element event.
+ *
+ * @param uri the uri of the element
+ * @param localName the local name of the element
+ * @param qName the qName of the element
+ * @throws SAXException thrown if there is an exception processing
+ */
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ if (SUPPRESS.equals(qName)) {
+ supressionRules.add(rule);
+ rule = null;
+ } else if (FILE_PATH.equals(qName)) {
+ PropertyType pt = processPropertyType();
+ rule.setFilePath(pt);
+ } else if (SHA1.equals(qName)) {
+ rule.setSha1(currentText.toString());
+ } else if (CPE.equals(qName)) {
+ PropertyType pt = processPropertyType();
+ rule.addCpe(pt);
+ } else if (CWE.equals(qName)) {
+ rule.addCwe(currentText.toString());
+ } else if (CVE.equals(qName)) {
+ rule.addCve(currentText.toString());
+ } else if (CVSS_BELOW.equals(qName)) {
+ float cvss = Float.parseFloat(currentText.toString());
+ }
+ }
+
+ /**
+ * Collects the body text of the node being processed.
+ *
+ * @param ch the char array of text
+ * @param start the start position to copy text from in the char array
+ * @param length the number of characters to copy from the char array
+ * @throws SAXException thrown if there is a parsing exception
+ */
+ @Override
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ currentText.append(ch, start, length);
+ }
+
+ /**
+ * Processes field members that have been collected during the characters
+ * and startElement method to construct a PropertyType object.
+ *
+ * @return a PropertyType object
+ */
+ private PropertyType processPropertyType() {
+ PropertyType pt = new PropertyType();
+ pt.setValue(currentText.toString());
+ if (currentAttributes != null && currentAttributes.getLength() > 0) {
+ final String regex = currentAttributes.getValue("regex");
+ if (regex != null) {
+ pt.setRegex(Boolean.parseBoolean(regex));
+ }
+ final String caseSensitive = currentAttributes.getValue("caseSensitive");
+ if (regex != null) {
+ pt.setCaseSensitive(Boolean.parseBoolean(caseSensitive));
+ }
+ }
+ return pt;
+ }
+}
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionParser.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionParser.java
new file mode 100644
index 000000000..464039869
--- /dev/null
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionParser.java
@@ -0,0 +1,107 @@
+/*
+ * This file is part of dependency-check-core.
+ *
+ * Dependency-check-core is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Dependency-check-core is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * dependency-check-core. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2013 Jeremy Long. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.suppression;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+/**
+ * A simple validating parser for XML Suppression Rules.
+ *
+ * @author Jeremy Long (jeremy.long@owasp.org)
+ */
+public class SuppressionParser {
+
+ /**
+ * JAXP Schema Language, source:
+ * http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html
+ */
+ public static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
+ /**
+ * W3C XML Schema, source:
+ * http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html
+ */
+ public static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
+ /**
+ * JAXP Schema Source, source:
+ * http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html
+ */
+ public static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";
+
+ /**
+ * Parses the given xml file and returns a list of the suppression rules
+ * contained.
+ *
+ * @param file an xml file containing suppression rules
+ * @return a list of suppression rules
+ * @throws SuppressionParseException thrown if the xml file cannot be parsed
+ */
+ public List parseSuppressionRules(File file) throws SuppressionParseException {
+ try {
+ File schema = new File(this.getClass().getClassLoader().getResource("schema/suppression.xsd").getPath());
+ SuppressionHandler handler = new SuppressionHandler();
+
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+ factory.setValidating(true);
+ SAXParser saxParser = factory.newSAXParser();
+ saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA);
+ saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, schema);
+ XMLReader xmlReader = saxParser.getXMLReader();
+ xmlReader.setErrorHandler(new SuppressionErrorHandler());
+ xmlReader.setContentHandler(handler);
+
+ InputStream inputStream = new FileInputStream(file);
+ Reader reader = new InputStreamReader(inputStream); //, "UTF-8");
+ InputSource in = new InputSource(reader);
+ //in.setEncoding("UTF-8");
+
+ xmlReader.parse(in);
+
+
+ return handler.getSupressionRules();
+ } catch (ParserConfigurationException ex) {
+ Logger.getLogger(SuppressionParser.class.getName()).log(Level.FINE, null, ex);
+ throw new SuppressionParseException(ex);
+ } catch (SAXException ex) {
+ Logger.getLogger(SuppressionParser.class.getName()).log(Level.FINE, null, ex);
+ throw new SuppressionParseException(ex);
+ } catch (FileNotFoundException ex) {
+ Logger.getLogger(SuppressionParser.class.getName()).log(Level.FINE, null, ex);
+ throw new SuppressionParseException(ex);
+ } catch (IOException ex) {
+ Logger.getLogger(SuppressionParser.class.getName()).log(Level.FINE, null, ex);
+ throw new SuppressionParseException(ex);
+ }
+ }
+}
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionRule.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionRule.java
new file mode 100644
index 000000000..e8ce2b061
--- /dev/null
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/suppression/SuppressionRule.java
@@ -0,0 +1,334 @@
+/*
+ * This file is part of dependency-check-core.
+ *
+ * Dependency-check-core is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Dependency-check-core is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * dependency-check-core. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2013 Jeremy Long. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.suppression;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.owasp.dependencycheck.dependency.Dependency;
+import org.owasp.dependencycheck.dependency.Identifier;
+import org.owasp.dependencycheck.dependency.Vulnerability;
+
+/**
+ *
+ * @author Jeremy Long (jeremy.long@owasp.org)
+ */
+public class SuppressionRule {
+
+ /**
+ * The file path for the suppression.
+ */
+ private PropertyType filePath;
+
+ /**
+ * Get the value of filePath.
+ *
+ * @return the value of filePath
+ */
+ public PropertyType getFilePath() {
+ return filePath;
+ }
+
+ /**
+ * Set the value of filePath.
+ *
+ * @param filePath new value of filePath
+ */
+ public void setFilePath(PropertyType filePath) {
+ this.filePath = filePath;
+ }
+ /**
+ * The sha1 hash.
+ */
+ private String sha1;
+
+ /**
+ * Get the value of sha1.
+ *
+ * @return the value of sha1
+ */
+ public String getSha1() {
+ return sha1;
+ }
+
+ /**
+ * Set the value of sha1.
+ *
+ * @param sha1 new value of sha1
+ */
+ public void setSha1(String sha1) {
+ this.sha1 = sha1;
+ }
+ /**
+ * A list of CPEs to suppression
+ */
+ private List cpe = new ArrayList();
+
+ /**
+ * Get the value of cpe.
+ *
+ * @return the value of cpe
+ */
+ public List getCpe() {
+ return cpe;
+ }
+
+ /**
+ * Set the value of cpe.
+ *
+ * @param cpe new value of cpe
+ */
+ public void setCpe(List cpe) {
+ this.cpe = cpe;
+ }
+
+ /**
+ * Adds the cpe to the cpe list.
+ *
+ * @param cpe the cpe to add
+ */
+ public void addCpe(PropertyType cpe) {
+ this.cpe.add(cpe);
+ }
+
+ /**
+ * Returns whether or not this suppression rule as CPE entries.
+ *
+ * @return whether or not this suppression rule as CPE entries
+ */
+ public boolean hasCpe() {
+ return cpe.size() > 0;
+ }
+ /**
+ * The list of cvssBelow scores.
+ */
+ private List cvssBelow = new ArrayList();
+
+ /**
+ * Get the value of cvssBelow
+ *
+ * @return the value of cvssBelow
+ */
+ public List getCvssBelow() {
+ return cvssBelow;
+ }
+
+ /**
+ * Set the value of cvssBelow
+ *
+ * @param cvssBelow new value of cvssBelow
+ */
+ public void setCvssBelow(List cvssBelow) {
+ this.cvssBelow = cvssBelow;
+ }
+
+ /**
+ * Adds the cvss to the cvssBelow list.
+ *
+ * @param cvss the cvss to add
+ */
+ public void addCvssBelow(Float cvss) {
+ this.cvssBelow.add(cvss);
+ }
+
+ /**
+ * Returns whether or not this suppression rule has cvss suppressions.
+ *
+ * @return whether or not this suppression rule has cvss suppressions
+ */
+ public boolean hasCvssBelow() {
+ return cvssBelow.size() > 0;
+ }
+ /**
+ * The list of cwe entries to suppress.
+ */
+ private List cwe = new ArrayList();
+
+ /**
+ * Get the value of cwe.
+ *
+ * @return the value of cwe
+ */
+ public List getCwe() {
+ return cwe;
+ }
+
+ /**
+ * Set the value of cwe.
+ *
+ * @param cwe new value of cwe
+ */
+ public void setCwe(List cwe) {
+ this.cwe = cwe;
+ }
+
+ /**
+ * Adds the cwe to the cwe list.
+ *
+ * @param cwe the cwe to add
+ */
+ public void addCwe(String cwe) {
+ this.cwe.add(cwe);
+ }
+
+ /**
+ * Returns whether this suppression rule has CWE entries.
+ *
+ * @return whether this suppression rule has CWE entries
+ */
+ public boolean hasCwe() {
+ return cwe.size() > 0;
+ }
+ /**
+ * The list of cve entries to suppress.
+ */
+ private List cve = new ArrayList();
+
+ /**
+ * Get the value of cve.
+ *
+ * @return the value of cve
+ */
+ public List getCve() {
+ return cve;
+ }
+
+ /**
+ * Set the value of cve.
+ *
+ * @param cve new value of cve
+ */
+ public void setCve(List cve) {
+ this.cve = cve;
+ }
+
+ /**
+ * Adds the cve to the cve list.
+ *
+ * @param cve the cve to add
+ */
+ public void addCve(String cve) {
+ this.cve.add(cve);
+ }
+
+ /**
+ * Returns whether this suppression rule has CVE entries.
+ *
+ * @return whether this suppression rule has CVE entries
+ */
+ public boolean hasCve() {
+ return cve.size() > 0;
+ }
+
+ public void process(Dependency dependency) {
+ if (filePath != null && !filePath.matches(dependency.getFilePath())) {
+ return;
+ }
+ if (sha1 != null && !sha1.equalsIgnoreCase(dependency.getSha1sum())) {
+ return;
+ }
+ if (this.hasCpe()) {
+ Iterator itr = dependency.getIdentifiers().iterator();
+ while (itr.hasNext()) {
+ Identifier i = itr.next();
+ for (PropertyType c : this.cpe) {
+ if (cpeMatches(c, i)) {
+ itr.remove();
+ break;
+ }
+ }
+ }
+ }
+ if (hasCve() || hasCwe() || hasCvssBelow()) {
+ Iterator itr = dependency.getVulnerabilities().iterator();
+ boolean remove = false;
+ while (!remove && itr.hasNext()) {
+ Vulnerability v = itr.next();
+ for (String entry : this.cve) {
+ if (entry.equalsIgnoreCase(v.getName())) {
+ remove = true;
+ break;
+ }
+ }
+ if (!remove) {
+ for (String entry : this.cwe) {
+ if (v.getCwe() != null) {
+ final String toMatch = String.format("CWE-%s ", entry);
+ final String toTest = v.getCwe().substring(0, toMatch.length()).toUpperCase();
+ if (toTest.equals(toMatch)) {
+ remove = true;
+ break;
+ }
+ }
+ }
+ }
+ if (!remove) {
+ for (float cvss : this.cvssBelow) {
+ if (v.getCvssScore() < cvss) {
+ remove = true;
+ break;
+ }
+ }
+ }
+ if (remove) {
+ itr.remove();
+ }
+ }
+ }
+ }
+
+ boolean cpeHasNoVersion(PropertyType c) {
+ if (c.isRegex()) {
+ return false;
+ } // cpe:/a:jboss:jboss:1.0.0:
+ if (countCharacter(c.getValue(), ':') == 3) {
+ return true;
+ }
+ return false;
+ }
+
+ int countCharacter(String str, char c) {
+ int count = 0;
+ int pos = str.indexOf(c) + 1;
+ while (pos > 0) {
+ count += 1;
+ pos = str.indexOf(c, pos) + 1;
+ }
+ return count;
+ }
+
+ boolean cpeMatches(PropertyType cpeEntry, Identifier identifier) {
+ if (cpeEntry.matches(identifier.getValue())) {
+ return true;
+ } else if (cpeHasNoVersion(cpeEntry)) {
+ if (cpeEntry.isCaseSensitive()) {
+ if (identifier.getValue().startsWith(cpeEntry.getValue())) {
+ return true;
+ }
+ } else {
+ final String id = identifier.getValue().toLowerCase();
+ final String check = cpeEntry.getValue().toLowerCase();
+ if (id.startsWith(check)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/suppression/PropertyTypeTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/suppression/PropertyTypeTest.java
new file mode 100644
index 000000000..e18b130da
--- /dev/null
+++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/suppression/PropertyTypeTest.java
@@ -0,0 +1,108 @@
+/*
+ * This file is part of dependency-check-core.
+ *
+ * Dependency-check-core is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Dependency-check-core is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * dependency-check-core. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2013 Jeremy Long. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.suppression;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Jeremy Long (jeremy.long@owasp.org)
+ */
+public class PropertyTypeTest {
+
+ public PropertyTypeTest() {
+ }
+
+ @BeforeClass
+ public static void setUpClass() {
+ }
+
+ @AfterClass
+ public static void tearDownClass() {
+ }
+
+ @Before
+ public void setUp() {
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+ /**
+ * Test of set and getValue method, of class PropertyType.
+ */
+ @Test
+ public void testSetGetValue() {
+
+ PropertyType instance = new PropertyType();
+ String expResult = "test";
+ instance.setValue(expResult);
+ String result = instance.getValue();
+ assertEquals(expResult, result);
+ }
+
+ /**
+ * Test of isRegex method, of class PropertyType.
+ */
+ @Test
+ public void testIsRegex() {
+ PropertyType instance = new PropertyType();
+ boolean result = instance.isRegex();
+ assertFalse(instance.isRegex());
+ instance.setRegex(true);
+ assertTrue(instance.isRegex());
+ }
+
+ /**
+ * Test of isCaseSensitive method, of class PropertyType.
+ */
+ @Test
+ public void testIsCaseSensitive() {
+ PropertyType instance = new PropertyType();
+ assertFalse(instance.isCaseSensitive());
+ instance.setCaseSensitive(true);
+ assertTrue(instance.isCaseSensitive());
+ }
+
+ /**
+ * Test of matches method, of class PropertyType.
+ */
+ @Test
+ public void testMatches() {
+ String text = "Simple";
+
+ PropertyType instance = new PropertyType();
+ instance.setValue("simple");
+ assertTrue(instance.matches(text));
+ instance.setCaseSensitive(true);
+ assertFalse(instance.matches(text));
+
+ instance.setValue("s.*le");
+ instance.setRegex(true);
+ assertFalse(instance.matches(text));
+ instance.setCaseSensitive(false);
+ assertTrue(instance.matches(text));
+ }
+}
diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/suppression/SuppressionHandlerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/suppression/SuppressionHandlerTest.java
new file mode 100644
index 000000000..a47dc4515
--- /dev/null
+++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/suppression/SuppressionHandlerTest.java
@@ -0,0 +1,95 @@
+/*
+ * This file is part of dependency-check-core.
+ *
+ * Dependency-check-core is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Dependency-check-core is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * dependency-check-core. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2013 Jeremy Long. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.suppression;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.List;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+
+/**
+ *
+ * @author Jeremy Long (jeremy.long@owasp.org)
+ */
+public class SuppressionHandlerTest {
+
+ public SuppressionHandlerTest() {
+ }
+
+ @BeforeClass
+ public static void setUpClass() {
+ }
+
+ @AfterClass
+ public static void tearDownClass() {
+ }
+
+ @Before
+ public void setUp() {
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+ /**
+ * Test of getSupressionRules method, of class SuppressionHandler.
+ *
+ * @throws Exception thrown if there is an exception....
+ */
+ @Test
+ public void testHandler() throws Exception {
+ File file = new File(this.getClass().getClassLoader().getResource("suppressions.xml").getPath());
+
+ File schema = new File(this.getClass().getClassLoader().getResource("schema/suppression.xsd").getPath());
+ SuppressionHandler handler = new SuppressionHandler();
+
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+ factory.setValidating(true);
+ SAXParser saxParser = factory.newSAXParser();
+ saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA);
+ saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, schema);
+ XMLReader xmlReader = saxParser.getXMLReader();
+ xmlReader.setErrorHandler(new SuppressionErrorHandler());
+ xmlReader.setContentHandler(handler);
+
+ InputStream inputStream = new FileInputStream(file);
+ Reader reader = new InputStreamReader(inputStream); //, "UTF-8");
+ InputSource in = new InputSource(reader);
+ //in.setEncoding("UTF-8");
+
+ xmlReader.parse(in);
+
+ List result = handler.getSupressionRules();
+ assertTrue(result.size() > 3);
+ }
+}
diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/suppression/SuppressionParserTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/suppression/SuppressionParserTest.java
new file mode 100644
index 000000000..7c5ce205c
--- /dev/null
+++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/suppression/SuppressionParserTest.java
@@ -0,0 +1,66 @@
+/*
+ * This file is part of dependency-check-core.
+ *
+ * Dependency-check-core is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Dependency-check-core is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * dependency-check-core. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2013 Jeremy Long. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.suppression;
+
+import java.io.File;
+import java.util.List;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ * Test of the suppression parser.
+ *
+ * @author Jeremy Long (jeremy.long@owasp.org)
+ */
+public class SuppressionParserTest {
+
+ public SuppressionParserTest() {
+ }
+
+ @BeforeClass
+ public static void setUpClass() {
+ }
+
+ @AfterClass
+ public static void tearDownClass() {
+ }
+
+ @Before
+ public void setUp() {
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+ /**
+ * Test of parseSuppressionRules method, of class SuppressionParser.
+ */
+ @Test
+ public void testParseSuppressionRules() throws Exception {
+ File file = new File(this.getClass().getClassLoader().getResource("suppressions.xml").getPath());
+ SuppressionParser instance = new SuppressionParser();
+ List result = instance.parseSuppressionRules(file);
+ assertTrue(result.size() > 3);
+ }
+}
diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/suppression/SuppressionRuleTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/suppression/SuppressionRuleTest.java
new file mode 100644
index 000000000..294bf6f4a
--- /dev/null
+++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/suppression/SuppressionRuleTest.java
@@ -0,0 +1,471 @@
+/*
+ * This file is part of dependency-check-core.
+ *
+ * Dependency-check-core is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Dependency-check-core is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * dependency-check-core. If not, see http://www.gnu.org/licenses/.
+ *
+ * Copyright (c) 2013 Jeremy Long. All Rights Reserved.
+ */
+package org.owasp.dependencycheck.suppression;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+import org.owasp.dependencycheck.dependency.Dependency;
+import org.owasp.dependencycheck.dependency.Identifier;
+import org.owasp.dependencycheck.dependency.Vulnerability;
+
+/**
+ * Test of the suppression rule.
+ *
+ * @author Jeremy Long (jeremy.long@owasp.org)
+ */
+public class SuppressionRuleTest {
+
+ public SuppressionRuleTest() {
+ }
+
+ @BeforeClass
+ public static void setUpClass() {
+ }
+
+ @AfterClass
+ public static void tearDownClass() {
+ }
+
+ @Before
+ public void setUp() {
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+ //
+ /**
+ * Test of FilePath property, of class SuppressionRule.
+ */
+ @Test
+ public void testFilePath() {
+ SuppressionRule instance = new SuppressionRule();
+ PropertyType expResult = new PropertyType();
+ expResult.setValue("test");
+ instance.setFilePath(expResult);
+ PropertyType result = instance.getFilePath();
+ assertEquals(expResult, result);
+ }
+
+ /**
+ * Test of Sha1 property, of class SuppressionRule.
+ */
+ @Test
+ public void testSha1() {
+ SuppressionRule instance = new SuppressionRule();
+ String expResult = "384FAA82E193D4E4B0546059CA09572654BC3970";
+ instance.setSha1(expResult);
+ String result = instance.getSha1();
+ assertEquals(expResult, result);
+ }
+
+ /**
+ * Test of Cpe property, of class SuppressionRule.
+ */
+ @Test
+ public void testCpe() {
+ SuppressionRule instance = new SuppressionRule();
+ ArrayList cpe = new ArrayList();
+ instance.setCpe(cpe);
+ assertFalse(instance.hasCpe());
+ PropertyType pt = new PropertyType();
+ pt.setValue("one");
+ instance.addCpe(pt);
+ assertTrue(instance.hasCpe());
+ List result = instance.getCpe();
+ assertEquals(cpe, result);
+
+ }
+
+ /**
+ * Test of CvssBelow property, of class SuppressionRule.
+ */
+ @Test
+ public void testGetCvssBelow() {
+ SuppressionRule instance = new SuppressionRule();
+ ArrayList cvss = new ArrayList();
+ instance.setCvssBelow(cvss);
+ assertFalse(instance.hasCvssBelow());
+ instance.addCvssBelow(0.7f);
+ assertTrue(instance.hasCvssBelow());
+ List result = instance.getCvssBelow();
+ assertEquals(cvss, result);
+ }
+
+ /**
+ * Test of Cwe property, of class SuppressionRule.
+ */
+ @Test
+ public void testCwe() {
+ SuppressionRule instance = new SuppressionRule();
+ ArrayList cwe = new ArrayList();
+ instance.setCwe(cwe);
+ assertFalse(instance.hasCwe());
+ instance.addCwe("2");
+ assertTrue(instance.hasCwe());
+ List result = instance.getCwe();
+ assertEquals(cwe, result);
+ }
+
+ /**
+ * Test of Cve property, of class SuppressionRule.
+ */
+ @Test
+ public void testCve() {
+ SuppressionRule instance = new SuppressionRule();
+ ArrayList cve = new ArrayList();
+ instance.setCve(cve);
+ assertFalse(instance.hasCve());
+ instance.addCve("CVE-2013-1337");
+ assertTrue(instance.hasCve());
+ List result = instance.getCve();
+ assertEquals(cve, result);
+ }
+ //
+
+ //
+ /**
+ * Test of getFilePath method, of class SuppressionRule.
+ */
+ @Test
+ public void testGetFilePath() {
+ //already tested, this is just left so the IDE doesn't recreate it.
+ }
+
+ /**
+ * Test of setFilePath method, of class SuppressionRule.
+ */
+ @Test
+ public void testSetFilePath() {
+ //already tested, this is just left so the IDE doesn't recreate it.
+ }
+
+ /**
+ * Test of getSha1 method, of class SuppressionRule.
+ */
+ @Test
+ public void testGetSha1() {
+ //already tested, this is just left so the IDE doesn't recreate it.
+ }
+
+ /**
+ * Test of setSha1 method, of class SuppressionRule.
+ */
+ @Test
+ public void testSetSha1() {
+ //already tested, this is just left so the IDE doesn't recreate it.
+ }
+
+ /**
+ * Test of getCpe method, of class SuppressionRule.
+ */
+ @Test
+ public void testGetCpe() {
+ //already tested, this is just left so the IDE doesn't recreate it.
+ }
+
+ /**
+ * Test of setCpe method, of class SuppressionRule.
+ */
+ @Test
+ public void testSetCpe() {
+ //already tested, this is just left so the IDE doesn't recreate it.
+ }
+
+ /**
+ * Test of addCpe method, of class SuppressionRule.
+ */
+ @Test
+ public void testAddCpe() {
+ //already tested, this is just left so the IDE doesn't recreate it.
+ }
+
+ /**
+ * Test of hasCpe method, of class SuppressionRule.
+ */
+ @Test
+ public void testHasCpe() {
+ //already tested, this is just left so the IDE doesn't recreate it.
+ }
+
+ /**
+ * Test of setCvssBelow method, of class SuppressionRule.
+ */
+ @Test
+ public void testSetCvssBelow() {
+ //already tested, this is just left so the IDE doesn't recreate it.
+ }
+
+ /**
+ * Test of addCvssBelow method, of class SuppressionRule.
+ */
+ @Test
+ public void testAddCvssBelow() {
+ //already tested, this is just left so the IDE doesn't recreate it.
+ }
+
+ /**
+ * Test of hasCvssBelow method, of class SuppressionRule.
+ */
+ @Test
+ public void testHasCvssBelow() {
+ //already tested, this is just left so the IDE doesn't recreate it.
+ }
+
+ /**
+ * Test of getCwe method, of class SuppressionRule.
+ */
+ @Test
+ public void testGetCwe() {
+ //already tested, this is just left so the IDE doesn't recreate it.
+ }
+
+ /**
+ * Test of setCwe method, of class SuppressionRule.
+ */
+ @Test
+ public void testSetCwe() {
+ //already tested, this is just left so the IDE doesn't recreate it.
+ }
+
+ /**
+ * Test of addCwe method, of class SuppressionRule.
+ */
+ @Test
+ public void testAddCwe() {
+ //already tested, this is just left so the IDE doesn't recreate it.
+ }
+
+ /**
+ * Test of hasCwe method, of class SuppressionRule.
+ */
+ @Test
+ public void testHasCwe() {
+ //already tested, this is just left so the IDE doesn't recreate it.
+ }
+
+ /**
+ * Test of getCve method, of class SuppressionRule.
+ */
+ @Test
+ public void testGetCve() {
+ //already tested, this is just left so the IDE doesn't recreate it.
+ }
+
+ /**
+ * Test of setCve method, of class SuppressionRule.
+ */
+ @Test
+ public void testSetCve() {
+ //already tested, this is just left so the IDE doesn't recreate it.
+ }
+
+ /**
+ * Test of addCve method, of class SuppressionRule.
+ */
+ @Test
+ public void testAddCve() {
+ //already tested, this is just left so the IDE doesn't recreate it.
+ }
+
+ /**
+ * Test of hasCve method, of class SuppressionRule.
+ */
+ @Test
+ public void testHasCve() {
+ //already tested, this is just left so the IDE doesn't recreate it.
+ }
+ //
+
+ /**
+ * Test of cpeHasNoVersion method, of class SuppressionRule.
+ */
+ @Test
+ public void testCpeHasNoVersion() {
+ PropertyType c = new PropertyType();
+ c.setValue("cpe:/a:microsoft:.net_framework:4.5");
+ SuppressionRule instance = new SuppressionRule();
+ assertFalse(instance.cpeHasNoVersion(c));
+ c.setValue("cpe:/a:microsoft:.net_framework:");
+ assertFalse(instance.cpeHasNoVersion(c));
+ c.setValue("cpe:/a:microsoft:.net_framework");
+ assertTrue(instance.cpeHasNoVersion(c));
+ }
+
+ /**
+ * Test of countCharacter method, of class SuppressionRule.
+ */
+ @Test
+ public void testCountCharacter() {
+ String str = "cpe:/a:microsoft:.net_framework:4.5";
+ char c = ':';
+ SuppressionRule instance = new SuppressionRule();
+ int expResult = 4;
+ int result = instance.countCharacter(str, c);
+ assertEquals(expResult, result);
+ str = "::";
+ expResult = 2;
+ result = instance.countCharacter(str, c);
+ assertEquals(expResult, result);
+ str = "these are not the characters you are looking for";
+ expResult = 0;
+ result = instance.countCharacter(str, c);
+ assertEquals(expResult, result);
+ }
+
+ /**
+ * Test of cpeMatches method, of class SuppressionRule.
+ */
+ @Test
+ public void testCpeMatches() {
+ Identifier identifier = new Identifier("cwe", "cpe:/a:microsoft:.net_framework:4.5", "some url not needed for this test");
+
+ PropertyType cpe = new PropertyType();
+ cpe.setValue("cpe:/a:microsoft:.net_framework:4.5");
+
+ SuppressionRule instance = new SuppressionRule();
+ boolean expResult = true;
+ boolean result = instance.cpeMatches(cpe, identifier);
+ assertEquals(expResult, result);
+
+ cpe.setValue("cpe:/a:microsoft:.net_framework:4.0");
+ expResult = false;
+ result = instance.cpeMatches(cpe, identifier);
+ assertEquals(expResult, result);
+
+ cpe.setValue("CPE:/a:microsoft:.net_framework:4.5");
+ cpe.setCaseSensitive(true);
+ expResult = false;
+ result = instance.cpeMatches(cpe, identifier);
+ assertEquals(expResult, result);
+
+ cpe.setValue("cpe:/a:microsoft:.net_framework");
+ cpe.setCaseSensitive(false);
+ expResult = true;
+ result = instance.cpeMatches(cpe, identifier);
+ assertEquals(expResult, result);
+
+ cpe.setValue("cpe:/a:microsoft:.*");
+ cpe.setRegex(true);
+ expResult = true;
+ result = instance.cpeMatches(cpe, identifier);
+ assertEquals(expResult, result);
+
+ cpe.setValue("CPE:/a:microsoft:.*");
+ cpe.setRegex(true);
+ cpe.setCaseSensitive(true);
+ expResult = false;
+ result = instance.cpeMatches(cpe, identifier);
+ assertEquals(expResult, result);
+
+ cpe.setValue("cpe:/a:apache:.*");
+ cpe.setRegex(true);
+ cpe.setCaseSensitive(false);
+ expResult = false;
+ result = instance.cpeMatches(cpe, identifier);
+ assertEquals(expResult, result);
+ }
+
+ /**
+ * Test of process method, of class SuppressionRule.
+ */
+ @Test
+ public void testProcess() {
+ File struts = new File(this.getClass().getClassLoader().getResource("struts2-core-2.1.2.jar").getPath());
+ Dependency dependency = new Dependency(struts);
+ dependency.addIdentifier("cwe", "cpe:/a:microsoft:.net_framework:4.5", "some url not needed for this test");
+ String sha1 = dependency.getSha1sum();
+ dependency.setSha1sum("384FAA82E193D4E4B0546059CA09572654BC3970");
+ Vulnerability v = createVulnerability();
+ dependency.addVulnerability(v);
+
+ //cwe
+ SuppressionRule instance = new SuppressionRule();
+ instance.setSha1(sha1);
+ instance.addCwe("287");
+ instance.process(dependency);
+ assertTrue(dependency.getVulnerabilities().size() == 1);
+ dependency.setSha1sum(sha1);
+ instance.process(dependency);
+ assertTrue(dependency.getVulnerabilities().isEmpty());
+
+ //cvss
+ dependency.addVulnerability(v);
+ instance = new SuppressionRule();
+ instance.addCvssBelow(5f);
+ instance.process(dependency);
+ assertTrue(dependency.getVulnerabilities().size() == 1);
+ instance.addCvssBelow(8f);
+ instance.process(dependency);
+ assertTrue(dependency.getVulnerabilities().isEmpty());
+
+ //cve
+ dependency.addVulnerability(v);
+ instance = new SuppressionRule();
+ instance.addCve("CVE-2012-1337");
+ instance.process(dependency);
+ assertTrue(dependency.getVulnerabilities().size() == 1);
+ instance.addCve("CVE-2013-1337");
+ instance.process(dependency);
+ assertTrue(dependency.getVulnerabilities().isEmpty());
+
+ //cpe
+ instance = new SuppressionRule();
+ PropertyType pt = new PropertyType();
+ pt.setValue("cpe:/a:microsoft:.net_framework:4.0");
+ instance.addCpe(pt);
+ instance.process(dependency);
+ assertTrue(dependency.getIdentifiers().size() == 1);
+ pt = new PropertyType();
+ pt.setValue("cpe:/a:microsoft:.net_framework:4.5");
+ instance.addCpe(pt);
+ pt = new PropertyType();
+ pt.setValue(".*");
+ pt.setRegex(true);
+ instance.setFilePath(pt);
+ instance.process(dependency);
+ assertTrue(dependency.getIdentifiers().isEmpty());
+
+ dependency.addIdentifier("cwe", "cpe:/a:microsoft:.net_framework:4.0", "some url not needed for this test");
+ dependency.addIdentifier("cwe", "cpe:/a:microsoft:.net_framework:4.5", "some url not needed for this test");
+ dependency.addIdentifier("cwe", "cpe:/a:microsoft:.net_framework:5.0", "some url not needed for this test");
+ pt = new PropertyType();
+ pt.setValue("cpe:/a:microsoft:.net_framework");
+ instance.addCpe(pt);
+ assertTrue(dependency.getIdentifiers().size() == 3);
+ instance.process(dependency);
+ assertTrue(dependency.getIdentifiers().isEmpty());
+ }
+
+ private Vulnerability createVulnerability() {
+ Vulnerability v = new Vulnerability();
+ v.setCwe("CWE-287 Improper Authentication");
+ v.setName("CVE-2013-1337");
+ v.setCvssScore(7.5f);
+ return v;
+ }
+}