Skip to content

Reject enveloped-signature after a transform that returns octets #647

Description

@cjbarth

Problem

A Reference whose transforms put enveloped-signature after a canonicalization, such as [exc-c14n, enveloped-signature], signs and verifies. The canonicalization returns octets, the library parses them into a new document for the next transform (src/signed-xml.ts#L1452-L1474), and enveloped-signature removes the Signature it finds there by its SignatureValue.

XMLDSig doesn't allow that for this transform:

  • §6.6.4: the transform "may only be applied to a node-set from its parent XML document", and it must produce the output of an XPath transform that uses here().
  • §6.6.3: here() "results in an error if the containing XPath expression does not appear in the same XML document against which the XPath expression is being evaluated".

§4.4.3.2 says to parse octets when the next transform needs a node-set. That rule is general, and §6.6.4 excludes this transform from it. #585 added support for the order on the strength of §4.4.3.2 alone.

Other implementations

I signed <root><x>1</x></root> with master (fe2d091), URI="", in both orders:

Verifier [enveloped-signature, exc-c14n] [exc-c14n, enveloped-signature]
xml-crypto master valid valid
.NET System.Security.Cryptography.Xml 6.0.1 valid valid
JDK 21 javax.xml.crypto.dsig valid invalid: the reference digest doesn't match
xmlsec not run not run; its source returns XMLSEC_ERRORS_R_TRANSFORM_SAME_DOCUMENT_REQUIRED

A signature this library creates in that order verifies with .NET and with xml-crypto 6.2.0 or later, and nowhere else I checked. Since 6.2.0 the library's own round trip passes, so the signer gets no sign that anything is wrong. Before 6.2.0 the round trip failed, which is how #111 was reported. That reporter fixed their code by listing enveloped-signature first, and asked for an error if the order is standardized.

This is a conformance problem, not a bypass. #585 removes only the Signature being verified and refuses a document that carries its SignatureValue twice.

In 6.x

#649 deprecates the order in 6.4 (#648). Applying enveloped-signature after octets were parsed prints the DeprecationWarning XML_CRYPTO_ENVELOPED_SIGNATURE_AFTER_CANONICALIZATION, when signing and when verifying, and the README says to list enveloped-signature first.

Proposal

In 7.0, throw when enveloped-signature is applied after an earlier transform of the same Reference returned octets. That covers computeSignature(), checkSignature() and getCanonXml(). The error should name the transform order and §6.6.4.

Then remove what only that order needs:

  • the lookup of the loaded signature in a re-parsed document, in canonicalize()
  • the deprecation warning, and the README paragraph that describes the order
  • the tests that sign or verify it, and the fixtures dotnet_enveloped_signature_after_exc_c14n.xml, dotnet_enveloped_signature_after_c14n.xml and inclusive_namespaces_enveloped_signature_after_exc_c14n.xml
  • inclusive_namespaces_on_second_of_two_exc_c14n.xml, which uses the order to cover per-transform PrefixLists and needs a replacement signed as [enveloped-signature, exc-c14n, exc-c14n PrefixList="b"]

Parsing octets for other transforms stays: a canonicalization followed by another canonicalization or by a custom transform is the §4.4.3.2 case.

Signatures in this order stop verifying, whether a .NET caller or xml-crypto 6.2.0–6.3.x created them, so this belongs in 7.0.

Activity

  1. added this to the v7.0 milestone on Oct 4, 2026
  2. added
    bugWrong behavior: the report of it, the fix, or the revert of a fix
    breaking-changeCan break existing callers; needs a major release. Stands alone or flags another kind
    on Oct 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    breaking-changeCan break existing callers; needs a major release. Stands alone or flags another kindbugWrong behavior: the report of it, the fix, or the revert of a fixsemver-major

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions