Skip to content

Commit 0e21e08

Browse files
authored
Merge pull request #22 from ppkarwasz/feature/remove-limits-class
[COMMONSXML-2] Remove `Limits` class and related functionality
2 parents a00db73 + d7e4262 commit 0e21e08

9 files changed

Lines changed: 201 additions & 612 deletions

File tree

src/main/java/org/apache/commons/xml/DocumentBuilderHardener.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@
3737
* <li><strong>FSP</strong>: required. It switches on the implementation's built-in security manager, which is what carries the processing limits.</li>
3838
* <li><strong>{@code XERCES_LOAD_EXTERNAL_DTD}</strong>: optional. Where supported, it skips the external DTD subset on non-validating parsers so a
3939
* DOCTYPE-only document parses without a fetch attempt. If not supported, the fetch will throw instead, due to the following settings.</li>
40-
* <li><strong>Limits</strong>: applied best-effort by {@link Limits#tryApply(DocumentBuilderFactory)}, which adapts to the JDK attribute limits or Xerces'
41-
* {@code SecurityManager} as appropriate.</li>
4240
* <li><strong>Deny-all resolver floor</strong>: every produced {@link DocumentBuilder} is wrapped by a {@link HardeningDocumentBuilderFactory} that keeps a
4341
* deny-all {@link EntityResolver} floor. That floor blocks external DTD, entity, schema and {@code xi:include} fetches in one place: the stock JDK's
4442
* XInclude processor ignores {@code ACCESS_EXTERNAL_*} and consults the {@link EntityResolver} instead, so no {@code ACCESS_EXTERNAL_*} attributes are
@@ -60,8 +58,6 @@ static DocumentBuilderFactory harden(final DocumentBuilderFactory factory) {
6058
}
6159
// Required: enables the implementation's security manager, which carries the limits.
6260
setFeature(factory, XMLConstants.FEATURE_SECURE_PROCESSING, true);
63-
// Optional, implementation-based: JDK attribute limits or Xerces' SecurityManager.
64-
Limits.tryApply(factory);
6561
// Optional: skip the external DTD subset on non-validating parsers so DOCTYPE-only documents parse without a blocked fetch attempt.
6662
setOptionalFeature(factory, XERCES_LOAD_EXTERNAL_DTD, false);
6763
// Required: HardeningDocumentBuilderFactory installs a deny-all EntityResolver floor on every DocumentBuilder.

src/main/java/org/apache/commons/xml/JaxpSetters.java

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ final class JaxpSetters {
4141
private interface ThrowingAction {
4242
void run() throws Exception;
4343
}
44-
private static final String KIND_ATTRIBUTE = "attribute";
44+
4545
private static final String KIND_FEATURE = "feature";
4646

4747
private static void apply(final Object factory, final String kind, final String name, final ThrowingAction action) {
@@ -52,10 +52,6 @@ private static void apply(final Object factory, final String kind, final String
5252
}
5353
}
5454

55-
static void setAttribute(final DocumentBuilderFactory factory, final String attribute, final Object value) {
56-
apply(factory, KIND_ATTRIBUTE, attribute, () -> factory.setAttribute(attribute, value));
57-
}
58-
5955
static void setFeature(final DocumentBuilderFactory factory, final String feature, final boolean value) {
6056
apply(factory, KIND_FEATURE, feature, () -> factory.setFeature(feature, value));
6157
}
@@ -88,22 +84,6 @@ static void setFeature(final XMLReader reader, final String feature, final boole
8884
apply(reader, KIND_FEATURE, feature, () -> reader.setFeature(feature, value));
8985
}
9086

91-
static void setOptionalAttribute(final DocumentBuilderFactory factory, final String attribute, final Object value) {
92-
try {
93-
factory.setAttribute(attribute, value);
94-
} catch (final Exception e) {
95-
// Ignored: the implementation does not recognize this attribute.
96-
}
97-
}
98-
99-
static void setOptionalAttribute(final TransformerFactory factory, final String attribute, final Object value) {
100-
try {
101-
factory.setAttribute(attribute, value);
102-
} catch (final Exception e) {
103-
// Ignored: the implementation does not recognize this attribute.
104-
}
105-
}
106-
10787
static void setOptionalFeature(final DocumentBuilderFactory factory, final String feature, final boolean value) {
10888
try {
10989
factory.setFeature(feature, value);

src/main/java/org/apache/commons/xml/Limits.java

Lines changed: 0 additions & 395 deletions
This file was deleted.

src/main/java/org/apache/commons/xml/SAXParserHardener.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@
5151
* processing limits.</li>
5252
* <li><strong>{@code XERCES_LOAD_EXTERNAL_DTD}</strong>: optional. Where supported, it skips the external DTD subset on non-validating parsers so a
5353
* DOCTYPE-only document parses without a fetch attempt. If not supported, the fetch will throw instead, due to the following settings.</li>
54-
* <li><strong>Limits</strong>: applied best-effort by {@link Limits#tryApply(XMLReader)}, which adapts to the JDK limit properties or Xerces'
55-
* {@code SecurityManager} as appropriate.</li>
5654
* <li><strong>Deny-all resolver floor</strong>: every reader is wrapped in a {@link HardeningXMLReader} that keeps a deny-all {@link EntityResolver} floor.
5755
* That floor blocks external DTD, entity, schema and {@code xi:include} fetches in one place: the stock JDK's XInclude processor ignores
5856
* {@code ACCESS_EXTERNAL_*} and consults the {@link EntityResolver} instead, so no {@code ACCESS_EXTERNAL_*} properties are needed here. A caller can
@@ -176,8 +174,6 @@ static XMLReader hardenReader(final XMLReader reader) {
176174
setFeature(reader, XMLConstants.FEATURE_SECURE_PROCESSING, true);
177175
// Optional: skip the external DTD subset on non-validating parsers so DOCTYPE-only documents parse without a blocked fetch attempt.
178176
setOptionalFeature(reader, XERCES_LOAD_EXTERNAL_DTD, false);
179-
// Optional, implementation-based: JDK limit properties or Xerces' SecurityManager.
180-
Limits.tryApply(reader);
181177
// Required: HardeningXMLReader installs a deny-all EntityResolver floor on the reader.
182178
// That floor blocks external DTD, entity, schema and xi:include fetches in one place: no ACCESS_EXTERNAL_* properties are needed here.
183179
// Callers can chain their resolvers, but not override the floor.

src/main/java/org/apache/commons/xml/StaxHardener.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@
2929
* <p>Rather than branching on the implementation class, {@link #harden(XMLInputFactory)} consolidates the JDK Zephyr and Woodstox recipes into one pass that
3030
* probes which properties each factory accepts and adapts:</p>
3131
* <ul>
32-
* <li><strong>Limits</strong>: applied best-effort by {@link Limits#tryApply(XMLInputFactory)}, which sets both the JDK and the Woodstox limit properties;
33-
* each implementation honors its own and rejects the other's.</li>
3432
* <li><strong>External DTD subset</strong>: skipped via Zephyr's {@value #ZEPHYR_IGNORE_EXTERNAL_DTD} (best-effort), so a DOCTYPE-only document parses
3533
* without a fetch attempt instead of tripping the deny-all resolver below. Woodstox skips it through {@value #WSTX_DTD_RESOLVER} instead.</li>
3634
* <li><strong>External entities</strong>: denied through a non-removable {@link Resolvers.FallbackDenyXMLResolver} floor on the entity-resolution hook,
@@ -82,8 +80,6 @@ protected Object onUnresolved(final String publicID, final String systemID, fina
8280
}
8381

8482
static XMLInputFactory harden(final XMLInputFactory factory) {
85-
// Optional, implementation-based: JDK limit properties or Woodstox limit properties.
86-
Limits.tryApply(factory);
8783
// Optional: Zephyr's StAX equivalent of XERCES_LOAD_EXTERNAL_DTD=false skips the external DTD subset entirely.
8884
setOptionalProperty(factory, ZEPHYR_IGNORE_EXTERNAL_DTD, true);
8985

src/main/java/org/apache/commons/xml/TransformerHardener.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@
4343
* hardening surface is reachable only through a vendor API.</li>
4444
* <li><strong>FSP</strong> ({@link XMLConstants#FEATURE_SECURE_PROCESSING}): required. On XSLTC it enables the runtime evaluator limits; on Xalan it disables
4545
* reflection-based extension functions.</li>
46-
* <li><strong>Limits</strong>: applied best-effort by {@link Limits#tryApply(TransformerFactory)}. XSLTC honors the JDK attribute limits; Xalan ignores them
47-
* (its caps come from FSP).</li>
4846
* <li><strong>{@link Resolvers.FallbackDenyURIResolver} floor</strong>: required. A deny-all {@link URIResolver} floor, installed by
4947
* {@link HardeningTransformerFactory} and carried onto every produced {@link Transformer}, blocks {@code xsl:import}/{@code xsl:include} at compile time
5048
* and {@code document()} at runtime, the one channel both XSLTC and Xalan route through. A caller-set {@link URIResolver} is routed through the floor
@@ -72,8 +70,6 @@ static TransformerFactory harden(final TransformerFactory factory) {
7270
}
7371
// Required: enables secure processing (XSLTC runtime limits; Xalan's extension-function block).
7472
setFeature(factory, XMLConstants.FEATURE_SECURE_PROCESSING, true);
75-
// Best-effort: JDK's XSLTC honors the JDK attribute limits, pinning them to JDK 25 secure values; Xalan ignores them.
76-
Limits.tryApply(factory);
7773
// Required: source/stylesheet parsing provisions its own SAX reader otherwise; the wrapper routes every Source through a hardened one and installs the
7874
// deny-all URIResolver floor (blocking xsl:import/include at compile time and document() at runtime) that a caller-set resolver cannot remove.
7975
return new HardeningTransformerFactory((SAXTransformerFactory) factory);

src/site/markdown/threat_model.md

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -72,27 +72,29 @@ defends against: that is the reason reconfiguration moves a report
7272

7373
### Assumptions about the environment
7474

75-
The library does not open network connections, spawn processes, install signal handlers, or read environment variables
76-
of its own: each `XmlFactories` method only configures and returns a JAXP factory, and reads the JDK system properties
77-
listed below. Which hardening recipe applies depends on the JAXP implementation present on the classpath.
75+
The library does not open network connections,
76+
spawn processes,
77+
install signal handlers,
78+
or read environment variables of its own:
79+
each `XmlFactories` method only configures and returns a JAXP factory.
80+
Which hardening recipe applies depends on the JAXP implementation present on the classpath.
7881

7982
**System properties that modify behavior**
8083

81-
When a factory or parser is created, the library reads the following JDK system properties and pins each value on every
82-
recognized parser, including bundled ones that ignore `jdk.xml.*` on their own. If a property is unset, the fixed value
83-
shown applies (matching the JDK 25 secure default), regardless of the JDK in use. These properties are trusted
84-
deployment configuration: an operator may set one to tighten (or loosen) a limit globally, but loosening through one is
85-
reconfiguration, treated like loosening any other reserved setting (see [What is out of scope](#what-is-out-of-scope)).
86-
87-
- `jdk.xml.elementAttributeLimit`: `200`
88-
- `jdk.xml.entityExpansionLimit`: `2500`
89-
- `jdk.xml.entityReplacementLimit`: `100000`
90-
- `jdk.xml.maxElementDepth`: `100`
91-
- `jdk.xml.maxGeneralEntitySizeLimit`: `100000`
92-
- `jdk.xml.maxOccurLimit`: `5000`
93-
- `jdk.xml.maxParameterEntitySizeLimit`: `15000`
94-
- `jdk.xml.maxXMLNameLimit`: `1000`
95-
- `jdk.xml.totalEntitySizeLimit`: `100000`
84+
The library reads no system property of its own. It enables secure processing (`FEATURE_SECURE_PROCESSING`) on every
85+
recognized parser and leaves the resulting processing limits (entity expansion, element depth, attribute count, and
86+
similar) at the implementation's own secure default. Those defaults differ by implementation, and on the stock JDK by
87+
JDK version and the standard `jdk.xml.*` limit properties the JDK itself reads:
88+
89+
- On the stock JDK, secure processing honors the `jdk.xml.*` limit properties (for example `jdk.xml.entityExpansionLimit`,
90+
default `2500` on JDK 25 and `64000` on JDK 8 through 21). These are trusted deployment configuration: an operator may
91+
set one to tighten (or loosen) a limit globally, but loosening through one is reconfiguration, treated like loosening
92+
any other reserved setting (see [What is out of scope](#what-is-out-of-scope)).
93+
- The bundled parsers apply their own hardcoded secure defaults instead (for example external Xerces and Woodstox cap
94+
entity expansion at `100000`) and do not read `jdk.xml.*`.
95+
96+
Every one of these defaults still bounds entity expansion tightly enough to reject entity-expansion denial of service
97+
such as Billion Laughs.
9698

9799
**Reserved settings (must not be loosened)**
98100

@@ -115,7 +117,7 @@ produces, breaks the hardening for that instance.
115117
- `javax.xml.stream.isSupportingExternalEntities`
116118
- `javax.xml.stream.supportDTD`
117119
- `jdk.xml.overrideDefaultParser`
118-
- the JDK processing-limit properties listed above
120+
- the implementation's secure-processing limits (entity expansion, element depth, attribute count, and similar)
119121

120122
This list is not exhaustive:
121123
any other feature, attribute, property, or system property that
@@ -226,8 +228,7 @@ A report judged against this model receives exactly one of:
226228

227229
Revise this model when any of the following change: a new `XmlFactories` factory method or other public
228230
surface; support for a JAXP implementation beyond those listed under [What is in scope](#what-is-in-scope);
229-
a change in the pinned processing-limit defaults this list records; a new reserved setting; or a
230-
report that cannot be routed to one of the dispositions above.
231+
a new reserved setting; or a report that cannot be routed to one of the dispositions above.
231232

232233
## Security Vulnerabilities
233234

0 commit comments

Comments
 (0)