apache/santuario-xml-security-java), artifact org.apache.santuario:xmlsec.main @ HEAD (2026-06), 4.0.x/3.0.x line.SECURITY.md; §3/§9 findings are closed citing this document.SECURITY.md / advisories (cited); (maintainer) = a Santuario maintainer in this review; (inferred) = reasoned from code/domain, not yet confirmed — each has a §14 open question.What it is. A Java library implementing the W3C XML Signature and XML Encryption standards (plus the JSR-105 javax.xml.crypto API). It is consumed in-process by applications and frameworks (notably WS-Security stacks — WSS4J, CXF, OpenSAML/Shibboleth, Apache Santuario users in SAML/SOAP) to sign, verify, encrypt, and decrypt XML. It ships two implementations: a mature DOM-based stack and a newer StAX (streaming) stack. The security-critical operations are verification and decryption of attacker-controlled XML.
Intended use: an application calls the library to verify a signature on, or decrypt, an XML document that originates outside the application's trust boundary (a SOAP message, a SAML assertion, a signed document). Equally, to produce signatures/ciphertext over its own (trusted) data.
Caller trust level: the calling application is trusted; the XML input to verification/decryption is untrusted and adversary-controlled. This is the defining trust split of the library. (inferred — Q1.)
Component families.
| Family | Entry point | Processes untrusted XML? | In model? |
|---|---|---|---|
| DOM XML Signature (verify) | XMLSignature.checkSignatureValue, SignedInfo | yes | Yes |
| DOM XML Encryption (decrypt) | XMLCipher.doFinal / decryptData | yes | Yes |
| StAX (streaming) Sig/Enc | InboundXMLSec, *InputProcessor | yes | Yes |
| Transforms / canonicalization | Transform, Transforms, Canonicalizer | yes (transform chain runs on attacker XML) | Yes |
| Key resolution | KeyResolver, *KeyResolverSpi | yes (KeyInfo is attacker-supplied) | Yes |
| Signing / encryption (produce) | XMLSignature.sign, XMLCipher.encryptData | no — over trusted data | partial — see §3 |
| JSR-105 API surface | javax.xml.crypto.dsig.* | as above | Yes (delegates to DOM) |
KeyInfo. It does not decide whether K is trusted. Validating the certificate chain / matching K against an allow-list is the **caller’s** responsibility (§10). A report that boils down to “I trusted a self-signed cert in KeyInfo” is OUT-OF-MODEL: trusted-input / BY-DESIGN. (documented — KeyResolver returns keys; trust decisions are not in this layer.)santuario-xml-security-cpp) and the two archived repos — out of scope. (documented — SECURITY.md “retired”.)The boundary is the XML document submitted for verification/decryption. Everything in that document — elements, Reference URIs, Transform chains, KeyInfo, EncryptedKey, algorithm identifiers, namespace prefixes — is attacker-controlled and must be treated as hostile.
untrusted XML (SOAP/SAML/doc) │ attacker controls structure, transforms, KeyInfo, algorithms ▼ parse (DocumentBuilderFactory — DTD handling = §8/§5a) ▼ Signature verify: resolve References -> run Transform chain -> canonicalize -> digest -> verify sig │ ▲ XSLT/XPath transforms run here (§9 false friend) Decrypt: resolve EncryptedKey -> KeyResolver -> unwrap -> decrypt -> (optional) re-parse ▼ result handed to caller ──► caller must check WHO signed + WHAT was signed (§10)
Reachability precondition (the triager's test): a finding is in-model only if reachable from the untrusted XML during verify/decrypt with secure validation enabled (§5a). A finding that requires secure validation to be off, or requires the caller to skip trust/coverage checks, is out of model (§5a / §3).
XMLSignature/XMLCipher instances are not assumed thread-safe; per-operation instances are the expected usage. (inferred — Q4.)Transform/KeyResolver is configured to do — but note the default-resolver and transform behaviour can dereference URIs (§9). (inferred — Q5, high priority.)Secure validation mode is the load-bearing configuration. Santuario exposes a “secure validation” flag (e.g. XMLSignature / XMLCipher.setSecureValidation(true), the org.apache.xml.security.secureValidation property, and on by default in some JSR-105 paths). With secure validation on, the library:
RetrievalMethod/KeyInfo remote dereferencing,Reference/Transform elements to bound expansion. (documented — these are the historical CVE mitigations folded into secure validation; exact set is Q-confirmed in §14.)The insecure-default problem (must be resolved by the maintainer). Whether secure validation is on by default depends on entry point and version (the JSR-105 javax.xml.crypto path vs the native org.apache.xml.security path have differed). This reshapes §8/§9/§11a/§13 simultaneously:
OUT-OF-MODEL: non-default-build and §10 carries “enable secure validation.”Per-parameter trust for the security-critical entry points:
| Entry point | Parameter | Attacker-controllable? | Caller must enforce |
|---|---|---|---|
| signature verify | the XML document / SignedInfo | yes | enable secure validation; check coverage (§10) |
| signature verify | KeyInfo (embedded key/cert) | yes | establish trust in the resolved key — do not trust KeyInfo blindly |
| signature verify | Reference URI / Transform chain | yes | rely on secure validation to bound transforms/derefs |
| decrypt | EncryptedData / EncryptedKey | yes | secure validation; treat decrypted bytes as untrusted |
| decrypt | algorithm identifiers | yes | secure validation enforces allow-list |
| sign / encrypt | content to protect, signing key | no — caller-supplied trusted | protect the private key (caller) |
Plus: the parser-level inputs (DOCTYPE, entities, external refs) are attacker-controlled and governed by §5a/§8.
KeyInfo, algorithms; ability to craft signature-wrapping, transform, key- confusion, decryption-oracle, and resource-exhaustion payloads. (inferred — Q1.)Transform. Severity: critical. (documented.)Reference/Transform elements is capped to bound CPU/memory under secure validation. Violation: super- linear blowup from many references/transforms. Severity: security (DoS). (inferred — Q7: confirm the exact caps.)Reference resolves to the security-relevant content. (documented — canonical caveat.)KeyInfo is a convenience, not a trust decision; certificate-path validation / key pinning is the caller's (§3/§10).KeyInfo, and decryption oracles at the protocol layer.References resolve to the exact content you are about to trust (defeat XSW); prefer ID-based references you control and re-check post-verify.KeyInfo-embedded keys implicitly.KeyInfo keys/certs without path validation → accept attacker's key.DocumentBuilderFactory / transform / weak-algo reachable with secure validation OFF — non-finding: off is the trusted-input posture (§5a); reachability precondition (secure validation on) not met. OUT-OF-MODEL: non-default-build (pending Q6).BY-DESIGN.BY-DESIGN / VALID-HARDENING only if the API makes the safe check unreasonably hard.OUT-OF-MODEL: unsupported-component (§3).| Disposition | Meaning | Licensed by |
|---|---|---|
VALID | A §8 property breaks with secure validation on, via untrusted XML. | §8, §6, §7 |
VALID-HARDENING | No §8 break, but the API makes a §11 misuse (esp. XSW coverage) too easy. | §11 |
OUT-OF-MODEL: trusted-input | Requires attacker control of key-trust / config the model trusts. | §6 |
OUT-OF-MODEL: adversary-not-in-scope | Requires an excluded capability. | §7 |
OUT-OF-MODEL: non-default-build | Only manifests with secure validation off. | §5a |
OUT-OF-MODEL: unsupported-component | Retired C++ / archived repos. | §3 |
BY-DESIGN: property-disclaimed | Key trust, coverage checking, protocol oracles. | §9 |
KNOWN-NON-FINDING | Matches §11a. | §11a |
MODEL-GAP | Unroutable. | triggers §12 |
Wave 1 — the load-bearing ones.
org.apache.xml.security vs JSR-105 javax.xml.crypto, DOM vs StAX, and by version), is secure validation on by default, or must the caller opt in? This decides whether secure-validation-off findings are VALID or OUT-OF-MODEL: non-default-build. (§5a/§8/§9/§11a/§13.)Wave 2 — the secure-validation checklist (confirm/correct the §8 list).
Reference/Transform counts? (§8.)Wave 3 — surface & coexistence.
THREAT_MODEL.md + AGENTS.md alongside your existing SECURITY.md (which we kept). Confirm the disclosure pointer and whether the model should become canonical with SECURITY.md linking to it. (§1/§15.)The repo's SECURITY.md is a disclosure-process + supported-versions policy (no embedded threat model); it points at the ASF security process and the published advisories at santuario.apache.org/secadv.html. This THREAT_MODEL.md is additive — SECURITY.md is preserved and gains a pointer to the model. The published advisories are a high-value source for refining §8/§11a in a later pass (each historical CVE maps to a secure-validation mitigation).