From 66b137182abefd741a4b692693ce5bc0d79e4993 Mon Sep 17 00:00:00 2001 From: Artem Chernyshev Date: Mon, 30 Jun 2025 20:06:56 +0300 Subject: [PATCH] fix: properly read namespaces with no prefix from the root element Another attempt to fix: https://github.com/crewjam/saml/pull/580 The code is reading the attributes from the elements in the loop, then writes to a map using `chileEl.Scope` as the key. Intention behind this code is not clear, as the map contains a random string for an empty space, depending which element was the last one. Instead, write the key to the map only if the `childEl` is the element we're encoding. Tested that against Fusion Auth SAML and Microsoft SP with SAML. Can't submit the ACS/Metadata for Microsoft for the testing purposes, as it contains the sensitive data. Signed-off-by: Artem Chernyshev --- go.mod | 2 +- service_provider.go | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 44c05136..ffd3f928 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/crewjam/saml go 1.22 require ( - github.com/golang-jwt/jwt/v5 v5.2.2 github.com/beevik/etree v1.5.0 + github.com/golang-jwt/jwt/v5 v5.2.2 github.com/google/go-cmp v0.7.0 github.com/mattermost/xml-roundtrip-validator v0.1.0 github.com/russellhaering/goxmldsig v1.4.0 diff --git a/service_provider.go b/service_provider.go index c97886d0..ae919480 100644 --- a/service_provider.go +++ b/service_provider.go @@ -1812,6 +1812,10 @@ func findChild(parentEl *etree.Element, childNS string, childTag string) (*etree func elementToBytes(el *etree.Element) ([]byte, error) { namespaces := map[string]string{} for _, childEl := range el.FindElements("//*") { + if el.Tag != childEl.Tag { + continue + } + ns := childEl.NamespaceURI() if ns != "" { namespaces[childEl.Space] = ns @@ -1821,7 +1825,11 @@ func elementToBytes(el *etree.Element) ([]byte, error) { doc := etree.NewDocument() doc.SetRoot(el.Copy()) for space, uri := range namespaces { - doc.Root().CreateAttr("xmlns:"+space, uri) + if space == "" { + doc.Root().CreateAttr("xmlns", uri) + } else { + doc.Root().CreateAttr("xmlns:"+space, uri) + } } return doc.WriteToBytes() @@ -1833,6 +1841,7 @@ func unmarshalElement(el *etree.Element, v interface{}) error { if err != nil { return err } + return xml.Unmarshal(buf, v) }