- Project: Apache Axiom — "contains core interfaces of the Axiom
API", a StAX-based XML object model conforming to the W3C XML
Information Set, with a SAX adapter, a MIME multipart parser for
SOAP-with-Attachments / XOP / MTOM, and pluggable implementations
(
axiom-implLLOM,axiom-dom) (documented:axiom-api/src/main/java/org/apache/axiom/om/package.html). - Repository:
apache/ws-axiom. - Version / commit: this model is drafted against the default branch at clone time. A report against project release N should be triaged against the model as it stood at N, not at HEAD.
- Date: 2026-05-30.
- Authors: ASF Security team draft, awaiting Axiom / Webservices PMC review.
- Status: draft — under maintainer review.
- Reporting: vulnerabilities that fall under §8 (claimed
properties) should be reported per the Apache Security Team disclosure
channel (https://www.apache.org/security/); reports that fall under
§3 (out of scope) or §9 (properties not provided) will be closed by
Axiom triagers citing this document. The project does not ship an
in-repo
SECURITY.mdat draft time (inferred — §14 Q1). - Provenance legend — (documented) = drawn from in-repo docs / source comments / project website with citation; (maintainer) = stated by an Axiom maintainer in response to this draft; (inferred) = synthesized by the producer from code structure or domain knowledge, awaiting PMC ratification (every (inferred) tag has a matching §14 question).
- Draft confidence: 24 documented / 0 maintainer / 27 inferred.
Axiom is a Java library that provides an in-memory representation of an
XML document conforming to the W3C XML Infoset, with a streaming
backbone (StAX). It is the underlying OM (object model) used by Apache
Axis2, Apache WSS4J's bindings, Apache Neethi, and other SOAP-centric
runtimes. Axiom ships an API module (axiom-api), two implementations
(axiom-impl — the LLOM linked-list model; axiom-dom — a W3C-DOM
view of the same), a multipart MIME parser
(org.apache.axiom.mime.MultipartBody) for SOAP-with-Attachments / XOP
/ MTOM, a SAX adapter, a base64 utility, weaver-based bytecode
generation for the LLOM (axiom-weaver), and language-server / Jakarta
/ Javax compatibility shims.
- In-process Java OM for XML documents — both general-purpose XML and
SOAP envelopes specifically (documented:
axiom-api/src/main/java/org/apache/axiom/om/package.html). - The SOAP-oriented entry points (
OMXMLBuilderFactory.createSOAPModelBuilder,MultipartBody.builder()) are designed to be consumed by a SOAP stack — historically Apache Axis2 — that builds an OM, performs message-level processing, and routes to a service implementation.
Axiom is an in-process library. No daemon, no listening socket, no CLI on the supported surface. The threat model is therefore that of a streaming XML parser + DOM-like object model + MIME multipart parser with caller-selectable hardening profiles.
| Role | Trust level | Notes |
|---|---|---|
| Embedding Java application / SOAP stack | trusted | Calls Axiom's OMXMLBuilderFactory.* entry points, selects a StAXParserConfiguration (DEFAULT / STANDALONE / SOAP / COALESCING / NON_COALESCING / PRESERVE_CDATA_SECTIONS), supplies the bytes, optionally configures an OMFactory or custom XMLInputFactory. |
Caller-supplied OMFactory / OMMetaFactory |
trusted | Pluggable; axiom-impl (LLOM) and axiom-dom are the bundled choices. |
| Producer of the XML / SOAP / MIME bytes | untrusted | The only attacker-controllable input position. |
Producer of the JVM system property org.apache.axiom.om.OMMetaFactoryLocator (and similar OSGi locator state) |
trusted | Locator selection is a JVM-startup-time decision. |
Caller-supplied XMLInputFactory / XMLOutputFactory |
trusted | Caller may pass in their own; Axiom wraps it. If the caller's factory is mis-hardened, that is the caller's problem. |
Bundled implementations of OMFactory (LLOM axiom-impl, DOM axiom-dom) |
trusted upstream within this repo | Vulnerabilities in the implementation modules are in-model. |
| Family | Representative entry point | Touches outside the process? | In-model? |
|---|---|---|---|
axiom-api core OM — OMElement, OMDocument, OMText, OMNode, OMContainer, OMSerializable |
OMXMLBuilderFactory.createOMBuilder(InputStream) |
no | yes |
axiom-api StAX wrapper — XMLStreamReader/Writer wrappers (util/stax/) |
n/a | no | yes |
axiom-api SAX adapter — AbstractXMLReader |
n/a | no | yes |
axiom-api MIME parser — MultipartBody, PartImpl, Part, MultipartBodyWriter, ContentType, ContentTransferEncoding |
MultipartBody.builder().setInputStream(...).build() |
no (operates on in-memory / caller stream) | yes |
axiom-api base64 — org.apache.axiom.util.base64.* |
n/a | no | yes |
axiom-api locator — org.apache.axiom.locator.* (OMMetaFactoryLocator) |
reads system properties + OSGi service registry | filesystem (classpath) | yes |
axiom-api StAX dialect detection — org.apache.axiom.util.stax.dialect.* (Woodstox, SJSXP, Stax2) |
reads classpath / org.codehaus.stax2.* |
none directly | yes |
axiom-impl (LLOM) — linked-list OM implementation |
invoked through OMFactory |
none | yes |
axiom-dom — W3C DOM view of the same OM |
invoked through OMFactory |
none | yes |
axiom-weaver + axiom-weaver-annotations — bytecode-generation helper for the implementations |
build-time only | none at runtime | out of model at runtime (§3) — in-model only insofar as it affects the generated implementation |
axiom-jakarta-activation, axiom-javax-activation, axiom-jakarta-jaxb, axiom-javax-jaxb, axiom-compat, axiom-legacy-attachments, axiom-mixins, jakarta-bom, javax-bom |
shim / BOM modules | none directly | yes insofar as they re-expose APIs |
samples/, systests/, apidocs/, devguide/, legal/, distribution/, etc/, testing/, buildutils/, mixins/ |
sample / test / packaging | n/a | out of model (§3) |
A finding is in-model only if it reaches a row marked yes.
- A SOAP / WSDL processor. Axiom provides the OM and the
SOAP-message-level helpers (
SOAPEnvelope,SOAPHeader,SOAPBody,SOAPMessage, etc.); routing / service-implementation dispatch is the SOAP stack's responsibility (Axis2). →OUT-OF-MODEL: out-of-layer. - The transport layer. Axiom does not open sockets or read from
the network on its own. →
OUT-OF-MODEL: out-of-layer. - Validation against an XML Schema. Axiom is an OM library, not
a validator. →
OUT-OF-MODEL: out-of-layer. - The XML parser itself. Axiom uses whatever StAX implementation
the JDK / classpath supplies (Woodstox, SJSXP, JDK built-in). It
configures the parser via
StAXParserConfigurationbut does not ship a parser. Defects intrinsic to Woodstox / SJSXP / the JDK StAX implementation are out of model and reported upstream (inferred — §14 Q2). →OUT-OF-MODEL: unsupported-component. axiom-weaverruntime behavior. The weaver is a build-time tool that generates LLOM implementation classes; defects in generated code land inaxiom-impland are in-model there. The weaver itself is out of model. →OUT-OF-MODEL: unsupported-component.samples/,systests/,testing/*. Sample apps and test support. →OUT-OF-MODEL: unsupported-component.- Apache Axis2. Axis2 is the most well-known consumer of Axiom
but lives in a separate repository (
apache/axis-axis2-java-core) with its own threat model. →OUT-OF-MODEL: out-of-layer. - Apache WSS4J's WS-Security processing on an Axiom OM. WSS4J
has its own threat model; Axiom only provides the OM. →
OUT-OF-MODEL: out-of-layer.
| # | Transition | Authentication | Authorization |
|---|---|---|---|
| B1 | Caller → `OMXMLBuilderFactory.createOMBuilder(InputStream | Reader | Source |
| B2 | OMXMLBuilderFactory.* → bundled XMLInputFactory (selected by StAXDialectDetector, configured by StAXParserConfiguration) |
none | the configuration chosen at the builder call is the gate |
| B3 | OMXMLBuilderFactory.createSOAPModelBuilder(InputStream) → bundled XMLInputFactory configured for SOAP (rejects DOCTYPE) — see StAXParserConfiguration.SOAP (documented: StAXParserConfiguration.java lines 135-145) |
none | SOAP profile is the gate |
| B4 | Caller → MultipartBody.builder().setInputStream(...).build() |
none | MIME framing parsed by Axiom; per-part bytes wrapped as Part |
| B5 | Caller → OMMetaFactoryLocator (via org.apache.axiom.om.OMMetaFactoryLocator system property and OSGi service registry) |
trusted | startup-time class loading |
- Core OM builder (
OMXMLBuilderFactory.createOMBuilder(InputStream)): in-model when bytes are attacker-controlled. The defaultStAXParserConfigurationis DEFAULT = PRESERVE_CDATA_SECTIONS (documented:StAXParserConfiguration.javalines 48-58, 60-61;OMXMLBuilderFactory.javaline 107). DEFAULT does not disable DTD support, does not disable external entities, does not disallow DOCTYPE. It only enables CDATA reporting. - SOAP-specific builder (
OMXMLBuilderFactory.createSOAPModelBuilder(InputStream)): in-model when bytes are attacker-controlled. The builder uses the SOAP profile, which disallows DOCTYPE declarations on the wire (documented:StAXParserConfiguration.javalines 125-145). - STANDALONE profile (caller explicitly chooses
StAXParserConfiguration.STANDALONE): setsIS_SUPPORTING_EXTERNAL_ENTITIES=falseand installs a customXMLResolverthat returns empty content for any external resource (documented:StAXParserConfiguration.javalines 72-95). This is the hardened profile for general XML input. - MIME parser (
MultipartBody.builder().setInputStream(...).build()): in-model when bytes are attacker-controlled. Parses MIME framing, produces per-part streams; size is bounded only by what the configuredPartBlobFactorychooses to do (inferred — §14 Q3). axiom-impl/axiom-dom: in-model insofar as they implement the API surface; reachable only via the API.- Locator / dialect detection: in-model insofar as it influences which StAX implementation is loaded; the selection relies on the system property and OSGi state being operator-controlled.
- JDK: minimum supported JDK version is in
pom.xml. Axiom 2.0+ targets a modern JDK; earlier branches supported older JDKs (inferred — §14 Q4). - StAX implementation: a working StAX provider on the classpath
(Woodstox is the supported preferred provider; SJSXP and the
JDK StAX implementation are also recognized by
StAXDialectDetector) (documented:axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/). - Bundled JDK XML platform: standard
javax.xml.stream.XMLInputFactory/XMLOutputFactory. - JDK MIME/Mail platform: NOT required — Axiom's MIME parser is
self-contained in
org.apache.axiom.mime. jakarta-activation/javax-activation: optional shim modules for the JavaBeans Activation Framework (DataSource / DataHandler); in-model insofar as Axiom uses them.AGENTS.md— "This project uses the spotless-maven-plugin withpalantirJavaFormatto enforce consistent Java formatting" (documented:AGENTS.md). This is build-time formatting; not a runtime claim.
- Opens no listening sockets (inferred — §14 Q5).
- Spawns no child processes (inferred — §14 Q5).
- Installs no signal handlers (inferred — §14 Q5).
- Reads a small set of documented system properties for
OMMetaFactoryLocatorselection and for compatibility hacks; does not consumeLD_*-style envvars for security-sensitive decisions (inferred — §14 Q5). - Writes nothing of its own initiative; the serializer writes to the
OutputStream/Writerthe caller hands in (inferred — §14 Q5).
Axiom ships as a single Maven artifact set. There are no compile-time
feature toggles known to materially change the security envelope
(inferred — §14 Q6). The runtime security envelope is shaped by
the choice of StAXParserConfiguration at builder-call time:
| Profile | XXE / DTD posture | Maintainer stance | When intended |
|---|---|---|---|
DEFAULT (== PRESERVE_CDATA_SECTIONS) |
DTD allowed; external entities enabled by JDK default; DOCTYPE allowed | maintainer ruling required — see §14 Q7 | General XML input where the caller already trusts the bytes |
STANDALONE |
DTD allowed but external entities returned as empty via custom XMLResolver; DOCTYPE allowed |
safe-by-default for non-SOAP input from untrusted sources; caller explicitly opts in | XML parsing of untrusted-but-non-SOAP input |
SOAP |
DTD disallowed at first encounter (dialect.disallowDoctypeDecl(...)) |
safe-by-default for SOAP input | SOAP envelope parsing (RFC says SOAP MUST NOT contain DTDs) |
COALESCING |
inherits the calling profile | n/a (orthogonal to XXE) | Caller wants coalesced text nodes |
NON_COALESCING |
inherits the calling profile | n/a (orthogonal to XXE) | Caller wants non-coalesced text nodes |
PRESERVE_CDATA_SECTIONS |
inherits the calling profile | n/a (orthogonal to XXE) | Caller wants CDATA preserved |
The default OMXMLBuilderFactory.createOMBuilder(InputStream) resolves
to StAXParserConfiguration.DEFAULT, which does not disable DTD
processing or external entities (documented:
OMXMLBuilderFactory.java lines 106-107, 119-120, 222, 248;
StAXParserConfiguration.java lines 60-61). The maintainer ruling
captured in §14 Q7 will determine whether a report shaped "I called
createOMBuilder(InputStream) on attacker bytes and an XXE worked"
is:
- (a)
VALID— because the SDK default should be safe and the project will fix by changing the default; or - (b)
OUT-OF-MODEL: non-default-build— because the caller is documented as expected to chooseSOAPfor SOAP input andSTANDALONEfor general untrusted XML, per §10.
The SOAP-specific entry point
(OMXMLBuilderFactory.createSOAPModelBuilder) installs the SOAP
profile by default, which does block DOCTYPE. Reports against
SOAP input through the SOAP-specific entry point are unambiguously
VALID if a DTD slips through.
System property knobs (locator selection, dialect overrides) are trusted by §3 / §5.
| Entry point | Parameter | Attacker-controllable? | Caller must enforce |
|---|---|---|---|
OMXMLBuilderFactory.createOMBuilder(InputStream) |
bytes | yes | pick the right StAXParserConfiguration — DEFAULT does not block XXE; caller must use STANDALONE for untrusted general XML |
OMXMLBuilderFactory.createOMBuilder(StAXParserConfiguration, InputStream) |
bytes + config | yes | use STANDALONE for untrusted general XML, SOAP for SOAP input |
OMXMLBuilderFactory.createOMBuilder(Reader) |
character data | yes | same as above |
OMXMLBuilderFactory.createOMBuilder(Source) |
bytes / chars | yes | same as above |
OMXMLBuilderFactory.createOMBuilder(XMLStreamReader) |
events | yes if the StreamReader was built on attacker bytes | caller's XMLInputFactory is responsible for XXE / DTD posture; Axiom does not re-configure |
OMXMLBuilderFactory.createSOAPModelBuilder(InputStream) |
SOAP bytes | yes | nothing — uses StAXParserConfiguration.SOAP which disallows DOCTYPE |
OMXMLBuilderFactory.createSOAPModelBuilder(StAXParserConfiguration, InputStream) |
SOAP bytes + override | yes | if caller overrides to a less safe profile, the override is the caller's choice |
MultipartBody.builder().setInputStream(InputStream).build() |
MIME bytes | yes | bound the maximum total body size externally |
MultipartBody.builder().setPartBlobFactory(...) |
factory | trusted | caller's choice; affects per-part storage (memory vs spool to disk) |
MultipartBody.builder().setContentType(...) |
Content-Type string | caller-supplied | caller controls; Axiom parses the boundary delimiter from it |
PartImpl.getInputStream() |
per-part read | streams attacker bytes | caller must close the stream |
OMElement.serialize(OutputStream) / .serialize(Writer) |
output sink | caller-supplied | caller's choice |
Base64.decode(String) |
base64 input | yes if from attacker | size is the caller's responsibility |
OMMetaFactoryLocator (system property) |
class name | trusted by §3, §5 | operator must lock down property setting |
- No documented bound on input XML size; the StAX implementation may
apply its own (Woodstox
P_MAX_*properties, JDKentityExpansionLimit). - No documented bound on MIME multipart total size, per-part size, or part count (inferred — §14 Q3).
- No documented bound on base64 input size or output expansion ratio (inferred — §14 Q3).
- No rate limit of any kind; Axiom is a parsing library, not a service.
| Actor | In scope? | Capabilities |
|---|---|---|
| Producer of the XML / SOAP bytes | yes | full byte control of the input stream |
| Producer of the MIME multipart bytes | yes | full byte control of Content-Type boundary + part bodies |
Producer of a <!DOCTYPE> declaration referencing http://attacker/ |
in scope only when the DEFAULT profile is in use against untrusted bytes — see §14 Q7 | |
| Producer of a base64-encoded payload that decompresses to gigabytes | in scope insofar as Axiom decodes; caller bounds output size | |
| In-process caller | out of scope — trusted by construction | |
| Owner of the JVM system properties / classpath | out of scope | |
Author of a hostile OMFactory / OMMetaFactory |
out of scope (§2) | |
Author of a hostile XMLInputFactory / XMLOutputFactory passed via setStAXFactory |
out of scope (§2) | |
| Co-tenant in shared JVM | out of scope (inferred — §14 Q8) | |
| Side-channel observer | out of scope (inferred — §14 Q8) | |
| Quantum adversary | out of scope |
- Condition: caller used
OMXMLBuilderFactory.createSOAPModelBuilder(InputStream)(which selects the SOAP profile by default) or explicitly selectedStAXParserConfiguration.SOAP. - Violation symptom: an inbound SOAP envelope containing a
<!DOCTYPE ...>is parsed to completion without an exception, and the XXE / billion-laughs payload triggers. - Severity: security-critical,
VALIDper §13. - (documented:
StAXParserConfiguration.javalines 125-145;OMXMLBuilderFactory.javaSOAP overloads (e.g.createSOAPModelBuilder(InputStream)family))
- Condition: caller explicitly selected
StAXParserConfiguration.STANDALONE. - Violation symptom: an external entity reference (
<!ENTITY foo SYSTEM "http://attacker/" >) results in HTTP fetch to the attacker URL. - Severity: security-critical,
VALIDper §13. - (documented:
StAXParserConfiguration.javalines 72-95)
- Condition: the OM was built by Axiom from a well-formed source.
- Violation symptom: serialized output is not well-formed XML.
- Severity: correctness-only,
VALID-HARDENINGif a downstream parser interprets the malformed output in a security-relevant way (inferred — §14 Q9). - (inferred — §14 Q9)
- Condition: a well-formed MIME multipart input.
- Violation symptom:
PartImpl.getInputStream()returns bytes past the boundary of its part, contaminating a neighboringPart's body. - Severity: security-critical when the parts cross a trust
boundary (e.g. one part is signed/authenticated and a neighboring
part is not);
VALIDper §13. - (inferred — §14 Q10)
- Condition: input is a
Stringorbyte[]. - Violation symptom: Java exception not caught at the caller — but this is Java; memory corruption is JVM-level.
- Severity: correctness-only unless the decoder produces output orders-of-magnitude larger than its input without warning.
- (inferred — §14 Q11)
State each plainly so a triager can route an inbound report to the matching disclaimer.
- No XXE defense on the default
OMXMLBuilderFactory.createOMBuilderpath. The default profile (DEFAULT==PRESERVE_CDATA_SECTIONS) does not disable DTD processing or external entities; it only enables CDATA reporting. Callers handling untrusted non-SOAP XML must explicitly selectSTANDALONE(documented:StAXParserConfiguration.javalines 48-95;OMXMLBuilderFactory.javaline 107). - No defense when the caller passes in a pre-built
XMLStreamReader. Axiom does not re-configure caller-supplied readers; the caller'sXMLInputFactoryis the gate. - No bound on input XML / SOAP / MIME size. Whatever the embedding application supplied, Axiom processes. The StAX implementation may enforce its own limits.
- No bound on the number of parts in a MIME multipart, the size of any individual part, or the total decoded size of a base64 payload.
- No protection against XML signature wrapping. Axiom is the OM; signature-wrapping is the WS-Security layer's concern (WSS4J) (see WSS4J §8 P2).
- No data-at-rest protection. Serialized output is whatever bytes the caller's sink stores.
- No constant-time guarantees. Axiom does not deal with secrets.
- No transport-layer security — there is no transport.
- No protection against a hostile
OMFactory,OMMetaFactory,XMLInputFactory,XMLOutputFactory, orXMLResolverplugged in by the caller. - No defense against side-channel observation.
- No quantum resistance.
- No claim about thread-safety of the OM model across writes.
Concurrent mutation of the same
OMElementis unsupported (inferred — §14 Q12).
DEFAULTprofile name looks safe, but it isn't a hardened default for untrusted bytes.StAXParserConfiguration.DEFAULTis the baseline shape (CDATA preserved); it does not disable XXE / DTD. TheSOAPandSTANDALONEprofiles are the hardened selections (documented:StAXParserConfiguration.java).OMXMLBuilderFactory.createOMBuilder(InputStream)looks symmetric withcreateSOAPModelBuilder(InputStream), but its default profile is different. The SOAP-specific entry point selects the SOAP-hardened profile; the general OM entry point selects DEFAULT.PRESERVE_CDATA_SECTIONSlooks like a security feature, but it isn't. It is a fidelity feature; CDATA preservation is about round-tripping, not safety.MultipartBodyparser looks like a complete RFC 2046 / RFC 5322 email parser, but it isn't. It is targeted at SOAP-with-Attachments / XOP / MTOM and may not handle the full surface of email-style MIME (message/rfc822nested envelopes, transfer-encodingquoted-printableedge cases, …) (inferred — §14 Q3).OMMetaFactoryLocatorsystem property is a privilege-escalation surface, not a feature flag. A class named there isClass.forName- loaded into the running JVM.- The
axiom-domimplementation is not a drop-in W3C DOM; it is a W3C-DOM-shaped view of an Axiom OM (documented:axiom-dommodule purpose).
- XXE / external entity disclosure via the DEFAULT profile.
- Billion-laughs / quadratic blowup via the DEFAULT profile.
- Compression bombs in base64 — decoder size is the caller's bound.
- MIME nesting bombs via deeply-nested multipart bodies (inferred — §14 Q3).
- Signature wrapping — WSS4J's concern.
- MIME boundary smuggling — Axiom parses the boundary the caller's
Content-Typedeclared; if a part body legitimately contains the boundary string and the producer didn't escape, Axiom's behavior is per RFC.
The embedding Java application must:
- For SOAP input, use
OMXMLBuilderFactory.createSOAPModelBuilder(InputStream)(or passStAXParserConfiguration.SOAPexplicitly). The SOAP profile blocks DOCTYPE (documented:StAXParserConfiguration.javaline 135-145). - For general untrusted XML input, explicitly pass
StAXParserConfiguration.STANDALONEtocreateOMBuilder. The barecreateOMBuilder(InputStream)defaults to a profile that does not disable XXE / DTD. - When passing a pre-built
XMLStreamReader, configure the sourceXMLInputFactorywithSUPPORT_DTD=falseandIS_SUPPORTING_EXTERNAL_ENTITIES=false. - Bound the maximum input size at the caller's HTTP / transport layer — Axiom imposes none.
- Bound MIME multipart total size, per-part size, and part count at the caller layer.
- Set
OMMetaFactoryLocatorsystem properties only at JVM startup from a trusted source. - Treat any caller-installed
OMFactory,XMLInputFactory,XMLOutputFactory,XMLResolver, orPartBlobFactoryas part of the security TCB. - For deployment shapes that ingest SOAP envelopes that may carry attachments, route signature-wrapping defense through WSS4J or an equivalent message-level security layer; Axiom is the OM, not the policy.
- Do not let untrusted actors influence the
Content-Typeheader whoseboundaryparameter the MIME parser will key on.
- Calling
OMXMLBuilderFactory.createOMBuilder(InputStream)on attacker-controlled XML and assuming the default profile blocks XXE. It doesn't (documented:StAXParserConfiguration.java). - Using
createSOAPModelBuilder(...)with an explicitStAXParserConfiguration.DEFAULToverride. Override defeats the SOAP-profile DOCTYPE block. - Wrapping a JDK
XMLInputFactorythat was not hardened against XXE. Axiom does not retroactively reconfigure. - Trusting
MultipartBodyto enforce a maximum part count or per-part size. It does not; caller is responsible. - Using
Base64.decodeon attacker bytes and storing the result in memory unbounded. - Setting
OMMetaFactoryLocatorsystem property from a servlet- context init parameter. The named class isClass.forName-loaded. - Mutating the same
OMElementfrom multiple threads. Threading guarantees are unspecified (inferred — §14 Q12). - Mixing
axiom-implandaxiom-domOMs on the sameOMMetaFactorychain. Behavior is undefined (inferred — §14 Q13). - Building a SOAP envelope via the general
createOMBuilderthen callinggetEnvelope(). The two builder paths are not interchangeable; the SOAP path validates SOAP-specific shape (inferred — §14 Q14). - Trusting that
MultipartBody.getPart(contentId)returns at most one part per content-id. Repeated content-ids are RFC-illegal but not necessarily rejected by Axiom (inferred — §14 Q15).
This section is the highest-leverage input for automated agentic security scans. Each entry: tool symptom, why it is safe under the model, the section that licenses the call.
- "
XMLInputFactory.newInstance()inStAXUtilsdoes not setSUPPORT_DTD=false." Axiom's profile-based design intentionally exposes the choice to the caller; theSOAPprofile sets it viadisallowDoctypeDecl(), theSTANDALONEprofile sets it (documented:StAXParserConfiguration.javalines 72-95, 125-145). →KNOWN-NON-FINDINGif the report was against the generalcreateOMBuilderpath; investigate via §14 Q7 otherwise. - "
DocumentBuilderFactory.newInstance()without hardening." Axiom does not provide aDocumentBuilder-based entry point; if a tool flags this againstaxiom-dom, check whetheraxiom-dominternally constructs DOMs from caller OMs (it does not). →KNOWN-NON-FINDING. - "
Class.forName(System.getProperty('org.apache.axiom.om.OMMetaFactoryLocator'))is dynamic-class-loading." Documented locator extension point; the system property is the trust gate. →OUT-OF-MODEL: trusted-input. - "
MultipartBodyreads MIME boundaries fromContent-Typewithout authentication." The MIME parser parses what RFC 2046 says to parse; authentication is a higher-layer concern. →BY-DESIGN: property-disclaimedper §9. - "Hardcoded
'transmitter.jks'/'receiver.jks'password in test resources." No such resource ships inaxiom-api/src/main; if a tool flagstesting/*, that's test data. →OUT-OF-MODEL: unsupported-component. - "
AccessController.doPrivilegeddeprecated in JDK 17." JDK compatibility wrapper. →KNOWN-NON-FINDING. - "
InputStream.close()not in finally." Code-quality finding, not security. →OUT-OF-MODEL: out-of-layer. - "
OMElement.toString()may serialize without escaping." The documented API isOMElement.serialize(OutputStream);toString()is debug-only (inferred — §14 Q16). →KNOWN-NON-FINDING. - "
base64decoder accepts non-canonical whitespace / padding." RFC-permissive behavior; not a security defect. →KNOWN-NON-FINDING. - "
OMXMLBuilderFactory.createOMBuilder(InputStream)enables XXE." By design — the caller chose the DEFAULT profile by not passing one. See §14 Q7 — currently (inferred) asOUT-OF-MODEL: non-default-buildorVALID-HARDENING. →KNOWN-NON-FINDINGonly if Q7 rules the default is "dev-default, caller must pick"; otherwiseVALID-HARDENING. - "
StAXDialectDetectorreflectively loads provider-specific classes." Dialect detection helper; loads only documented provider classes (Woodstox, SJSXP, Stax2). →KNOWN-NON-FINDING. - "
axiom-weavergenerates bytecode at build time." Build-time tool; not in the runtime trust boundary. →OUT-OF-MODEL: unsupported-component. - "
OMTextmay carry binary attachment data — possible deserialization injection."OMTextis a typed leaf, not Java deserialization. →KNOWN-NON-FINDING.
Revise this document when any of the following lands:
- A change in the default
StAXParserConfigurationforOMXMLBuilderFactory.createOMBuilder(InputStream)(e.g. flipping DEFAULT to a hardened profile). - A new
StAXParserConfigurationprofile or a change in the SOAP profile's DOCTYPE block. - A new public entry point on
OMXMLBuilderFactorythat accepts new input shapes. - A new MIME-multipart entry point or a change in
MultipartBody's per-part bound behavior. - A new OM implementation (
axiom-impl/axiom-domsiblings). - A new locator mechanism beyond
OMMetaFactoryLocator. - A change in the supported StAX provider matrix.
- A change in the Jakarta / Javax bifurcation that introduces a new module.
- A vulnerability report that cannot be cleanly routed to one of the §13 dispositions — evidence the model has a gap.
A report against Axiom receives exactly one of the following:
| Disposition | Meaning | Licensed by |
|---|---|---|
VALID |
Violates a §8 property via an in-scope §7 adversary using an in-scope §6 input. | §8, §6, §7 |
VALID-HARDENING |
No §8 property violated, but a §11 misuse pattern can be made harder to fall into by code change. Typically no CVE. | §11 |
OUT-OF-MODEL: trusted-input |
Requires attacker control of a §6 parameter the model marks trusted (caller-supplied XMLStreamReader, hostile OMFactory, system-property-controlled locator). |
§6 |
OUT-OF-MODEL: adversary-not-in-scope |
Requires a §7 actor the model excludes (in-process caller, operator). | §7 |
OUT-OF-MODEL: unsupported-component |
Lands in samples/, systests/, testing/, axiom-weaver/, etc. |
§3 items 5, 6 |
OUT-OF-MODEL: non-default-build |
Only manifests under a StAXParserConfiguration the maintainer rules dev/test (see §14 Q7). |
§5a |
OUT-OF-MODEL: out-of-layer |
Concerns a SOAP / Axis2 / WSS4J responsibility, or a transport / validation step Axiom does not implement. | §3 items 1–3, 7, 8 |
BY-DESIGN: property-disclaimed |
Concerns a §9 property the project explicitly does not provide (no XXE defense on DEFAULT, no MIME size bound, no thread-safety on mutation). | §9 |
KNOWN-NON-FINDING |
Matches a §11a recurring false positive. | §11a |
MODEL-GAP |
Cannot be cleanly routed to any of the above — triggers §12 model revision. | §12 |
Every (inferred) tag in the body maps to one of these. Proposed answers are inline; please confirm, correct, or strike.
Q1. Axiom does not currently ship an in-repo SECURITY.md.
Should the project (a) adopt a SECURITY.md that names a supported-
branch matrix (proposed), (b) leave reporting to the foundation page
only, or (c) defer to the Webservices PMC's umbrella policy? (meta)
Q2. Defects intrinsic to Woodstox / SJSXP / the JDK StAX implementation — confirm policy is "report upstream; Axiom picks up via classpath" (proposed: yes). (maps to §3 item 4)
Q3. Confirm that MultipartBody's MIME parser imposes no
documented bound on:
- total body size
- per-part body size
- number of parts
- MIME nesting depth (nested
multipart/related) Content-Transfer-Encoding: quoted-printableexpansion ratio
Proposed: no bound; caller imposes. (maps to §6, §9, §10 item 5)
Q4. Supported JDK matrix per branch. Proposed: 2.0+ targets a modern JDK (please specify). (maps to §5)
Q5. Negative-side inventory in §5: Axiom opens no sockets, spawns no processes, installs no signal handlers, reads only documented system properties, and writes nothing of its own initiative. Confirm? (maps to §5)
Q6. Build-time variants: confirm there are no compile-time feature toggles that materially change the security envelope (proposed: none). (maps to §5a)
Q7. The big DEFAULT-profile question. A SOAP-specific
constructor exists and uses StAXParserConfiguration.SOAP, which
blocks DOCTYPE. The general OMXMLBuilderFactory.createOMBuilder(InputStream)
constructor defaults to StAXParserConfiguration.DEFAULT, which does
not block XXE / DTD. Is this:
- (a) Supported production posture — i.e. a report that the
bare
createOMBuilder(InputStream)allowed XXE isVALID, and the project will fix by flipping the default; or - (b) "Dev/test default; callers are documented as required to
pick
STANDALONEfor untrusted general XML" — i.e. same report isOUT-OF-MODEL: non-default-build?
Proposed: (b), but a strong argument can be made that the default should be flipped to STANDALONE for safety. (maps to §5a, §9, §10 item 2, §11, §11a, §13)
Q8. Co-tenant in shared JVM and side-channel observers: out of scope (proposed)? (maps to §7)
Q9. §8 P3 (round-trip serialize correctness) — confirm this is
correctness-only, with a VALID-HARDENING carve-out when the
divergence creates a security-meaningful downstream misinterpretation.
(maps to §8 P3)
Q10. §8 P4 (MIME parts do not bleed bytes) — confirm this is a claimed property; identify the existing regression tests that exercise the boundary parsing on adversarial input. (maps to §8 P4)
Q11. §8 P5 (base64 decoder safety) — confirm correctness-only with no claim about output-size expansion. (maps to §8 P5)
Q12. Thread-safety: confirm that concurrent mutation of the
same OMElement is unsupported (proposed); concurrent reads on a
fully-built immutable OM are supported (proposed). (maps to §9, §11)
Q13. Mixing axiom-impl and axiom-dom on the same
OMMetaFactory chain: behavior undefined (proposed)? (maps to §11)
Q14. SOAP shape validation: confirm the SOAP-specific builders validate SOAP-specific structural rules (envelope element, header / body location) and the general builders do not. (maps to §11)
Q15. MultipartBody.getPart(contentId): behavior on repeated
content-id values — first-wins, last-wins, or all-rejected (proposed:
first-wins)? (maps to §11)
Q16. OMElement.toString() semantics — documented as debug-only
(proposed)? (maps to §11a)
Q17. This document should be hosted in-repo at
docs/security/threat-model.md (proposed) or on
ws.apache.org/axiom/? (meta)
Q18. Should this document explicitly note the AGENTS.md
spotless:apply formatting requirement as out of scope (proposed:
out of scope — formatting is not a security property)? (meta)
Q19. §11a known-non-findings is thin (~13 patterns). Could the
Axiom PMC populate from JIRA "not a bug" / "wontfix" closures
(AXIOM-* tickets)? Concrete asks: 3–5 patterns the PMC sees recur in
inbound reports. (meta — §11a)
Q20. What kind of change to Axiom should trigger a revision (proposed list in §12 — confirm or correct)? (meta — §12)
Axiom does not ship a SECURITY.md. The threat-model sources are the
in-repo README.txt, AGENTS.md, the JavaDoc / source comments, the
docs/ directory, and the project website
https://ws.apache.org/axiom/.
| Source | Claim | Lands in |
|---|---|---|
README.txt |
Axiom is the OM library | §1 |
AGENTS.md |
spotless formatting requirement at build time | §5 environment (build-time only) |
axiom-api/src/main/java/org/apache/axiom/om/package.html |
"Contains core interfaces of the Axiom API … defines interfaces for the information items identified by the XML Information Set" | §1, §2 intended use, §2 component-family table |
axiom-api/src/main/java/org/apache/axiom/om/util/StAXParserConfiguration.java lines 48-58, 60-61 |
DEFAULT == PRESERVE_CDATA_SECTIONS — enables CDATA reporting, does not disable DTD / external entities | §5a, §6, §9 first bullet, §11, §11a, §14 Q7 |
StAXParserConfiguration.java lines 72-95 |
STANDALONE sets IS_SUPPORTING_EXTERNAL_ENTITIES=false and installs XMLResolver returning empty content; "to process documents referencing DTDs with system IDs that are network locations" |
§5a, §8 P2, §10 item 2 |
StAXParserConfiguration.java lines 125-145 |
SOAP profile disallows DOCTYPE — "A SOAP message MUST NOT contain a Document Type Declaration" | §5a, §8 P1, §10 item 1 |
axiom-api/src/main/java/org/apache/axiom/om/OMXMLBuilderFactory.java |
general builders use DEFAULT; SOAP builders use SOAP | §4 reachability, §5a insecure-default case, §11 first bullet |
axiom-api/src/main/java/org/apache/axiom/mime/MultipartBody.java (and siblings PartImpl, Part, PartInputStream) |
MIME multipart parser for SOAP-with-Attachments / XOP / MTOM | §2 component-family, §6 trust table, §8 P4, §9 |
axiom-api/src/main/java/org/apache/axiom/locator/ |
OMMetaFactoryLocator system-property + OSGi-service locator |
§3, §5a |
axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/ |
StAX dialect detection (Woodstox, SJSXP, Stax2) | §3 item 4, §5 environment, §11a |
docs/design/osgi-integration.md (per docs/design/README.md) |
OSGi separation between API and implementation | §3 (out-of-scope context for axiom-weaver) |
docs/release-process.md |
Release-engineering process; not a security artifact | meta |
apidocs/ |
Per-module javadoc tree; mineable but no security policy per se | §11a sources |
samples/, systests/, testing/ |
Sample apps, regression suites | §3 item 6 (out-of-scope inventory) |
axiom-weaver/, axiom-weaver-annotations/ |
Build-time bytecode generator for LLOM | §3 item 5 |
axiom-jakarta-activation/, axiom-javax-activation/, axiom-jakarta-jaxb/, axiom-javax-jaxb/, jakarta-bom/, javax-bom/ |
Jakarta / Javax compatibility shims and BOMs | §2 component-family table |
axiom-compat/, axiom-legacy-attachments/ |
Backwards-compat shims | §2 component-family table |