From bb4de1d0088d6d440ee6ac13496e7c6c60d14113 Mon Sep 17 00:00:00 2001 From: Riccardo Manfrin <3090891+riccardomanfrin@users.noreply.github.com> Date: Tue, 8 Sep 2026 15:06:46 +0200 Subject: [PATCH] [client] Read MDM boolean keys delivered as JSON numbers (#7471) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit encoding/json decodes every JSON number into float64, so the policy values the mobile loaders produce never contain int or int64. GetBool accepted both of those but not float64, so a managed boolean pushed as 1 or 0 — how some MDM consoles normalise flags — was reported as unreadable while the key still counted as managed: the policy was not applied, and the conflict gate rejected both values the user could pick for that field. The rejected-float assertion predates the JSON channel. It came with the registry and plist loaders, where a real number for a flag is a configuration mistake; on the JSON channel an integer is the only shape a number can take. GetInt already accepts float64. --- client/mdm/policy.go | 2 ++ client/mdm/policy_test.go | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/client/mdm/policy.go b/client/mdm/policy.go index c57c5303e..638fa0d80 100644 --- a/client/mdm/policy.go +++ b/client/mdm/policy.go @@ -235,6 +235,8 @@ func (p *Policy) GetBool(key string) (bool, bool) { return t != 0, true case int64: return t != 0, true + case float64: + return t != 0, true } return false, false } diff --git a/client/mdm/policy_test.go b/client/mdm/policy_test.go index 177fcd550..ea467f861 100644 --- a/client/mdm/policy_test.go +++ b/client/mdm/policy_test.go @@ -96,7 +96,8 @@ func TestPolicy_GetBool(t *testing.T) { {"int64 nonzero", int64(2), true, true}, {"int64 zero", int64(0), false, true}, {"string garbage", "maybe", false, false}, - {"float unsupported", 1.0, false, false}, + {"float nonzero", 1.0, true, true}, + {"float zero", 0.0, false, true}, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { @@ -156,6 +157,20 @@ func TestPolicy_GetStringSlice(t *testing.T) { }) } +// encoding/json decodes every JSON number into float64, so the mobile +// loaders never see int. +func TestJSONLoader_BoolFromNumber(t *testing.T) { + p := NewJSONLoader(func() string { return `{"blockInbound":1,"disableProfiles":0}` }).Load() + + got, ok := p.GetBool(KeyBlockInbound) + assert.True(t, ok) + assert.True(t, got) + + got, ok = p.GetBool(KeyDisableProfiles) + assert.True(t, ok) + assert.False(t, got) +} + func TestLoader_NilFetcherReturnsEmpty(t *testing.T) { // Loader.Load with no fetcher (desktop construction) must degrade // gracefully and never return nil; on linux loadPlatform is a stub