Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
8 changes: 6 additions & 2 deletions src/main/java/org/apache/commons/xml/XmlFactories.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,14 @@
* <ul>
* <li><strong>External DTDs are not fetched.</strong></li>
* <li><strong>External entities are not resolved.</strong></li>
* <li><strong>Internal entity expansion is bounded</strong> by the JDK's default limit, so DoS payloads such as Billion Laughs are rejected before they
* exhaust resources.</li>
* <li><strong>Internal entity expansion is bounded</strong> by the platform's secure-processing limit, so DoS payloads such as Billion Laughs are rejected
* before they exhaust resources.</li>
* </ul>
*
* <p>These guarantees are defined on OpenJDK 8 or later (and JDK distributions built from it). No version of Android supports
* {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING}, so on Android (API level 19 or later) the hardening is applied as best-effort without a guarantee,
* tested as complete starting with API level 33; see the threat model's "Assumptions about the environment".</p>
*
* <p>The guarantees hold whether or not the caller opts into DTD validation
* ({@link javax.xml.parsers.DocumentBuilderFactory#setValidating(boolean) setValidating(true)}) or attaches a compiled XSD via
* {@link javax.xml.parsers.DocumentBuilderFactory#setSchema(javax.xml.validation.Schema) setSchema}: every external resource the validation would otherwise
Expand Down
12 changes: 12 additions & 0 deletions src/site/markdown/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,18 @@ it resolves to empty content,
so the parse continues without it
(see Configuration below).

### Supported runtimes

The library requires OpenJDK 8 or later (or a JDK distribution built from it), or Android API level 19 or later.

The security guarantees are defined only on the OpenJDK family
(see the [Threat Model](threat_model.html)).
No version of Android supports `FEATURE_SECURE_PROCESSING`
(so states [Android's own documentation](https://developer.android.com/reference/javax/xml/parsers/DocumentBuilderFactory#setFeature%28java.lang.String,%20boolean%29)),
so the library secures the platform's parsers as best-effort.
Android's `XmlPullParser` API is not supported:
it is not a JAXP API.

### Supported implementations

Out of the box the library recognizes the stock JDK JAXP implementations, Apache Xerces 2.x, Woodstox, and Saxon-HE. If
Expand Down
47 changes: 38 additions & 9 deletions src/site/markdown/threat_model.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ because your reader's settings are indistinguishable from configuration you chos

### What is in scope

- The hardening recipes applied by `XmlFactories` to the JAXP implementations it recognizes (stock JDK, Apache Xerces,
Xalan, Saxon, Woodstox, and Android's Expat/KXmlParser).
- The hardening recipes applied by `XmlFactories` to the JAXP implementations it recognizes (stock JDK, Apache Xerces, Xalan, Saxon, and Woodstox).
The recipes for Android's Expat/KXmlParser are applied as best-effort and carry no guarantee
(see **Supported runtimes** under [Assumptions about the environment](#assumptions-about-the-environment)).
- A factory returned by `XmlFactories`, used as delivered, that fails to provide a guarantee the Javadoc states it
provides.

Expand All @@ -88,6 +89,21 @@ or read environment variables of its own:
each `XmlFactories` method only configures and returns a JAXP factory.
Which hardening recipe applies depends on the JAXP implementation present on the classpath.

**Supported runtimes**

The guarantees are defined on a single runtime family:
OpenJDK 8 or later (and JDK distributions built from it).
On these runtimes the recognized parsers apply the processing limits the guarantees rely on.

Android, on every API level, carries no guarantee:
no version of Android supports `FEATURE_SECURE_PROCESSING`
(so states [Android's own documentation](https://developer.android.com/reference/javax/xml/parsers/DocumentBuilderFactory#setFeature%28java.lang.String,%20boolean%29)),
the setting the guaranteed processing limits build on.
The library still hardens Android's parsers as best-effort,
tested as complete starting with API level 33
(see [Supported runtimes](index.html) on the main page),
but a report demonstrated only on Android is [out of scope](#what-is-out-of-scope) on any API level.

**System properties that modify behavior**

The library reads a single system property of its own,
Expand All @@ -99,9 +115,10 @@ Either way the resource is not fetched,
so the property selects an error-reporting style,
not a security posture.

The library enables secure processing (`FEATURE_SECURE_PROCESSING`) on every
recognized parser and leaves the resulting processing limits (entity expansion, element depth, attribute count, and
similar) at the implementation's own secure default. Those defaults differ by implementation, and on the stock JDK by
The library enables secure processing (`FEATURE_SECURE_PROCESSING`) on every recognized parser that supports it
(no Android parser does, see **Supported runtimes** above)
and leaves the resulting processing limits (entity expansion, element depth, attribute count, and similar)
at the implementation's own secure default. Those defaults differ by implementation, and on the stock JDK by
JDK version and the standard `jdk.xml.*` limit properties the JDK itself reads:

- On the stock JDK, secure processing honors the `jdk.xml.*` limit properties (for example `jdk.xml.entityExpansionLimit`,
Expand All @@ -111,7 +128,8 @@ JDK version and the standard `jdk.xml.*` limit properties the JDK itself reads:
- The bundled parsers apply their own hardcoded secure defaults instead (for example external Xerces and Woodstox cap
entity expansion at `100000`) and do not read `jdk.xml.*`.

Every one of these defaults still bounds entity expansion tightly enough to reject entity-expansion denial of service
On the supported runtimes (see **Supported runtimes** above),
every one of these defaults still bounds entity expansion tightly enough to reject entity-expansion denial of service
such as Billion Laughs.

**Reserved settings (must not be loosened)**
Expand Down Expand Up @@ -214,6 +232,10 @@ and reports against a factory reconfigured in any of the ways below are out of s
before wrapping it in a `SAXSource`.
- The behavior of a JAXP implementation that `XmlFactories` does not recognize (it throws rather than returning an
unhardened factory), and any defect in the underlying JAXP implementation itself.
- **Android, on any API level.**
No version of Android supports `FEATURE_SECURE_PROCESSING`,
so the hardening there is best-effort and no guarantee is defined
(see **Supported runtimes** under [Assumptions about the environment](#assumptions-about-the-environment)).

### Downstream responsibility

Expand All @@ -233,6 +255,9 @@ are **not** vulnerabilities under this model:
- XXE, external-entity, SSRF-through-external-reference, or entity-expansion (Billion Laughs) reports against
a factory used as delivered. Blocking these is exactly what the hardening does. A working proof against an
unmodified instance is a `VALID` finding (see below); a scanner that pattern-matches on parser type is not.
- A report demonstrated only on Android,
where the hardening is best-effort and no guarantee is defined
(see **Supported runtimes** under [Assumptions about the environment](#assumptions-about-the-environment)).
- Reports against an instance after the caller installed a resolver (including the `DefaultHandler` passed to
`SAXParser.parse(..., DefaultHandler)`) or loosened a reserved setting.
- Reports demonstrated on a parser the reporter configured themselves:
Expand All @@ -257,13 +282,17 @@ A report judged against this model receives exactly one of:
| `OUT-OF-SCOPE: reconfigured` | A reserved setting was loosened, or a resolver was installed, on the factory or a produced instance before the reported behavior (see [What is out of scope](#what-is-out-of-scope)). |
| `OUT-OF-SCOPE: caller input` | The behavior follows from a top-level URI, a parser instance the caller constructed outside the library, or other input the caller passed directly to a parse call. |
| `OUT-OF-SCOPE: foreign implementation` | The behavior is in a JAXP implementation `XmlFactories` does not recognize, or in the underlying JAXP implementation itself. |
| `OUT-OF-SCOPE: unsupported runtime` | The behavior is demonstrated only on a runtime the guarantees are not defined on, such as Android on any API level (see **Supported runtimes** under [Assumptions about the environment](#assumptions-about-the-environment)). |
| `MODEL-GAP` | The report fits none of the above. The model is then incomplete: revise it rather than making an ad-hoc call. |

### Conditions that would change this model

Revise this model when any of the following change: a new `XmlFactories` factory method or other public
surface; support for a JAXP implementation beyond those listed under [What is in scope](#what-is-in-scope);
a new reserved setting; or a report that cannot be routed to one of the dispositions above.
Revise this model when any of the following change:
a new `XmlFactories` factory method or other public surface;
support for a JAXP implementation beyond those listed under [What is in scope](#what-is-in-scope);
a change to the supported runtimes (see **Supported runtimes** under [Assumptions about the environment](#assumptions-about-the-environment));
a new reserved setting;
or a report that cannot be routed to one of the dispositions above.

## Security Vulnerabilities

Expand Down
Loading