Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Log when non-base suppressions rules are unused #4709

Merged
merged 26 commits into from Aug 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
47f5f5a
fixes #4685
jeremylong Jul 21, 2022
679b0ab
make suppression rules collection a singleton so when rules run multi…
jeremylong Jul 27, 2022
0c3c3f3
make checkstyle happier
jeremylong Jul 28, 2022
9a9a8f7
fix build
jeremylong Jul 28, 2022
6ed4062
suppress warning
jeremylong Jul 28, 2022
5bc821b
purge github action cache
jeremylong Jul 28, 2022
ea4662c
Bump ossindex-service-client from 1.8.1 to 1.8.2
dependabot[bot] Jul 28, 2022
f255f92
Extend Quarkus Liquibase pattern
marcelstoer Jul 28, 2022
0d6504e
Add FP for parseurl
MisaelBustamante Jul 28, 2022
8dc569c
Apply suggestions from code review
MisaelBustamante Jul 31, 2022
7e32b9d
merge #4703
jeremylong Aug 1, 2022
cc66a98
merge #4715
jeremylong Aug 1, 2022
64e2a4a
Bump maven-reporting-api from 3.1.0 to 3.1.1
dependabot[bot] Aug 1, 2022
7952bb4
Bump postgresql from 42.4.0 to 42.4.1
dependabot[bot] Aug 4, 2022
a6927ad
Fix issue 4733. Update the mysql, mssql, postgresql and oracle initia…
albertwangnz Aug 9, 2022
807a813
Bump maven-site-plugin from 3.12.0 to 3.12.1
dependabot[bot] Aug 5, 2022
169d975
fix vuln count check on test
jeremylong Aug 9, 2022
82b046a
add yarn.lock to mixedLangSet to enable yarnAuditAnalyzer
livingwithcode Aug 10, 2022
e3396cc
Update maven/src/main/java/org/owasp/dependencycheck/maven/BaseDepend…
jeremylong Aug 12, 2022
db56450
update test cases to work with the singleton implementation
jeremylong Aug 17, 2022
0167809
remove unused interface
jeremylong Aug 17, 2022
c0ce698
Update core/src/main/java/org/owasp/dependencycheck/analyzer/Abstract…
jeremylong Aug 18, 2022
071dde7
Update core/src/main/java/org/owasp/dependencycheck/analyzer/Abstract…
jeremylong Aug 18, 2022
58ef8c7
remove un-needed code
jeremylong Aug 18, 2022
7e36392
Merge branch 'main' into logUnusedSuppressionRules
jeremylong Aug 18, 2022
596b237
fix javadoc
jeremylong Aug 18, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -29,6 +29,7 @@
import org.owasp.dependencycheck.BaseDBTestCase;

import static org.junit.Assert.assertTrue;
import org.owasp.dependencycheck.xml.suppression.SuppressionRules;

