Copilot commented on code in PR #22:
URL: https://github.com/apache/commons-xml/pull/22#discussion_r3552277372
##########
src/test/java/org/apache/commons/xml/BillionLaughsTest.java:
##########
@@ -24,237 +24,192 @@
/**
* Checks whether parsers reject a Billion Laughs payload (nested entity
expansion in the internal DTD subset).
*
- * <p>Two fixtures are used:</p>
+ * <p>Each {@code hardened*} test asserts the library blocks the payload; its
{@code unconfigured*} positive control asserts the same payload parses once the
+ * limit is disabled, so a block reflects the hardening rather than a broken
wrapper. The library pins no custom entity-expansion limit; each parser keeps
its own
+ * secure-processing default, which varies by implementation: {@code 2,500}
(stock JDK), {@code 64,000} (external Xerces under {@code
FEATURE_SECURE_PROCESSING}),
+ * {@code 100,000} (external Xerces' and Woodstox's own security managers). A
payload therefore has to exceed the largest of these.</p>
*
- * <ul>
- * <li>The <strong>medium</strong> fixture nests three levels of 16x
expansion ({@code lol1} through {@code lol3}), so resolving {@code &lol3;}
produces
- * {@code 16 * 16 * 16 = 4096} leaf {@code &lol;} expansions and a total
of {@code 1 + 16 + 256 + 4096 = 4369} entity-expansion events. That is
- * comfortably over the {@code entityExpansionLimit = 2500} this library
pins on every JAXP factory it returns (mirroring JDK 25's secure value), so the
- * hardened side trips on every JDK from 8 to 25. The unconfigured side
disables the limit explicitly via {@code setAttribute/setProperty} on the JDK
- * property name, so it parses the ~4 KB of expanded {@code "A"} text
and finishes immediately.</li>
- * <li>The <strong>large</strong> fixture nests seven levels of 10x
expansion ({@code lol1} through {@code lol7}), so resolving {@code &lol7;}
produces
- * {@code 10^7 = 10 000 000} leaf expansions, ~10 MB of {@code "A"}
text, and an amplification factor in the tens of thousands. Sized to trip
- * libexpat >= 2.4's built-in billion-laughs check (8 MiB activation
threshold and 100x amplification factor).</li>
- * </ul>
- *
- * <p>Why a single character {@code "A"}: XSLTC compiles a stylesheet's
expanded text into a JVM string constant, which is capped at 65535 bytes. A
larger
- * expansion makes {@code newTransformer(stylesheet)} fail with a misleading
"GregorSamsa" stub-class error even when entity limits are disabled. The medium
- * fixture is sized to stay well under that ceiling. The large fixture cannot
be used for {@code Templates} / {@code Transformer} compilation for the same
- * reason.</p>
- *
- * <p>Which fixture each test uses:</p>
+ * <p>Every payload shares one six-level x10 {@link #DTD} (declaring entities
is free until they are referenced) and varies only the body it expands:</p>
*
* <ul>
- * <li>{@code hardened*} tests pull from {@code hardened*Payload} helpers:
large fixture on Android (libexpat is the only defense), medium fixture on JDK
- * (entity-expansion count limit is sufficient).</li>
- * <li>{@code unconfigured*} positive controls pull from {@code
medium*Payload} helpers regardless of platform: libexpat's billion-laughs check
cannot be
- * disabled from Java, so a permissive parse of the large fixture would
still trip on Android.</li>
+ * <li>{@link #CONTENT_101K} ({@code 101000}) on the JVM: above every JVM
parser default.</li>
+ * <li>{@link #CONTENT_9M} ({@code 9000000}) on Android: above libexpat's 8
MiB billion-laughs activation threshold, the only defense there since the limit
is
+ * not configurable. For that same reason the positive controls do not
run on Android (see {@link #assumeSAXLimitConfigurable()}): a payload the
hardened test
+ * blocks cannot be parsed even without hardening.</li>
* </ul>
+ *
+ * <p>Why a single character {@code "A"}: it makes the expanded size equal the
expansion count, so a payload's size maps directly onto each parser's limit.</p>
*/
class BillionLaughsTest {
- private static final String LARGE_CONTENT = "&lol7;";
-
- private static final String LARGE_DTD =
- " <!ENTITY lol \"A\">\n"
- + " <!ENTITY lol1
\"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">\n"
- + " <!ENTITY lol2
\"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;\">\n"
- + " <!ENTITY lol3
\"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">\n"
- + " <!ENTITY lol4
\"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;\">\n"
- + " <!ENTITY lol5
\"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;\">\n"
- + " <!ENTITY lol6
\"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;\">\n"
- + " <!ENTITY lol7
\"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;\">\n";
-
- private static final String MEDIUM_CONTENT = "&lol3;";
-
- private static final String MEDIUM_DTD =
- " <!ENTITY lol \"A\">\n"
- + " <!ENTITY lol1
\"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">\n"
- + " <!ENTITY lol2
\"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;\">\n"
- + " <!ENTITY lol3
\"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">\n";
-
- /**
- * Hardened-side payload for DOM/SAX/XmlReader
- *
- * <ul>
- * <li>~10 MiB on Android to trip libexpats 8 MiB limit, and</li>
- * <li>~4 KiB on JDK to trip JDK 25's {@code entityExpansionLimit =
2500}.</li>
- * </ul>
- */
- private static String hardenedXmlPayload() {
- return AttackTestSupport.IS_ANDROID
- ? withDoctype("root", LARGE_DTD,
AttackTestSupport.xmlBody(LARGE_CONTENT))
- : mediumXmlPayload();
- }
-
+ /** 100,000 + 1,000 = 101,000 expansions; above every JVM parser's secure
default (2,500 / 64,000 / 100,000). */
+ private static final String CONTENT_101K = "&lol5;&lol3;";
+ /** 9 x 1,000,000 = 9,000,000 expansions; above libexpat's 8 MiB
billion-laughs activation threshold. */
+ private static final String CONTENT_9M = repeatRef("lol6", 9);
/**
- * Hardened-side XSD payload
- *
- * <ul>
- * <li>~10 MiB on Android to trip libexpats 8 MiB limit, and</li>
- * <li>~4 KiB on JDK to trip JDK 25's {@code entityExpansionLimit =
2500}.</li>
- * </ul>
+ * Shared DTD for every payload: a six-level x10 ladder, {@code &lol1;}
through {@code &lol6;} ({@code &lol6;} expands to 1,000,000). Declaring an
entity costs
+ * nothing until it is referenced, so the DTD is identical on every
platform and only the expanded body ({@link #content()}) varies.
*/
- private static String hardenedXsdPayload() {
- return AttackTestSupport.IS_ANDROID
- ? withDoctype("xs:schema", LARGE_DTD,
AttackTestSupport.xsdBody(LARGE_CONTENT))
- : mediumXsdPayload();
- }
+ private static final String DTD =
+ " <!ENTITY lol \"A\">\n"
+ + entityLine("lol1", "lol") // 10
+ + entityLine("lol2", "lol1") // 100
+ + entityLine("lol3", "lol2") // 1000
+ + entityLine("lol4", "lol3") // 10000
+ + entityLine("lol5", "lol4") // 100000
+ + entityLine("lol6", "lol5"); // 1000000
/**
- * Hardened-side XSLT payload
+ * Skips a positive control on Android.
*
- * <ul>
- * <li>~10 MiB on Android to trip libexpats 8 MiB limit, and</li>
- * <li>~4 KiB on JDK to trip JDK 25's {@code entityExpansionLimit =
2500}, and</li>
- * <li>stay under XSLTC's 60 KB constant-pool cap, and</li>
- * </ul>
+ * <p>The controls prove the hardened test blocked a payload that would
otherwise parse, so they must use the very payload the hardened test blocks.
+ * On Android the entity-expansion limit is not configurable (libexpat's
billion-laughs check cannot be lifted), so that payload
+ * cannot be parsed even without hardening, leaving nothing to prove.</p>
*/
- private static String hardenedXsltPayload() {
- return AttackTestSupport.IS_ANDROID
- ? withDoctype("xsl:stylesheet", LARGE_DTD,
AttackTestSupport.xsltBody(LARGE_CONTENT))
- : mediumXsltPayload();
+ private static void assumeSAXLimitConfigurable() {
+ Assumptions.assumeFalse(AttackTestSupport.IS_ANDROID, "Skipped on
Android: the entity-expansion limit is not configurable");
}
Review Comment:
The helper name `assumeSAXLimitConfigurable()` is misleading now that it
gates multiple non-SAX positive controls (Schema, StAX, TrAX, Validator). A
more general name (e.g., `assumeEntityLimitConfigurable()` or similar) would
better reflect what the assumption actually asserts.
##########
src/test/java/org/apache/commons/xml/BillionLaughsTest.java:
##########
@@ -24,237 +24,192 @@
/**
* Checks whether parsers reject a Billion Laughs payload (nested entity
expansion in the internal DTD subset).
*
- * <p>Two fixtures are used:</p>
+ * <p>Each {@code hardened*} test asserts the library blocks the payload; its
{@code unconfigured*} positive control asserts the same payload parses once the
+ * limit is disabled, so a block reflects the hardening rather than a broken
wrapper. The library pins no custom entity-expansion limit; each parser keeps
its own
+ * secure-processing default, which varies by implementation: {@code 2,500}
(stock JDK), {@code 64,000} (external Xerces under {@code
FEATURE_SECURE_PROCESSING}),
+ * {@code 100,000} (external Xerces' and Woodstox's own security managers). A
payload therefore has to exceed the largest of these.</p>
*
- * <ul>
- * <li>The <strong>medium</strong> fixture nests three levels of 16x
expansion ({@code lol1} through {@code lol3}), so resolving {@code &lol3;}
produces
- * {@code 16 * 16 * 16 = 4096} leaf {@code &lol;} expansions and a total
of {@code 1 + 16 + 256 + 4096 = 4369} entity-expansion events. That is
- * comfortably over the {@code entityExpansionLimit = 2500} this library
pins on every JAXP factory it returns (mirroring JDK 25's secure value), so the
- * hardened side trips on every JDK from 8 to 25. The unconfigured side
disables the limit explicitly via {@code setAttribute/setProperty} on the JDK
- * property name, so it parses the ~4 KB of expanded {@code "A"} text
and finishes immediately.</li>
- * <li>The <strong>large</strong> fixture nests seven levels of 10x
expansion ({@code lol1} through {@code lol7}), so resolving {@code &lol7;}
produces
- * {@code 10^7 = 10 000 000} leaf expansions, ~10 MB of {@code "A"}
text, and an amplification factor in the tens of thousands. Sized to trip
- * libexpat >= 2.4's built-in billion-laughs check (8 MiB activation
threshold and 100x amplification factor).</li>
- * </ul>
- *
- * <p>Why a single character {@code "A"}: XSLTC compiles a stylesheet's
expanded text into a JVM string constant, which is capped at 65535 bytes. A
larger
- * expansion makes {@code newTransformer(stylesheet)} fail with a misleading
"GregorSamsa" stub-class error even when entity limits are disabled. The medium
- * fixture is sized to stay well under that ceiling. The large fixture cannot
be used for {@code Templates} / {@code Transformer} compilation for the same
- * reason.</p>
- *
- * <p>Which fixture each test uses:</p>
+ * <p>Every payload shares one six-level x10 {@link #DTD} (declaring entities
is free until they are referenced) and varies only the body it expands:</p>
*
* <ul>
- * <li>{@code hardened*} tests pull from {@code hardened*Payload} helpers:
large fixture on Android (libexpat is the only defense), medium fixture on JDK
- * (entity-expansion count limit is sufficient).</li>
- * <li>{@code unconfigured*} positive controls pull from {@code
medium*Payload} helpers regardless of platform: libexpat's billion-laughs check
cannot be
- * disabled from Java, so a permissive parse of the large fixture would
still trip on Android.</li>
+ * <li>{@link #CONTENT_101K} ({@code 101000}) on the JVM: above every JVM
parser default.</li>
+ * <li>{@link #CONTENT_9M} ({@code 9000000}) on Android: above libexpat's 8
MiB billion-laughs activation threshold, the only defense there since the limit
is
+ * not configurable. For that same reason the positive controls do not
run on Android (see {@link #assumeSAXLimitConfigurable()}): a payload the
hardened test
+ * blocks cannot be parsed even without hardening.</li>
* </ul>
+ *
+ * <p>Why a single character {@code "A"}: it makes the expanded size equal the
expansion count, so a payload's size maps directly onto each parser's limit.</p>
*/
class BillionLaughsTest {
- private static final String LARGE_CONTENT = "&lol7;";
-
- private static final String LARGE_DTD =
- " <!ENTITY lol \"A\">\n"
- + " <!ENTITY lol1
\"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">\n"
- + " <!ENTITY lol2
\"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;\">\n"
- + " <!ENTITY lol3
\"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">\n"
- + " <!ENTITY lol4
\"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;\">\n"
- + " <!ENTITY lol5
\"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;\">\n"
- + " <!ENTITY lol6
\"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;\">\n"
- + " <!ENTITY lol7
\"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;\">\n";
-
- private static final String MEDIUM_CONTENT = "&lol3;";
-
- private static final String MEDIUM_DTD =
- " <!ENTITY lol \"A\">\n"
- + " <!ENTITY lol1
\"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">\n"
- + " <!ENTITY lol2
\"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;\">\n"
- + " <!ENTITY lol3
\"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">\n";
-
- /**
- * Hardened-side payload for DOM/SAX/XmlReader
- *
- * <ul>
- * <li>~10 MiB on Android to trip libexpats 8 MiB limit, and</li>
- * <li>~4 KiB on JDK to trip JDK 25's {@code entityExpansionLimit =
2500}.</li>
- * </ul>
- */
- private static String hardenedXmlPayload() {
- return AttackTestSupport.IS_ANDROID
- ? withDoctype("root", LARGE_DTD,
AttackTestSupport.xmlBody(LARGE_CONTENT))
- : mediumXmlPayload();
- }
-
+ /** 100,000 + 1,000 = 101,000 expansions; above every JVM parser's secure
default (2,500 / 64,000 / 100,000). */
+ private static final String CONTENT_101K = "&lol5;&lol3;";
+ /** 9 x 1,000,000 = 9,000,000 expansions; above libexpat's 8 MiB
billion-laughs activation threshold. */
+ private static final String CONTENT_9M = repeatRef("lol6", 9);
/**
- * Hardened-side XSD payload
- *
- * <ul>
- * <li>~10 MiB on Android to trip libexpats 8 MiB limit, and</li>
- * <li>~4 KiB on JDK to trip JDK 25's {@code entityExpansionLimit =
2500}.</li>
- * </ul>
+ * Shared DTD for every payload: a six-level x10 ladder, {@code &lol1;}
through {@code &lol6;} ({@code &lol6;} expands to 1,000,000). Declaring an
entity costs
+ * nothing until it is referenced, so the DTD is identical on every
platform and only the expanded body ({@link #content()}) varies.
*/
- private static String hardenedXsdPayload() {
- return AttackTestSupport.IS_ANDROID
- ? withDoctype("xs:schema", LARGE_DTD,
AttackTestSupport.xsdBody(LARGE_CONTENT))
- : mediumXsdPayload();
- }
+ private static final String DTD =
+ " <!ENTITY lol \"A\">\n"
+ + entityLine("lol1", "lol") // 10
+ + entityLine("lol2", "lol1") // 100
+ + entityLine("lol3", "lol2") // 1000
+ + entityLine("lol4", "lol3") // 10000
+ + entityLine("lol5", "lol4") // 100000
+ + entityLine("lol6", "lol5"); // 1000000
/**
- * Hardened-side XSLT payload
+ * Skips a positive control on Android.
*
- * <ul>
- * <li>~10 MiB on Android to trip libexpats 8 MiB limit, and</li>
- * <li>~4 KiB on JDK to trip JDK 25's {@code entityExpansionLimit =
2500}, and</li>
- * <li>stay under XSLTC's 60 KB constant-pool cap, and</li>
- * </ul>
+ * <p>The controls prove the hardened test blocked a payload that would
otherwise parse, so they must use the very payload the hardened test blocks.
+ * On Android the entity-expansion limit is not configurable (libexpat's
billion-laughs check cannot be lifted), so that payload
+ * cannot be parsed even without hardening, leaving nothing to prove.</p>
*/
- private static String hardenedXsltPayload() {
- return AttackTestSupport.IS_ANDROID
- ? withDoctype("xsl:stylesheet", LARGE_DTD,
AttackTestSupport.xsltBody(LARGE_CONTENT))
- : mediumXsltPayload();
+ private static void assumeSAXLimitConfigurable() {
+ Assumptions.assumeFalse(AttackTestSupport.IS_ANDROID, "Skipped on
Android: the entity-expansion limit is not configurable");
}
- /**
- * Unconfigured-side payload for DOM/SAX/XmlReader
- *
- * <p>~4 KB of expanded {@code "A"}, which:</p>
- * <ul>
- * <li>trips JDK 25's {@code entityExpansionLimit = 2500}, but</li>
- * <li>does not trip libexpat's immutable 8 MiB limit.</li>
- * </ul>
- */
- private static String mediumXmlPayload() {
- return withDoctype("root", MEDIUM_DTD,
AttackTestSupport.xmlBody(MEDIUM_CONTENT));
+ /** The body to expand: 9,000,000 on Android, where libexpat is the only
defense and the limit is not configurable, 101,000 on the JVM. */
+ private static String content() {
+ return AttackTestSupport.IS_ANDROID ? CONTENT_9M : CONTENT_101K;
}
- /**
- * Unconfigured-side XSD payload
- *
- * <p>~4 KB of expanded {@code "A"}, which:</p>
- * <ul>
- * <li>trips JDK 25's {@code entityExpansionLimit = 2500}, but</li>
- * <li>does not trip libexpat's immutable 8 MiB limit.</li>
- * </ul>
- */
- private static String mediumXsdPayload() {
- return withDoctype("xs:schema", MEDIUM_DTD,
AttackTestSupport.xsdBody(MEDIUM_CONTENT));
+ /** Renders {@code <!ENTITY name "&ref;&ref;...">}, one ladder rung: ten
copies of {@code &ref;}. */
+ private static String entityLine(final String name, final String ref) {
+ return " <!ENTITY " + name + " \"" + repeatRef(ref, 10) + "\">\n";
}
- /**
- * Unconfigured-side XSLT payload
- *
- * <p>~4 KB of expanded {@code "A"}, which:</p>
- * <ul>
- * <li>trips JDK 25's {@code entityExpansionLimit = 2500}, but</li>
- * <li>stays under XSLTC's 60 KB constant-pool cap, and</li>
- * <li>does not trip libexpat's immutable 8 MiB limit.</li>
- * </ul>
- */
- private static String mediumXsltPayload() {
- return withDoctype("xsl:stylesheet", MEDIUM_DTD,
AttackTestSupport.xsltBody(MEDIUM_CONTENT));
+ /** Builds {@code times} copies of the entity reference {@code &name;}. */
+ private static String repeatRef(final String name, final int times) {
+ final String ref = "&" + name + ";";
+ final StringBuilder sb = new StringBuilder(ref.length() * times);
+ for (int i = 0; i < times; i++) {
+ sb.append(ref);
+ }
+ return sb.toString();
}
- private static String withDoctype(final String rootQName, final String
dtd, final String body) {
+ private static String withDoctype(final String rootQName, final String
body) {
return "<?xml version=\"1.0\"?>\n"
+ "<!DOCTYPE " + rootQName + " [\n"
- + dtd
+ + DTD
+ "]>\n"
+ body + "\n";
}
+ /** Payload for DOM/SAX/XmlReader/StAX/Transformer/Validator. */
+ private static String xmlPayload() {
+ return withDoctype("root", AttackTestSupport.xmlBody(content()));
+ }
+
+ /** XSD payload. */
+ private static String xsdPayload() {
+ return withDoctype("xs:schema", AttackTestSupport.xsdBody(content()));
+ }
+
+ /** XSLT payload. */
+ private static String xsltPayload() {
+ return withDoctype("xsl:stylesheet",
AttackTestSupport.xsltBody(content()));
+ }
Review Comment:
The XSLT payload embeds `content()` directly inside a template body via
`AttackTestSupport.xsltBody(...)`. On the JVM `content()` expands to ~101k
characters, which is likely to exceed XSLTC/Java classfile string-constant
limits (~65k) and make `unconfiguredTemplatesCompiles()` fail for reasons
unrelated to entity-limit hardening. Consider restructuring the stylesheet
carrier so it can exceed entity-expansion limits without producing a single
>65k literal text node (for example, avoid large literal text in the
stylesheet, or use an expansion pattern that triggers the count limit without
inflating the compiled text).
##########
src/test/java/org/apache/commons/xml/AttackTestSupport.java:
##########
@@ -347,8 +376,9 @@ static void assertPermissiveStaxParses(final String
payload) {
assertParseSucceeds(() -> {
final XMLInputFactory factory = XMLInputFactory.newInstance();
suppressException(() ->
factory.setProperty(XMLConstants.FEATURE_SECURE_PROCESSING, false));
- // URL form of the JDK property; JDK 8's
XMLSecurityManager.getIndex only matches this form, JDK 11+ accepts both.
- suppressException(() ->
factory.setProperty(JDK_ENTITY_EXPANSION_LIMIT, "0"));
+ liftJdkEntityLimits(factory);
+ // Woodstox ignores the JDK properties and enforces its own
default (100000) entity-count limit; lift it so the positive control parses.
+ suppressException(() -> factory.setProperty(WSTX_MAX_ENTITY_COUNT,
Long.MAX_VALUE));
Review Comment:
`com.ctc.wstx.maxEntityCount` is a Woodstox-specific property that typically
expects an `int`/`Integer`. Setting it to `Long.MAX_VALUE` can throw and be
swallowed by `suppressException(...)`, leaving the default (100000) in place
and causing the permissive StAX control to still fail for a 101k-entity payload.
##########
src/site/markdown/threat_model.md:
##########
@@ -78,21 +78,20 @@ listed below. Which hardening recipe applies depends on the
JAXP implementation
**System properties that modify behavior**
-When a factory or parser is created, the library reads the following JDK
system properties and pins each value on every
-recognized parser, including bundled ones that ignore `jdk.xml.*` on their
own. If a property is unset, the fixed value
-shown applies (matching the JDK 25 secure default), regardless of the JDK in
use. These properties are trusted
-deployment configuration: an operator may set one to tighten (or loosen) a
limit globally, but loosening through one is
-reconfiguration, treated like loosening any other reserved setting (see [What
is out of scope](#what-is-out-of-scope)).
-
-- `jdk.xml.elementAttributeLimit`: `200`
-- `jdk.xml.entityExpansionLimit`: `2500`
-- `jdk.xml.entityReplacementLimit`: `100000`
-- `jdk.xml.maxElementDepth`: `100`
-- `jdk.xml.maxGeneralEntitySizeLimit`: `100000`
-- `jdk.xml.maxOccurLimit`: `5000`
-- `jdk.xml.maxParameterEntitySizeLimit`: `15000`
-- `jdk.xml.maxXMLNameLimit`: `1000`
-- `jdk.xml.totalEntitySizeLimit`: `100000`
+The library reads no system property of its own. It 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
+JDK version and the standard `jdk.xml.*` limit properties the JDK itself reads:
Review Comment:
This section says the library reads no system property of its own, but the
preceding paragraph under "Assumptions about the environment" still states
`XmlFactories` methods "read the JDK system properties listed below". That
earlier sentence should be updated to avoid contradicting this section now that
`Limits` has been removed.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]