From dc89b471faf49eb41960fc9ab93874fe1799d1d2 Mon Sep 17 00:00:00 2001 From: Riccardo Manfrin <3090891+riccardomanfrin@users.noreply.github.com> Date: Wed, 22 Jul 2026 11:34:13 +0200 Subject: [PATCH] [client] checks/enforce MDM disableAutostart on every GUI launch, not just fresh installs (#6782) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Describe your changes `applyAutostartDefault` gated all MDM enforcement behind the one-time `AutostartInitialized` marker, so MDM `disableAutostart` only affected fresh installs — a policy pushed after autostart had been enabled could not revoke the OS login-item. The PR adds follow-up MDM enforcements at the top of the function: if at any time MDM sets `disableAutostart=true` and the OS registration is present, force `SetEnabled(false)` to align it. Trade-off: once the admin lifts the policy, autostart stays off until the user re-toggles in Settings — consistent with "MDM always wins" behavior of the other managed keys. ## Issue ticket number and link Follow-up to PR https://github.com/netbirdio/netbird/pull/6738 (introduced the `disableAutostart` MDM key with fresh-install-only semantics). ## Stack ### Checklist - [x] Is it a bug fix - [ ] Is a typo/documentation fix - [ ] Is a feature enhancement - [ ] It is a refactor - [ ] Created tests that fail without the change (if possible) > By submitting this pull request, you confirm that you have read and agree to the terms of the [Contributor License Agreement](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT.md). ## Documentation Select exactly one: - [x] I added/updated documentation for this change - [ ] Documentation is **not needed** for this change (explain why) ### Docs PR URL (required if "docs added" is checked) Paste the PR link from https://github.com/netbirdio/docs here: ## Summary by CodeRabbit - **New Features** - Added an administrative policy to disable client autostart (“Disable Autostart”). - Added support for configuring this policy via macOS MDM, Windows Group Policy (ADMX/ADML), and registry settings. - When enforced, the client prevents new autostart registration on fresh installs and removes existing autostart on the next GUI launch, keeping it disabled until the policy is lifted. - **Bug Fixes** - Improved enforcement logic for managed autostart defaults so policy state is applied consistently during startup and first-run setup. --- client/ui/autostart_default.go | 20 +++++++++++++++++--- client/ui/services/autostart.go | 2 +- docs/io.netbird.client.plist | 3 +++ docs/netbird-macos.mobileconfig | 2 ++ docs/netbird-macos.sh | 2 ++ docs/netbird-policy.reg | Bin 1490 -> 1558 bytes docs/netbird.adml | 3 +++ docs/netbird.admx | 12 ++++++++++++ 8 files changed, 40 insertions(+), 4 deletions(-) diff --git a/client/ui/autostart_default.go b/client/ui/autostart_default.go index bf1b16a97..162922579 100644 --- a/client/ui/autostart_default.go +++ b/client/ui/autostart_default.go @@ -51,7 +51,7 @@ func autostartDisabledByMDM(policy *mdm.Policy) bool { // netbirdFootprintExists reports whether the machine already carries NetBird // daemon config or state, meaning this is not a genuinely fresh install. It is // the update-safety gate for the autostart default: upgrading users always -// have a footprint, so an update can never trigger a login-item write. +// have a footprint, so an update can never trigger a autostart entry write. func netbirdFootprintExists() bool { candidates := []string{ profilemanager.DefaultConfigPath, @@ -69,9 +69,23 @@ func netbirdFootprintExists() bool { // applyAutostartDefault runs the one-time launch-on-login default for genuinely // fresh installs. The autostartInitialized marker is persisted before any // enable attempt so a crash mid-flow degrades to "never enabled" instead of -// retrying login-item writes on every launch. A user's later disable in +// retrying autostart entry writes on every launch. A user's later disable in // Settings is never overridden: the marker guarantees at-most-once, ever. func applyAutostartDefault(ctx context.Context, autostart *services.Autostart, prefs *preferences.Store, prefsFileExisted bool) { + mdmDisabled := autostartDisabledByMDM(mdm.LoadPolicy()) + + if mdmDisabled { + if enabled, err := autostart.IsEnabled(ctx); err != nil { + log.Warnf("MDM disableAutostart: read autostart state: %v", err) + } else if enabled { + if err := autostart.SetEnabled(ctx, false); err != nil { + log.Warnf("MDM disableAutostart: force off failed: %v", err) + } else { + log.Info("MDM disableAutostart enforced: autostart turned off") + } + } + } + priorFootprint := netbirdFootprintExists() || prefsFileExisted if prefs.Get().AutostartInitialized { @@ -84,7 +98,7 @@ func applyAutostartDefault(ctx context.Context, autostart *services.Autostart, p state := autostartDefaultState{ supported: autostart.Supported(ctx), - mdmDisabled: autostartDisabledByMDM(mdm.LoadPolicy()), + mdmDisabled: mdmDisabled, priorInstall: priorFootprint, } enable, reason := shouldEnableAutostartDefault(state) diff --git a/client/ui/services/autostart.go b/client/ui/services/autostart.go index f7e3aeea0..98e893f04 100644 --- a/client/ui/services/autostart.go +++ b/client/ui/services/autostart.go @@ -10,7 +10,7 @@ import ( "github.com/wailsapp/wails/v3/pkg/application" ) -// Autostart facade over Wails' AutostartManager. The OS login-item registration +// Autostart facade over Wails' AutostartManager. The OS autostart entry registration // is the single source of truth; nothing is mirrored to preferences. type Autostart struct { mgr *application.AutostartManager diff --git a/docs/io.netbird.client.plist b/docs/io.netbird.client.plist index 800ecead1..fe10b5b63 100644 --- a/docs/io.netbird.client.plist +++ b/docs/io.netbird.client.plist @@ -66,6 +66,9 @@ disableAutoConnect + disableAutostart + + disableClientRoutes diff --git a/docs/netbird-macos.mobileconfig b/docs/netbird-macos.mobileconfig index 9bf616094..8216dd55d 100644 --- a/docs/netbird-macos.mobileconfig +++ b/docs/netbird-macos.mobileconfig @@ -103,6 +103,8 @@