Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.XMLConstants;


class GoodDocumentBuilderFactory {
Expand Down Expand Up @@ -167,3 +168,14 @@ private void setFeatures(DocumentBuilderFactory dbf) throws Exception {
}

}

class GoodDocumentBuilderFactoryAccessExternalDtd {
public void blockExternalDtd() throws ParserConfigurationException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
//ok:documentbuilderfactory-disallow-doctype-decl-missing
dbf.newDocumentBuilder();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.XMLConstants;


class GoodDocumentBuilderFactory {
Expand Down Expand Up @@ -163,3 +164,14 @@ private void setFeatures(DocumentBuilderFactory dbf) throws Exception {
}

}

class GoodDocumentBuilderFactoryAccessExternalDtd {
public void blockExternalDtd() throws ParserConfigurationException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
//ok:documentbuilderfactory-disallow-doctype-decl-missing
dbf.newDocumentBuilder();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ rules:
...

$FACTORY.setFeature("http://xml.org/sax/features/external-general-entities", false);
- patterns:
- pattern: $FACTORY.setAttribute($ATTR, "")
- metavariable-regex:
metavariable: $ATTR
regex: ^(.*\.)?ACCESS_EXTERNAL_DTD$

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restrict the sanitizer to the JAXP XMLConstants symbol

When application code has any other expression ending in ACCESS_EXTERNAL_DTD, this regex suppresses the XXE finding without checking what property that expression represents. For example, a local String ACCESS_EXTERNAL_DTD = XMLConstants.ACCESS_EXTERNAL_SCHEMA; followed by dbf.setAttribute(ACCESS_EXTERNAL_DTD, "") matches this sanitizer even though external DTD/entity access remains enabled. Match XMLConstants.ACCESS_EXTERNAL_DTD explicitly, and handle the statically imported form only when the corresponding javax.xml.XMLConstants static import is present.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Recognize the property in static initializers

When a static factory field is hardened in a static initializer and consumed from another method, this sanitizer is in a different taint scope from newDocumentBuilder() and does not prevent the field-use source from firing. The source section explicitly has pattern-not-inside exceptions for the existing setFeature mitigations but no equivalent for setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""), so the new mitigation still produces a false positive in that established static-field pattern.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Recognize the property when applied by a helper

When callers pass the factory to a local hardening helper that sets ACCESS_EXTERNAL_DTD, this direct-call sanitizer does not match the helper invocation, so the later newDocumentBuilder() remains reported. The rule already has a separate helper-method sanitizer branch for each accepted setFeature defense, but this change does not add the new setAttribute defense there; the same abstraction demonstrated by GoodDocumentBuilderFactoryCtr2 therefore stops working for the newly supported mitigation.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Re-taint factories when external DTD access is restored

When code first sets ACCESS_EXTERNAL_DTD to "" but later changes the same property to a permissive value such as "all" before constructing the builder, this by-side-effect sanitizer permanently clears the factory's taint and the sink is missed even though external entity resolution is enabled again. The analogous insecure setFeature(..., true/false) mutations have dedicated rules, but there is no rule or taint source for a nonempty ACCESS_EXTERNAL_DTD assignment, so this change introduces an uncovered XXE false negative unless such assignments re-taint the factory.

Useful? React with 👍 / 👎.

- focus-metavariable: $FACTORY
- patterns:
- pattern-either:
Expand Down