/**
*
Expand Down Expand Up @@ -131,8 +132,8 @@ public void testNestedBADReportFormat() throws Exception {
public void testGetFailBuildOnCVSS() {
Exception exception = Assert.assertThrows(BuildException.class, () -> buildFileRule.executeTarget("failCVSS"));

String expectedMessage = String.format("One or more dependencies were identified with vulnerabilities that " +
"have a CVSS score greater than or equal to '%.1f':", 3.0f);
String expectedMessage = String.format("One or more dependencies were identified with vulnerabilities that "
+ "have a CVSS score greater than or equal to '%.1f':", 3.0f);

Assert.assertTrue(exception.getMessage().contains(expectedMessage));
}
Expand All @@ -144,7 +145,8 @@ public void testGetFailBuildOnCVSS() {
public void testSuppressingCVE() {
// GIVEN an ant task with a vulnerability
final String antTaskName = "suppression";

//as the suppression rules are now a singleton - we must reset the list to cause the new suppression rules to load
SuppressionRules.getInstance().list().clear();
// WHEN executing the ant task
buildFileRule.executeTarget(antTaskName);
if (buildFileRule.getError() != null && !buildFileRule.getError().isEmpty()) {
Expand All @@ -168,7 +170,8 @@ public void testSuppressingCVE() {
public void testSuppressingSingle() {
// GIVEN an ant task with a vulnerability using the legacy property
final String antTaskName = "suppression-single";

//as the suppression rules are now a singleton - we must reset the list to cause the new suppression rules to load
SuppressionRules.getInstance().list().clear();
// WHEN executing the ant task
buildFileRule.executeTarget(antTaskName);

Expand All @@ -185,7 +188,8 @@ public void testSuppressingSingle() {
public void testSuppressingMultiple() {
// GIVEN an ant task with a vulnerability using multiple was to configure the suppression file
final String antTaskName = "suppression-multiple";

//as the suppression rules are now a singleton - we must reset the list to cause the new suppression rules to load
SuppressionRules.getInstance().list().clear();
// WHEN executing the ant task
buildFileRule.executeTarget(antTaskName);

Expand Down
3 changes: 3 additions & 0 deletions core/src/main/java/org/owasp/dependencycheck/Engine.java
Expand Up @@ -82,6 +82,7 @@
import static org.owasp.dependencycheck.analyzer.AnalysisPhase.PRE_IDENTIFIER_ANALYSIS;
import static org.owasp.dependencycheck.analyzer.AnalysisPhase.PRE_INFORMATION_COLLECTION;
import org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer;
import org.owasp.dependencycheck.xml.suppression.SuppressionRules;

/**
* Scans files, directories, etc. for Dependencies. Analyzers are loaded and
Expand Down Expand Up @@ -659,6 +660,8 @@ public void analyzeDependencies() throws ExceptionCollection {
.map(analyzers::get)
.forEach((analyzerList) -> analyzerList.forEach(this::closeAnalyzer));

SuppressionRules.getInstance().logUnusedRules();

LOGGER.debug("\n----------------------------------------------------\nEND ANALYSIS\n----------------------------------------------------");
final long analysisDurationSeconds = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - analysisStart);
LOGGER.info("Analysis Complete ({} seconds)", analysisDurationSeconds);
Expand Down
Expand Up @@ -43,7 +43,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
import org.owasp.dependencycheck.xml.suppression.SuppressionRuleFilter;
import org.owasp.dependencycheck.xml.suppression.SuppressionRules;

/**
* Abstract base suppression analyzer that contains methods for parsing the
Expand All @@ -52,7 +52,7 @@
* @author Jeremy Long
*/
@ThreadSafe
public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer implements SuppressionRuleFilter {
public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {

/**
* The Logger for use throughout the class.
Expand All @@ -63,9 +63,18 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer imple
*/
private static final String BASE_SUPPRESSION_FILE = "dependencycheck-base-suppression.xml";
/**
* The list of suppression rules.
* The collection of suppression rules.
*/
private final List<SuppressionRule> rules = new ArrayList<>();
private final SuppressionRules rules = SuppressionRules.getInstance();

/**
* Returns the suppression rules.
*
* @return the suppression rules
*/
protected SuppressionRules getSuppressionRules() {
return rules;
}

/**
* Get the number of suppression rules.
Expand Down Expand Up @@ -114,9 +123,22 @@ protected void analyzeDependency(Dependency dependency, Engine engine) throws An
if (rules.isEmpty()) {
return;
}
rules.forEach((rule) -> rule.process(dependency));
for (SuppressionRule rule : rules.list()) {
if (filter(rule)) {
rule.process(dependency);
}
}
}

/**
* Determines whether a suppression rule should be retained when filtering a set of suppression rules for a concrete suppression analyzer.
*
* @param rule the suppression rule to evaluate
* @return <code>true</code> if the rule should be retained; otherwise
* <code>false</code>
*/
abstract boolean filter(SuppressionRule rule);

/**
* Loads all the suppression rules files configured in the {@link Settings}.
*
Expand Down Expand Up @@ -160,7 +182,7 @@ private void loadSuppressionBaseData() throws SuppressionParseException {
if (in == null) {
throw new SuppressionParseException("Suppression rules `" + BASE_SUPPRESSION_FILE + "` could not be found");
}
ruleList = parser.parseSuppressionRules(in, this);
ruleList = parser.parseSuppressionRules(in);
} catch (SAXException | IOException ex) {
throw new SuppressionParseException("Unable to parse the base suppression data file", ex);
}
Expand Down Expand Up @@ -235,7 +257,7 @@ private List<SuppressionRule> loadSuppressionFile(final SuppressionParser parser
throw new SuppressionParseException(msg);
}
try {
list.addAll(parser.parseSuppressionRules(file, this));
list.addAll(parser.parseSuppressionRules(file));
} catch (SuppressionParseException ex) {
LOGGER.warn("Unable to parse suppression xml file '{}'", file.getPath());
LOGGER.warn(ex.getMessage());
Expand Down
Expand Up @@ -82,7 +82,7 @@ protected String getAnalyzerEnabledSettingKey() {

@Override
public boolean filter(SuppressionRule rule) {
return !rule.hasCpe();
return rule.hasCpe();
}

@Override
Expand Down
Expand Up @@ -76,7 +76,7 @@ protected String getAnalyzerEnabledSettingKey() {

@Override
public boolean filter(SuppressionRule rule) {
return !(rule.hasCve() || rule.hasCvssBelow() || rule.hasCwe() || rule.hasVulnerabilityName());
return rule.hasCve() || rule.hasCvssBelow() || rule.hasCwe() || rule.hasVulnerabilityName();
}

@Override
Expand Down
Expand Up @@ -104,10 +104,6 @@ public class SuppressionHandler extends DefaultHandler {
* The current node text being extracted from the element.
*/
private StringBuilder currentText;
/**
* The suppression rule filter.
*/
private final SuppressionRuleFilter filter;

/**
* Get the value of suppressionRules.
Expand All @@ -118,17 +114,6 @@ public List<SuppressionRule> getSuppressionRules() {
return suppressionRules;
}

/**
* Constructs a Suppression Handler.
*
* @param filter The suppression rule filter used when loading the
* suppression rules. This is used to differentiate vulnerability
* suppression rules from CPE suppression rules.
*/
public SuppressionHandler(SuppressionRuleFilter filter) {
this.filter = filter;
}

/**
* Handles the start element event.
*
Expand Down Expand Up @@ -176,8 +161,6 @@ public void endElement(String uri, String localName, String qName) throws SAXExc
case SUPPRESS:
if (rule.getUntil() != null && rule.getUntil().before(Calendar.getInstance())) {
LOGGER.info("Suppression is expired for rule: {}", rule);
} else if (filter != null && filter.filter(rule)) {
LOGGER.debug("Filtering {} for {}", rule.toString(), filter.getName());
} else {
suppressionRules.add(rule);
}
Expand Down
Expand Up @@ -77,14 +77,13 @@ public class SuppressionParser {
* contained.
*
* @param file an XML file containing suppression rules
* @param filter the suppression rule filter
* @return a list of suppression rules
* @throws SuppressionParseException thrown if the XML file cannot be parsed
*/
@SuppressFBWarnings(justification = "try with resource will clenaup the resources", value = {"OBL_UNSATISFIED_OBLIGATION"})
public List<SuppressionRule> parseSuppressionRules(File file, SuppressionRuleFilter filter) throws SuppressionParseException {
public List<SuppressionRule> parseSuppressionRules(File file) throws SuppressionParseException {
try (FileInputStream fis = new FileInputStream(file)) {
return parseSuppressionRules(fis, filter);
return parseSuppressionRules(fis);
} catch (SAXException | IOException ex) {
LOGGER.debug("", ex);
throw new SuppressionParseException(ex);
Expand All @@ -96,12 +95,11 @@ public List<SuppressionRule> parseSuppressionRules(File file, SuppressionRuleFil
* contained.
*
* @param inputStream an InputStream containing suppression rules
* @param filter a filter to use when loading suppression rules
* @return a list of suppression rules
* @throws SuppressionParseException thrown if the XML cannot be parsed
* @throws SAXException thrown if the XML cannot be parsed
*/
public List<SuppressionRule> parseSuppressionRules(InputStream inputStream, SuppressionRuleFilter filter)
public List<SuppressionRule> parseSuppressionRules(InputStream inputStream)
throws SuppressionParseException, SAXException {
try (
InputStream schemaStream13 = FileUtils.getResourceAsStream(SUPPRESSION_SCHEMA_1_3);
Expand All @@ -114,7 +112,7 @@ public List<SuppressionRule> parseSuppressionRules(InputStream inputStream, Supp
final String defaultEncoding = StandardCharsets.UTF_8.name();
final String charsetName = bom == null ? defaultEncoding : bom.getCharsetName();

final SuppressionHandler handler = new SuppressionHandler(filter);
final SuppressionHandler handler = new SuppressionHandler();
final SAXParser saxParser = XmlUtils.buildSecureSaxParser(schemaStream13, schemaStream12, schemaStream11, schemaStream10);
final XMLReader xmlReader = saxParser.getXMLReader();
xmlReader.setErrorHandler(new SuppressionErrorHandler());
Expand Down
Expand Up @@ -103,6 +103,29 @@ public class SuppressionRule {
*/
private Calendar until;

/**
* A flag whether or not the rule matched a dependency & CPE.
*/
private boolean matched = false;

/**
* Get the value of matched.
*
* @return the value of matched
*/
public boolean isMatched() {
return matched;
}

/**
* Set the value of matched.
*
* @param matched new value of matched
*/
public void setMatched(boolean matched) {
this.matched = matched;
}

/**
* Get the (@code{nullable}) value of until.
*
Expand Down Expand Up @@ -467,6 +490,7 @@ public void process(Dependency dependency) {
for (PropertyType c : this.cpe) {
if (identifierMatches(c, i)) {
if (!isBase()) {
matched = true;
if (this.notes != null) {
i.setNotes(this.notes);
}
Expand Down Expand Up @@ -507,7 +531,6 @@ public void process(Dependency dependency) {
removeVulns.add(v);
break;
}

}
}
if (!remove) {
Expand All @@ -524,13 +547,12 @@ public void process(Dependency dependency) {
}
}
}
if (remove) {
if (!isBase()) {
if (this.notes != null) {
v.setNotes(this.notes);
}
dependency.addSuppressedVulnerability(v);
if (remove && !isBase()) {
matched = true;
if (this.notes != null) {
v.setNotes(this.notes);
}
dependency.addSuppressedVulnerability(v);
}
}
removeVulns.forEach(dependency::removeVulnerability);
Expand Down Expand Up @@ -644,6 +666,9 @@ public String toString() {
if (sha1 != null) {
sb.append("sha1=").append(sha1).append(',');
}
if (packageUrl != null) {
sb.append("packageUrl=").append(packageUrl).append(',');
}
if (gav != null) {
sb.append("gav=").append(gav).append(',');
}
Expand Down

This file was deleted.