VYPR
Critical severityNVD Advisory· Published Mar 6, 2025· Updated Apr 15, 2026

CVE-2025-27509

CVE-2025-27509

Description

fleetdm/fleet is an open source device management, built on osquery. In vulnerable versions of Fleet, an attacker could craft a specially-formed SAML response to forge authentication assertions, provision a new administrative user account if Just-In-Time (JIT) provisioning is enabled, or create new accounts tied to forged assertions if f MDM enrollment is enabled. This vulnerability is fixed in 4.64.2, 4.63.2, 4.62.4, and 4.58.1.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/fleetdm/fleet/v4Go
>= 4.64.0, < 4.64.24.64.2
github.com/fleetdm/fleet/v4Go
>= 4.63.0, < 4.63.24.63.2
github.com/fleetdm/fleet/v4Go
>= 4.62.0, < 4.62.44.62.4
github.com/fleetdm/fleet/v4Go
>= 4.54.0, < 4.58.14.58.1
github.com/fleetdm/fleet/v4Go
< 4.53.24.53.2

Patches

5
718c95e47ad0

Merge commit from fork (#26853)

https://github.com/fleetdm/fleetLuke HeathMar 5, 2025via ghsa
2 files changed · +34 23
  • changes/9778-saml-validation-workflow+1 0 added
    @@ -0,0 +1 @@
    +* Improved SAML validation workflow.
    
  • server/sso/validate.go+33 23 modified
    @@ -15,7 +15,6 @@ import (
     	"github.com/fleetdm/fleet/v4/server/fleet"
     	rtvalidator "github.com/mattermost/xml-roundtrip-validator"
     	dsig "github.com/russellhaering/goxmldsig"
    -	"github.com/russellhaering/goxmldsig/etreeutils"
     )
     
     type Validator interface {
    @@ -161,38 +160,50 @@ func (v *validator) validateSignature(elt *etree.Element) (*etree.Element, error
     		// If entire doc is signed, success, we're done.
     		return validated, nil
     	}
    +	// Some IdPs (like Google) do not sign the root, and only sign the Assertion.
     	if err == dsig.ErrMissingSignature {
    -		// If entire document is not signed find signed assertions, remove assertions
    -		// that are not signed.
    -		err = v.validateAssertionSignature(elt)
    -		if err != nil {
    +		if err := v.validateAssertionSignature(elt); err != nil {
     			return nil, err
     		}
     		return elt, nil
     	}
    -
     	return nil, err
     }
     
    +var (
    +	errMissingAssertion              = errors.New("missing Assertion element under namespace urn:oasis:names:tc:SAML:2.0:assertion")
    +	errMultipleAssertions            = errors.New("multiple Assertions elements found")
    +	errAssertionWithInvalidNamespace = errors.New("Assertion with invalid namespace found")
    +)
    +
    +// validateAssertionSignature validates that one "Assertion" child element exists under
    +// the "urn:oasis:names:tc:SAML:2.0:assertion" namespace and that it's signed by the IdP.
    +// It returns:
    +//   - errMissingAssertion if there is no "Assertion" child element under the given tree.
    +//   - errMultipleAssertions if there's more than one "Assertion" element under the given tree.
    +//   - errAssertionWithInvalidNamespace if an "Assertion" element has a namespace that's not
    +//     "urn:oasis:names:tc:SAML:2.0:assertion"
    +//   - an error if the signature of the one "Assertion" element is invalid.
     func (v *validator) validateAssertionSignature(elt *etree.Element) error {
    -	validateAssertion := func(ctx etreeutils.NSContext, unverified *etree.Element) error {
    -		if unverified.Parent() != elt {
    -			return fmt.Errorf("assertion with unexpected parent: %s", unverified.Parent().Tag)
    -		}
    -		// Remove assertions that are not signed.
    -		detached, err := etreeutils.NSDetatch(ctx, unverified)
    -		if err != nil {
    -			return err
    +	var assertion *etree.Element
    +	for _, child := range elt.ChildElements() {
    +		if child.Tag == "Assertion" {
    +			if child.NamespaceURI() != "urn:oasis:names:tc:SAML:2.0:assertion" {
    +				return errAssertionWithInvalidNamespace
    +			}
    +			if assertion != nil {
    +				return errMultipleAssertions
    +			}
    +			assertion = child
     		}
    -		signed, err := v.context.Validate(detached)
    -		if err != nil {
    -			return err
    -		}
    -		elt.RemoveChild(unverified)
    -		elt.AddChild(signed)
    -		return nil
     	}
    -	return etreeutils.NSFindIterate(elt, "urn:oasis:names:tc:SAML:2.0:assertion", "Assertion", validateAssertion)
    +	if assertion == nil {
    +		return errMissingAssertion
    +	}
    +	if _, err := v.context.Validate(assertion); err != nil {
    +		return fmt.Errorf("failed to validate assertion signature: %w", err)
    +	}
    +	return nil
     }
     
     const (
    @@ -221,7 +232,6 @@ func generateSAMLValidID() (string, error) {
     
     func ValidateAudiences(metadata Metadata, auth fleet.Auth, audiences ...string) error {
     	validator, err := NewValidator(metadata, WithExpectedAudience(audiences...))
    -
     	if err != nil {
     		return fmt.Errorf("create validator from metadata: %w", err)
     	}
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.