From 66248c738fc7ea553facb44b56ef118af111a3ba Mon Sep 17 00:00:00 2001 From: Magnus Jensen Date: Mon, 4 Aug 2025 17:04:59 +0200 Subject: [PATCH] fix windows configuration profile failing to verify if using CDATA escape (#31564) fixes #29769 See comment for more context: https://github.com/fleetdm/fleet/issues/29769#issuecomment-3150798557 # Checklist for submitter If some of the following don't apply, delete the relevant line. - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually --- ...profiles-with-cdata-escape-fails-to-verify | 1 + server/fleet/microsoft_mdm.go | 12 +++++++++++ server/mdm/microsoft/profile_verifier.go | 4 ++-- server/mdm/microsoft/profile_verifier_test.go | 20 ++++++++++++++----- 4 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 changes/29769-windows-profiles-with-cdata-escape-fails-to-verify diff --git a/changes/29769-windows-profiles-with-cdata-escape-fails-to-verify b/changes/29769-windows-profiles-with-cdata-escape-fails-to-verify new file mode 100644 index 0000000000..1c1cd27db1 --- /dev/null +++ b/changes/29769-windows-profiles-with-cdata-escape-fails-to-verify @@ -0,0 +1 @@ +* Fixed an issue where windows configuration profiles fails to validate due to escaping data sequence with `` and profile verifier not stripping this away. \ No newline at end of file diff --git a/server/fleet/microsoft_mdm.go b/server/fleet/microsoft_mdm.go index a096814e74..b35118a17d 100644 --- a/server/fleet/microsoft_mdm.go +++ b/server/fleet/microsoft_mdm.go @@ -1423,6 +1423,18 @@ func (cmd *SyncMLCmd) GetTargetData() string { return "" } +// GetNormalizedTargetDataForVerification returns the first protocol commands target data +// and normalizes for verification processes +func (cmd *SyncMLCmd) GetNormalizedTargetDataForVerification() string { + content := cmd.GetTargetData() + + content = strings.TrimSpace(content) + content = strings.TrimPrefix(content, "") + + return content +} + func (cmd *SyncMLCmd) ShouldBeTracked(cmdVerb string) bool { if (cmdVerb == "") || cmd.CmdRef == nil || *cmd.CmdRef == "0" { return false diff --git a/server/mdm/microsoft/profile_verifier.go b/server/mdm/microsoft/profile_verifier.go index 4a9006011d..a90fbd462b 100644 --- a/server/mdm/microsoft/profile_verifier.go +++ b/server/mdm/microsoft/profile_verifier.go @@ -50,13 +50,13 @@ func LoopOverExpectedHostProfiles( } for _, rc := range prof.ReplaceCommands { locURI := rc.GetTargetURI() - data := rc.GetTargetData() + data := rc.GetNormalizedTargetDataForVerification() ref := HashLocURI(expectedProf.Name, locURI) fn(expectedProf, ref, locURI, data) } for _, ac := range prof.AddCommands { locURI := ac.GetTargetURI() - data := ac.GetTargetData() + data := ac.GetNormalizedTargetDataForVerification() ref := HashLocURI(expectedProf.Name, locURI) fn(expectedProf, ref, locURI, data) } diff --git a/server/mdm/microsoft/profile_verifier_test.go b/server/mdm/microsoft/profile_verifier_test.go index e4ae74aaae..16ef144dfc 100644 --- a/server/mdm/microsoft/profile_verifier_test.go +++ b/server/mdm/microsoft/profile_verifier_test.go @@ -48,6 +48,10 @@ func TestLoopHostMDMLocURIs(t *testing.T) { {Verb: "Replace", LocURI: "L3", Data: "D3"}, {Verb: "Add", LocURI: "L3.1", Data: "D3.1"}, })}, + "N4": {Name: "N4", RawProfile: syncml.ForTestWithData([]syncml.TestCommand{ + {Verb: "Replace", LocURI: "L4", Data: ""}, + {Verb: "Add", LocURI: "L4.1", Data: ""}, + })}, }, nil } ds.ExpandEmbeddedSecretsFunc = func(ctx context.Context, document string) (string, error) { @@ -77,6 +81,8 @@ func TestLoopHostMDMLocURIs(t *testing.T) { {"L2", "D2", "N2", "2736786183"}, {"L3", "D3", "N3", "894211447"}, {"L3.1", "D3.1", "N3", "3410477854"}, + {"L4", "D4", "N4", "4141459399"}, + {"L4.1", "D4.1", "N4", "236794510"}, }, got, ) @@ -288,8 +294,7 @@ func TestVerifyHostMDMProfilesHappyPaths(t *testing.T) { {"N1", syncml.ForTestWithData([]syncml.TestCommand{{ Verb: "Replace", LocURI: "L1", - Data: ` - + Data: ` @@ -298,7 +303,11 @@ func TestVerifyHostMDMProfilesHappyPaths(t *testing.T) { }, report: []osqueryReport{{ "N1", "200", "L1", - "<Enabled/><Data id=\"EnableScriptBlockInvocationLogging\" value=\"true\"/><Data id=\"ExecutionPolicy\" value=\"AllSigned\"/><Data id=\"Listbox_ModuleNames\" value=\"*\"/><Data id=\"OutputDirectory\" value=\"false\"/><Data id=\"SourcePathForUpdateHelp\" value=\"false\"/>", + ` + + + + `, }}, toVerify: []string{"N1"}, toFail: []string{}, @@ -312,13 +321,14 @@ func TestVerifyHostMDMProfilesHappyPaths(t *testing.T) { Verb: "Replace", LocURI: "L1", Data: ` - + ]]>`, }}), 0}, }, report: []osqueryReport{{ "N1", "200", "L1", - "<Enabled/><Data id=\"EnableScriptBlockInvocationLogging\" value=\"true\"/><Data id=\"ExecutionPolicy\" value=\"AllSigned\"/><Data id=\"Listbox_ModuleNames\" value=\"*\"/><Data id=\"OutputDirectory\" value=\"false\"/><Data id=\"SourcePathForUpdateHelp\" value=\"false\"/>", + ` + `, }}, toVerify: []string{}, toFail: []string{},