Hello!
As I was refactoring code to circumvent the problems in java.lang.IllegalArgumentException: Error: missing bug code for keySECXXEVAL · Issue #983 · spotbugs/sonar-findbugs · GitHub, I came across this false positive.
I’ve found that some java rules, like java:2755, findsecbugs:XXE_SCHEMA_FACTORY or findsecbugs:XXE_DOCUMENT (among others, there’s a bunch in this category) may falsely trigger when the safe configuration of a relevant object like SchemaFactory is done in a separate method.
Consider the following code that I extracted from my project:
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import javax.xml.XMLConstants;
import javax.xml.catalog.CatalogFeatures;
import javax.xml.transform.dom.DOMSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import java.io.IOException;
public enum XmlSchemaValidationSQ {
; // Trick to make a purely static class without explicitly hiding the constructor
public static final String CATALOG_FILE = XmlSchemaValidationSQ.class.getClassLoader()
.getResource("catalog.xml").toString();
private static final String SCHEMA_FILE = "custom-schema.xsd";
public static void validateAgainstCustomSchema(Document xmlDocument) {
try {
var schemaFactory = getSafeSchemaFactory();
var schemaFile = XmlSchemaValidationSQ.class.getClassLoader()
.getResource(XmlSchemaValidationSQ.SCHEMA_FILE);
var schema = schemaFactory.newSchema(schemaFile);
doValidation(xmlDocument, schema);
} catch (IOException | SAXException e) {
throw new RuntimeException(e);
}
}
private static SchemaFactory getSafeSchemaFactory() throws SAXNotSupportedException, SAXNotRecognizedException {
var schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
// to be compliant, completely disable DOCTYPE declaration:
schemaFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
// or prohibit the use of all protocols by external entities:
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
schemaFactory.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), CATALOG_FILE);
return schemaFactory;
}
private static void doValidation(Document xmlDocument, Schema schema) throws SAXException, IOException {
var validator = schema.newValidator();
validator.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
validator.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
validator.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), CATALOG_FILE);
validator.validate(new DOMSource(xmlDocument));
}
}
In SonarQube 10.5.1, the line var schema = schemaFactory.newSchema(schemaFile);
triggers rule findbugs:XXE_SCHEMA_FACTORY. However, the only path possible to this line leads past getSafeSchemaFactory()
which sets the proper properties as listed by the rule.
Somewhat surprisingly, SonarLint (10.6.2.78685) does not find this problem, but perhaps it does not apply the findsecbugs rules even though it’s bound to our SonarQube instance?
In any case, this is a false positive. The schemaFactory used in the respective line has been configured with the right setProperty
calls and that can be proven.
Edit: As a clarification; inlining getSafeSchemaFactory()
leads to the code not triggering the findbugs:XXE_SCHEMA_FACTORY rule. This strengthens my feeling that this is in fact a false positive.