diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java index bb9fa5a00..7279d11b8 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java @@ -17,15 +17,36 @@ */ package org.owasp.dependencycheck.analyzer; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; +import java.util.regex.Pattern; import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.dependency.Confidence; import org.owasp.dependencycheck.dependency.Dependency; import org.owasp.dependencycheck.dependency.Evidence; +import org.owasp.dependencycheck.suppression.PropertyType; +import org.owasp.dependencycheck.suppression.SuppressionParseException; +import org.owasp.dependencycheck.suppression.SuppressionParser; +import org.owasp.dependencycheck.utils.DownloadFailedException; +import org.owasp.dependencycheck.utils.Downloader; +import org.owasp.dependencycheck.utils.FileUtils; +import org.owasp.dependencycheck.utils.Settings; +import org.owasp.dependencycheck.xml.hints.VendorDuplicatingHintRule; +import org.owasp.dependencycheck.xml.hints.HintParseException; +import org.owasp.dependencycheck.xml.hints.HintParser; +import org.owasp.dependencycheck.xml.hints.HintRule; +import org.owasp.dependencycheck.xml.hints.Hints; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.SAXException; /** * @@ -62,18 +83,93 @@ public class HintAnalyzer extends AbstractAnalyzer implements Analyzer { public AnalysisPhase getAnalysisPhase() { return ANALYSIS_PHASE; } + + /** + * The initialize method does nothing for this Analyzer. + * + * @throws Exception thrown if there is an exception + */ + @Override + public void initialize() throws Exception { + super.initialize(); + loadHintRules(); + } // /** - * The HintAnalyzer uses knowledge about a dependency to add additional information to help in identification of identifiers - * or vulnerabilities. + * The Logger for use throughout the class + */ + private static final Logger LOGGER = LoggerFactory.getLogger(HintAnalyzer.class); + /** + * The name of the hint rule file + */ + private static final String HINT_RULE_FILE_NAME = "dependencycheck-base-hint.xml"; + /** + * The collection of hints. + */ + private Hints hints; + + /** + * The HintAnalyzer uses knowledge about a dependency to add additional + * information to help in identification of identifiers or vulnerabilities. * * @param dependency The dependency being analyzed * @param engine The scanning engine - * @throws AnalysisException is thrown if there is an exception analyzing the dependency. + * @throws AnalysisException is thrown if there is an exception analyzing + * the dependency. */ @Override public void analyze(Dependency dependency, Engine engine) throws AnalysisException { + for (HintRule hint : hints.getHintRules()) { + boolean shouldAdd = false; + for (Evidence given : hint.getGivenVendor()) { + if (dependency.getVendorEvidence().getEvidence().contains(given)) { + shouldAdd = true; + break; + } + } + if (!shouldAdd) { + for (Evidence given : hint.getGivenProduct()) { + if (dependency.getProductEvidence().getEvidence().contains(given)) { + shouldAdd = true; + break; + } + } + } + if (!shouldAdd) { + for (PropertyType pt : hint.getFilenames()) { + if (pt.matches(dependency.getFileName())) { + shouldAdd = true; + } + } + } + if (shouldAdd) { + for (Evidence e : hint.getAddVendor()) { + dependency.getVendorEvidence().addEvidence(e); + } + for (Evidence e : hint.getAddProduct()) { + dependency.getProductEvidence().addEvidence(e); + } + } + } + + final Iterator itr = dependency.getVendorEvidence().iterator(); + final List newEntries = new ArrayList(); + while (itr.hasNext()) { + final Evidence e = itr.next(); + for (VendorDuplicatingHintRule dhr : hints.getVendorDuplicatingHintRules()) { + if (dhr.getValue().equalsIgnoreCase(e.getValue(false))) { + newEntries.add(new Evidence(e.getSource() + " (hint)", + e.getName(), dhr.getDuplicate(), e.getConfidence())); + } + } + } + for (Evidence e : newEntries) { + dependency.getVendorEvidence().addEvidence(e); + } + + // + /* final Evidence springTest1 = new Evidence("Manifest", "Implementation-Title", "Spring Framework", @@ -154,7 +250,7 @@ public class HintAnalyzer extends AbstractAnalyzer implements Analyzer { if (product.contains(zendframeworkProduct)) { dependency.getProductEvidence().addEvidence("hint analyzer", "vendor", "zend_framework", Confidence.HIGHEST); } - + //sun/oracle problem final Iterator itr = dependency.getVendorEvidence().iterator(); final List newEntries = new ArrayList(); @@ -171,6 +267,83 @@ public class HintAnalyzer extends AbstractAnalyzer implements Analyzer { for (Evidence e : newEntries) { dependency.getVendorEvidence().addEvidence(e); } + */ + // + } + /** + * Loads the hint rules file. + * + * @throws SuppressionParseException thrown if the XML cannot be parsed. + */ + private void loadHintRules() throws HintParseException { + final HintParser parser = new HintParser(); + File file = null; + try { + hints = parser.parseHints(this.getClass().getClassLoader().getResourceAsStream(HINT_RULE_FILE_NAME)); + } catch (HintParseException ex) { + LOGGER.error("Unable to parse the base hint data file"); + LOGGER.debug("Unable to parse the base hint data file", ex); + } catch (SAXException ex) { + LOGGER.error("Unable to parse the base hint data file"); + LOGGER.debug("Unable to parse the base hint data file", ex); + } + final String filePath = Settings.getString(Settings.KEYS.SUPPRESSION_FILE); + if (filePath == null) { + return; + } + boolean deleteTempFile = false; + try { + final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE); + if (uriRx.matcher(filePath).matches()) { + deleteTempFile = true; + file = FileUtils.getTempFile("hint", "xml"); + final URL url = new URL(filePath); + try { + Downloader.fetchFile(url, file, false); + } catch (DownloadFailedException ex) { + Downloader.fetchFile(url, file, true); + } + } else { + file = new File(filePath); + if (!file.exists()) { + final InputStream fromClasspath = this.getClass().getClassLoader().getResourceAsStream(filePath); + if (fromClasspath != null) { + deleteTempFile = true; + file = FileUtils.getTempFile("hint", "xml"); + try { + org.apache.commons.io.FileUtils.copyInputStreamToFile(fromClasspath, file); + } catch (IOException ex) { + throw new HintParseException("Unable to locate suppressions file in classpath", ex); + } + } + } + } + + if (file != null) { + try { + Hints newHints = parser.parseHints(file); + hints.getHintRules().addAll(newHints.getHintRules()); + hints.getVendorDuplicatingHintRules().addAll(newHints.getVendorDuplicatingHintRules()); + LOGGER.debug("{} hint rules were loaded.", hints.getHintRules().size()); + LOGGER.debug("{} duplicating hint rules were loaded.", hints.getVendorDuplicatingHintRules().size()); + } catch (HintParseException ex) { + LOGGER.warn("Unable to parse hint rule xml file '{}'", file.getPath()); + LOGGER.warn(ex.getMessage()); + LOGGER.debug("", ex); + throw ex; + } + } + } catch (DownloadFailedException ex) { + throw new HintParseException("Unable to fetch the configured hint file", ex); + } catch (MalformedURLException ex) { + throw new HintParseException("Configured hint file has an invalid URL", ex); + } catch (IOException ex) { + throw new HintParseException("Unable to create temp file for hints", ex); + } finally { + if (deleteTempFile && file != null) { + FileUtils.delete(file); + } + } } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintErrorHandler.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintErrorHandler.java new file mode 100644 index 000000000..80818de45 --- /dev/null +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintErrorHandler.java @@ -0,0 +1,97 @@ +/* + * 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) 2016 Jeremy Long. All Rights Reserved. + */ +package org.owasp.dependencycheck.xml.hints; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +/** + * An XML parsing error handler. + * + * @author Jeremy Long + */ +public class HintErrorHandler implements ErrorHandler { + + /** + * The logger. + */ + private static final Logger LOGGER = LoggerFactory.getLogger(HintErrorHandler.class); + + /** + * Builds a prettier exception message. + * + * @param ex the SAXParseException + * @return an easier to read exception message + */ + private String getPrettyParseExceptionInfo(SAXParseException ex) { + + final StringBuilder sb = new StringBuilder(); + + 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.debug("", 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/xml/hints/HintHandler.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintHandler.java new file mode 100644 index 000000000..27a0a9d43 --- /dev/null +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintHandler.java @@ -0,0 +1,217 @@ +/* + * 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) 2016 Jeremy Long. All Rights Reserved. + */ +package org.owasp.dependencycheck.xml.hints; + +import java.util.ArrayList; +import java.util.List; +import org.owasp.dependencycheck.dependency.Confidence; +import org.owasp.dependencycheck.suppression.PropertyType; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +/** + * A handler to load hint rules. + * + * @author Jeremy Long + */ +public class HintHandler extends DefaultHandler { + + // + /** + * Element name. + */ + private static final String HINT = "hint"; + /** + * Element name. + */ + private static final String GIVEN = "given"; + /** + * Element name. + */ + private static final String ADD = "add"; + /** + * Element name. + */ + private static final String EVIDENCE = "evidence"; + /** + * Element name. + */ + private static final String FILE_NAME = "fileName"; + /** + * Element name. + */ + private static final String VENDOR_DUPLICATING_RULE = "vendorDuplicatingHint"; + /** + * Attribute name. + */ + private static final String DUPLIACE = "dupliace"; + /** + * Attribute name. + */ + private static final String VENDOR = "vendor"; + /** + * Attribute name. + */ + private static final String CONFIDENCE = "confidence"; + /** + * Attribute name. + */ + private static final String VALUE = "value"; + /** + * Attribute name. + */ + private static final String NAME = "name"; + /** + * Attribute name. + */ + private static final String SOURCE = "source"; + /** + * Attribute name. + */ + private static final String TYPE = "type"; + /** + * Attribute name. + */ + private static final String CASE_SENSITIVE = "caseSensitive"; + /** + * Attribute name. + */ + private static final String REGEX = "regex"; + /** + * Attribute name. + */ + private static final String CONTAINS = "contains"; + // + + /** + * The list of hint rules. + */ + private final List hintRules = new ArrayList(); + + /** + * Returns the list of hint rules. + * + * @return the value of hintRules + */ + public List getHintRules() { + return hintRules; + } + + /** + * The list of vendor duplicating hint rules. + */ + private final List vendorDuplicatingHintRules = new ArrayList(); + + /** + * Returns the list of vendor duplicating hint rules. + * + * @return the list of vendor duplicating hint rules + */ + public List getVendorDuplicatingHintRules() { + return vendorDuplicatingHintRules; + } + + /** + * The current rule being read. + */ + private HintRule rule; + /** + * The current state of the parent node (to differentiate between 'add' and + * 'given'). + */ + private boolean inAddNode = false; + + /** + * 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 attr 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 attr) throws SAXException { + if (HINT.equals(qName)) { + rule = new HintRule(); + } else if (ADD.equals(qName)) { + inAddNode = true; + } else if (GIVEN.equals(qName)) { + inAddNode = false; + } else if (EVIDENCE.equals(qName)) { + final String hintType = attr.getValue(TYPE); + if (VENDOR.equals(hintType)) { + if (inAddNode) { + rule.addAddVendor(attr.getValue(SOURCE), + attr.getValue(NAME), + attr.getValue(VALUE), + Confidence.valueOf(attr.getValue(CONFIDENCE))); + } else { + rule.addGivenVendor(attr.getValue(SOURCE), + attr.getValue(NAME), + attr.getValue(VALUE), + Confidence.valueOf(attr.getValue(CONFIDENCE))); + } + } else if (inAddNode) { + rule.addAddProduct(attr.getValue(SOURCE), + attr.getValue(NAME), + attr.getValue(VALUE), + Confidence.valueOf(attr.getValue(CONFIDENCE))); + } else { + rule.addGivenProduct(attr.getValue(SOURCE), + attr.getValue(NAME), + attr.getValue(VALUE), + Confidence.valueOf(attr.getValue(CONFIDENCE))); + } + } else if (FILE_NAME.equals(qName)) { + final PropertyType pt = new PropertyType(); + pt.setValue(attr.getValue(CONTAINS)); + if (attr.getLength() > 0) { + final String regex = attr.getValue(REGEX); + if (regex != null) { + pt.setRegex(Boolean.parseBoolean(regex)); + } + final String caseSensitive = attr.getValue(CASE_SENSITIVE); + if (caseSensitive != null) { + pt.setCaseSensitive(Boolean.parseBoolean(caseSensitive)); + } + } + rule.addFilename(pt); + } else if (VENDOR_DUPLICATING_RULE.equals(qName)) { + vendorDuplicatingHintRules.add(new VendorDuplicatingHintRule(attr.getValue(VALUE), attr.getValue(DUPLIACE))); + } + } + + /** + * Handles the end element event. + * + * @param uri the element's uri + * @param localName the local name + * @param qName the qualified name + * @throws SAXException thrown if there is an exception processing the + * element + */ + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (HINT.equals(qName) && rule != null) { + hintRules.add(rule); + rule = null; + } + } +} diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintParseException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintParseException.java new file mode 100644 index 000000000..4b5b19c6e --- /dev/null +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintParseException.java @@ -0,0 +1,68 @@ +/* + * 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) 2016 Jeremy Long. All Rights Reserved. + */ +package org.owasp.dependencycheck.xml.hints; + +import java.io.IOException; + +/** + * An exception used when parsing a suppression rule file fails. + * + * @author Jeremy Long + */ +public class HintParseException extends IOException { + + /** + * The serial version UID for serialization. + */ + private static final long serialVersionUID = 1L; + + /** + * Creates a new SuppressionParseException. + */ + public HintParseException() { + super(); + } + + /** + * Creates a new SuppressionParseException. + * + * @param msg a message for the exception. + */ + public HintParseException(String msg) { + super(msg); + } + + /** + * Creates a new SuppressionParseException. + * + * @param ex the cause of the parse exception + */ + public HintParseException(Throwable ex) { + super(ex); + } + + /** + * Creates a new SuppressionParseException. + * + * @param msg a message for the exception. + * @param ex the cause of the parse exception + */ + public HintParseException(String msg, Throwable ex) { + super(msg, ex); + } +} diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintParser.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintParser.java new file mode 100644 index 000000000..5eb0aa6bb --- /dev/null +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintParser.java @@ -0,0 +1,146 @@ +/* + * 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) 2016 Jeremy Long. All Rights Reserved. + */ +package org.owasp.dependencycheck.xml.hints; + +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 javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; + +/** + * A simple validating parser for XML Hint Rules. + * + * @author Jeremy Long + */ +public class HintParser { + + /** + * The logger. + */ + private static final Logger LOGGER = LoggerFactory.getLogger(HintParser.class); + /** + * 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"; + + /** + * The schema for the hint XML files. + */ + private static final String HINT_SCHEMA = "schema/dependency-hint.1.0.xsd"; + + /** + * Parses the given XML file and returns a list of the hints contained. + * + * @param file an XML file containing hints + * @return a list of hint rules + * @throws HintParseException thrown if the XML file cannot be parsed + */ + public Hints parseHints(File file) throws HintParseException { + FileInputStream fis = null; + try { + fis = new FileInputStream(file); + return parseHints(fis); + } catch (IOException ex) { + LOGGER.debug("", ex); + throw new HintParseException(ex); + } catch (SAXException ex) { + throw new HintParseException(ex); + } finally { + if (fis != null) { + try { + fis.close(); + } catch (IOException ex) { + LOGGER.debug("Unable to close stream", ex); + } + } + } + } + + /** + * Parses the given XML stream and returns a list of the hint rules + * contained. + * + * @param inputStream an InputStream containing hint rules + * @return a list of hint rules + * @throws HintParseException thrown if the XML cannot be parsed + * @throws SAXException thrown if the XML cannot be parsed + */ + public Hints parseHints(InputStream inputStream) throws HintParseException, SAXException { + try { + final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream(HINT_SCHEMA); + final HintHandler handler = new HintHandler(); + final SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setNamespaceAware(true); + factory.setValidating(true); + final SAXParser saxParser = factory.newSAXParser(); + saxParser.setProperty(HintParser.JAXP_SCHEMA_LANGUAGE, HintParser.W3C_XML_SCHEMA); + saxParser.setProperty(HintParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream)); + final XMLReader xmlReader = saxParser.getXMLReader(); + xmlReader.setErrorHandler(new HintErrorHandler()); + xmlReader.setContentHandler(handler); + + final Reader reader = new InputStreamReader(inputStream, "UTF-8"); + final InputSource in = new InputSource(reader); + + xmlReader.parse(in); + final Hints hints = new Hints(); + hints.setHintRules(handler.getHintRules()); + hints.setVendorDuplicatingHintRules(handler.getVendorDuplicatingHintRules()); + return hints; + } catch (ParserConfigurationException ex) { + LOGGER.debug("", ex); + throw new HintParseException(ex); + } catch (SAXException ex) { + if (ex.getMessage().contains("Cannot find the declaration of element 'hints'.")) { + throw ex; + } else { + LOGGER.debug("", ex); + throw new HintParseException(ex); + } + } catch (FileNotFoundException ex) { + LOGGER.debug("", ex); + throw new HintParseException(ex); + } catch (IOException ex) { + LOGGER.debug("", ex); + throw new HintParseException(ex); + } + } +} diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/package-info.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/package-info.java new file mode 100644 index 000000000..834876424 --- /dev/null +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains classes used to parse the hints file to add evidence to dependencies. + */ +package org.owasp.dependencycheck.xml.hints; diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java index 807b027ed..6f24387b0 100644 --- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java +++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java @@ -189,9 +189,13 @@ public final class Settings { */ public static final String MAX_DOWNLOAD_THREAD_POOL_SIZE = "max.download.threads"; /** - * The key for a list of suppression files. + * The key for the suppression file. */ public static final String SUPPRESSION_FILE = "suppression.file"; + /** + * The key for the hint file. + */ + public static final String HINTS_FILE = "hints.file"; /** * The properties key for whether the Jar Analyzer is enabled. */