bee5edaa0bc684e4b2cae32a3743cfe2ddceb026
4258
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
bee5edaa0b |
Add server-side orbit debug logging enablement - currently only configurable as a duration-after-enrollment setting (#45367)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #43997 # 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. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [x] Timeouts are implemented and retries are limited to avoid infinite loops - [x] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes ## Testing - [x] Added/updated automated tests - [x] Where appropriate, [automated tests simulate multiple hosts and test for host isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing) (updates to one hosts's records do not affect another) - [x] QA'd all new/changed functionality manually ## Database migrations - [x] Checked schema for all modified table for columns that will auto-update timestamps during migration. - [x] Confirmed that updating the timestamps is acceptable, and will not cause unwanted side effects. - [x] Ensured the correct collation is explicitly set for character columns (`COLLATE utf8mb4_unicode_ci`). ## fleetd/orbit/Fleet Desktop - [x] Verified compatibility with the latest released version of Fleet (see [Must rule](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/workflows/fleetd-development-and-release-strategy.md)) - [x] Verified that fleetd runs on macOS, Linux and Windows - [x] Verified auto-update works from the released version of component to the new version (see [tools/tuf/test](../tools/tuf/test/README.md)) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Configure Orbit to enable debug logging for a limited window on agent enrollment; enrolled hosts receive debug/verbose behavior while the window is active and it is reflected in agent config. * **Chores** * Added database column to record per-host debug-until timestamps and datastore support to extend it safely. * **Tests** * Added integration and unit tests covering validation, enrollment stamping, config generation, and runtime debug toggling. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45367) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> |
||
|
|
903e3a3f45 |
Sort software titles by display name instead of installer filename (#44873)
Closes #43673 ## Changes Sorts the `/software/titles` endpoint by display name (when set) instead of the internal `software_titles.name` (often an installer filename). **3 changes in `server/datastore/mysql/software_titles.go`:** 1. **Order key mapping** (line 24): `"name"` sort key now maps to `COALESCE(NULLIF(stdn.display_name, ''), st.name)` — uses display name when set, falls back to `st.name`. `NULLIF` ensures cleared display names (empty string) are treated as unset. 2. **Secondary sort** (line 579): Same `COALESCE(NULLIF(...))` expression for tie-breaking when sorting by a non-name column. 3. **LEFT JOIN** (line 635): Joins `software_title_display_names` so the COALESCE expressions can resolve. ## Testing ### Manual testing Inserted test software titles with display names that sort differently from installer filenames. Confirmed: - Before fix: sorted by internal `st.name` (installer filename) - After fix: sorted by display name, with fallback to `st.name` when no display name is set - Verified with `order_direction=asc`, `desc`, and secondary sort via `hosts_count` ### Unit tests `server/datastore/mysql/software_titles_sort_test.go` — 5 subtests (no MySQL required): - Order key mapping uses `NULLIF` for empty display names - Secondary sort uses `NULLIF` for empty display names - Primary name sort doesn't add redundant secondary name sort - SQL template includes `display_names` join - Empty display name falls back to `st.name` in sort expression SQL fixture (`select_software_titles_sql_fixture.gz`) regenerated to match updated queries. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Software titles listing now sorts by team-specific display names when present, falling back to default names; tie-breaking and overall sort behavior refined for more consistent ordering. * **Tests** * Added tests validating display-name sorting, correct fallback for empty names, secondary sort behavior, and generated query structure to ensure consistent results. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44873) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
714ca9af16 |
windows mdm profile bulk insert (#45401)
**Related issue:** Resolves #44804 This does not bulk every sql command, for simplicity. It does not bulk profiles with variables in them, those containing $FLEET_VAR_* placeholders. These still use individual command INSERTs per host. Remove commands are also not bulk-inserted because each removal requires computing activeLocURIs which varies per profile and can result in nil commands that should be skipped. # 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. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [x] Timeouts are implemented and retries are limited to avoid infinite loops - [x] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Reconciler now pre-builds and bulk-inserts Windows MDM commands for non-variable install profiles, reducing repeated writes and improving batching/enqueue efficiency. * Streamlined enqueue + host-profile upsert flow to handle pre-inserted commands and batch host processing. * **Tests** * Added tests for bulk command insertion, duplicate-command handling, and end-to-end enqueue/upsert behavior. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45401) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
77a29167ae |
Fixed Android hosts being auto-deleted by host expiry (#45471)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #45258 The change to zero time is conventionally consistent with the rest of the codebase, and produces zero observable behavior differences anywhere I could find except for the cleanup SQL (which is the bug being fixed). Decided not to do a migration since we do not expect hosts to actually stick around with the `1970-01-02` value, and we have not heard about this issue from customers. # 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] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Resolved an issue where hosts were being automatically deleted and re-enrolled repeatedly when host expiry cleanup was enabled. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45471) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
44732e2012 |
43984 setup experience psso UI updates (#45023)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #43984 # 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] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Updated the setup experience "Users" card to explain automatic creation of local accounts via identity provider credentials (PSSO), improving clarity for admins. * **Documentation** * Added a learn-more link to PSSO local account documentation from the Users card. * **Style** * Improved spacing and description layout within the Users card for better readability. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45023) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
4622eaf87e |
Made host team assignment sticky across orbit and osquery re-enrollments (#45339)
Resolves #43294. - [X] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. - [X] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. ## Testing - [X] Added/updated automated tests - [X] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed an issue where host team assignments were not persisting during re-enrollment. Team assignments are now sticky and remain unchanged when hosts re-enroll using a different team's enrollment secret, ensuring consistent team ownership across re-enrollments. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45339) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
47773c58ad |
Fix enable_host_users defaulting to false on fresh install (#45393)
Closes #44630 ## Summary - After a fresh Fleet install (`fleet prepare db` + `fleetctl setup`), `enable_host_users` persisted as `false` despite the documented and coded default being `true`. - **Root cause**: During setup, `NewAppConfig` correctly saves `enable_host_users: true`. However, the starter library then runs `fleetctl gitops` with a template that has no `features` section. In `DoGitOps`, when `features` is absent, an empty features map is created. `enable_software_inventory` was explicitly defaulted to `true`, but `enable_host_users` was not. The overwrite-mode PATCH then reset `enable_host_users` to `false` (Go's bool zero value). - Adds the same defaulting logic for `enable_host_users` as exists for `enable_software_inventory`, in both the global and team config paths in `DoGitOps`. ## Test plan Reproduced locally before and after the fix with a Fleet server + osqueryd agent (osquery 5.23.0): **Before fix:** 1. Created a fresh database, ran `fleet prepare db`, started `fleet serve --dev`, ran `fleetctl setup`. 2. Checked DB: `enable_host_users` was `false` (bug). 3. Enrolled a local osqueryd agent against the server. 4. Queried the host details API: `users` field was `null` (user collection disabled). 5. Confirmed `features.enable_host_users: false` via `GET /api/latest/fleet/config`. **After fix:** 1. Same steps with the fixed binary. 2. Checked DB: `enable_host_users` was `true` (correct). 3. Enrolled a local osqueryd agent against the server. 4. Queried the host details API: `users` field contained 3 collected users (root, sharonkatz, testuser) -- user collection working. 5. Confirmed `features.enable_host_users: true` via `GET /api/latest/fleet/config`. **Unit tests:** - [x] `TestGitOpsFeatures` -- updated assertion to expect `enable_host_users: true` when features are omitted from GitOps YAML (was previously testing the broken behavior). - [x] All `TestGitOps*` tests pass (`go test ./cmd/fleetctl/fleetctl/ -run TestGitOps`). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Bug Fixes * Fixed default host user collection behavior on fresh Fleet installs. Host user collection now correctly defaults to enabled, matching documented settings and ensuring the host details page displays accurate collection status information instead of incorrectly showing it as disabled. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45393) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
64f5660a95 |
Fix IdP host vitals not populating for MDM-migrated hosts (#41985)
Resolves #41985 Fixed issue were hosts migrated from another MDM via the macOS Tahoe end-user authentication flow had only the IdP email populated on host details because the SCIM user mapping was never created at OTA-enrollment ingest time. |
||
|
|
cfa90d442e |
Add changelog for CIS Win11 v5.0.1 update (#45374)
## Summary - Adds missing changelog entry for #45173 (CIS Win11 Enterprise benchmark v4.0.0 to v5.0.1 update) |
||
|
|
117a137ee1 |
fix Actions dropdown in Run script modal auto-closing (#45349)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #43640 # Checklist for submitter - [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] QA'd all new/changed functionality manually I figured out that the RunScriptModal was being re-rendered without any user events or network calls after the 2s mark. At first I thought the parent (ScriptModalGroup.tsx) could have been the culprit since there's a lot going on there (lots of callback functions passed to multiple modals). It turns out that RunScriptModal is wrapped in React.memo to avoid re-rendering but since some of its props changed in the parent component, this caused it to re-render and close the Actions dropdown randomly. To detect which where the problematic props changing, I threw this code at the top of RunScriptModal.tsx: ```react const prev = useRef<any>({}); useEffect(() => { const current = { currentUser, hostTeamId, onClose, page, setPage, hostScriptResponse, isFetchingHostScripts, isLoadingHostScripts, isError, onClickViewScript, onClickRunDetails, onClickRun, isRunningScript, isHidden, }; const changed = Object.entries(current).filter( ([k, v]) => prev.current[k] !== v ); console.log( "RunScriptModal re-render. Changed props:", changed.map(([k]) => k) ); prev.current = current; }); ``` and the output was: ``` RunScriptModal re-render. Changed props: (2) ['onClickViewScript', 'onClickRunDetails'] ``` So I just wrapped those two in useCallback and that fixed the issue. https://github.com/user-attachments/assets/f6eae13e-2a60-4fda-9468-2952acdedd58 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Bug Fixes * Fixed the Actions dropdown in the Run script modal on the Host details page auto-closing after 2-3 seconds. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45349) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
b1ecaefedc |
Fix cond access bypass activity on unrelated app config saves
Fixes #43609 and #43566 Fixed bug were toggling GitOps mode was creating a spurious update_conditional_access_bypass activity whenever Okta conditional access was already configured with bypass_disabled=true. |
||
|
|
038d4458cc |
Fix homebrew package matching incorrect CPE (#45186)
**Related issue:** Resolves #35195 |
||
|
|
683a66b4d1 |
Recovery Key can be viewed after team transfer if still present (#45280)
**Related issue:** Resolves #44459 ## Summary Fixed an issue where the recovery lock password for a macOS host could become unretrievable via the UI and API after the host was transferred to a team with recovery lock disabled, even though the password was still stored in the database. ## Root causes Three bugs combined to produce the symptom: - **Frontend visibility**: `canShowRecoveryLockPassword` gated the "Show Recovery Lock password" action on the current team's `enable_recovery_lock_password` setting and ignored the `recoveryLockPasswordAvailable` signal, so the UI option vanished whenever the host's new team had the feature off. - **API 404 on view**: `MarkRecoveryLockPasswordViewed` returned a `notFound` error when its UPDATE matched zero rows. This happened as soon as the `ClaimHostsForRecoveryLockClear` cron flipped the password row's `operation_type` from `install` to `remove` — causing `GET /hosts/:id/recovery_lock_password` to 404 even though the password had already been successfully retrieved and decrypted moments earlier in the same request. - **Stale rotation deadline**: `ClaimHostsForRecoveryLockClear` left the row's `auto_rotate_at` untouched when flipping to `remove`, so subsequent reads still surfaced the pre-transfer view-deadline and the UI rendered a rotation banner promising an auto-rotation that the cron (filtered on `operation_type='install'`) would never honor. ## Fix - **Frontend**: updated `canShowRecoveryLockPassword` to also show the action when a password is available, regardless of the team setting. - **API**: changed `MarkRecoveryLockPasswordViewed` to return a zero `time.Time` with no error when no install-state row exists. The service skips the `AutoRotateAt` assignment in that case and explicitly nulls any stale value loaded from the DB, so the response's `auto_rotate_at` is omitted. - **Data hygiene**: updated `ClaimHostsForRecoveryLockClear` to also set `auto_rotate_at = NULL` when flipping a row to `remove`, since the rotation deadline is meaningful only for install-state rows. - [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. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. |
||
|
|
4390d57f74 |
Fix POST /queries returning 500 on JSON null name/query (#43031)
Fixes #43031 Make sure we reject nil Name or Query in NewQuery with a BadRequestError before Verify(). |
||
|
|
8228f50511 |
Reject null name on POST /packs (#43032)
Fixes #43032 Added a nil-check in NewPack so a missing/null name returns the same BadRequestError as an empty-string name. |
||
|
|
c5c2dd9d4d | Fix more unreleased dark mode contrast bugs (#45295) | ||
|
|
f4b6b45997 | Bump Go to 1.26.3 to clear stdlib CVEs (#45277) | ||
|
|
049f29ee3f |
Apply labels before consumers in GitOps (#45194)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #44046 # Details Updates GitOps to ensure that team labels are created before any consumers (e.g. profiles, policies, software) that might use the labels are applied. It does this by adding a new `afterTeamApply` callback option to `ApplyGroup` that is called after team config is applied -- this is when team labels are now created, instead of after `ApplyGroup` runs. # 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 - [ ] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed GitOps deployments failing when a label and a profile that references it are created in the same run. * Ensures the correct apply ordering so dry-run/log output shows label application before profile application. * **Tests** * Added a regression test validating label → profile apply ordering to prevent future regressions. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45194) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
f67e13a29d |
Show uninstall button even if software title is not found in inventory (#45273)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #42026 - Show "uninstall" button if the status is `installed` (or `recently_installed`) which just reflects that the install script ran successfully, not that the software title for the installer is in the software inventory. For example, even with a no-op install script that exits successfully the button will be available. - Make the status clickable by removing the recentlyTakenAction check, since that only represents the last install script that ran. This should only really affect the `recently_installed` status (according to claude at least). This behaviour is already possible through the API, but it mostly depends on the specific uninstall scripts if they will pass or fail when the software doesn't even exist. # 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 - [ ] Where appropriate, [automated tests simulate multiple hosts and test for host isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing) (updates to one hosts's records do not affect another) - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Uninstall option now appears for installers even when the host inventory lacks a matching software entry, ensuring uninstall remains accessible. * **Tests** * Added regression tests verifying the uninstall button is visible and enabled for relevant installed states, including on personal device pages. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45273) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
89843674b8 |
Reduce fleet and fleetctl binary sizes by removing debug symbols (#45260)
Resolves #45256 In macOS: before: 129 MB build/fleet, 58 MB build/fleetctl. after: 86 MB build/fleet, 42 MB build/fleetctl. - [X] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. ## Testing - [X] QA'd all new/changed functionality manually. (Basic smoke testing of the binaries in macOS.) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Optimized binary sizes for fleet and fleetctl releases. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45260) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
2391b9261e |
Fix Location and MDM status vitals looking clickable on My device page (#43279)
Fixes #43279 On the My device page (DeviceUserPage), the Location and MDM status rows in the Vitals card rendered as <Button variant="link"> even though no modal was wired up, so clicking did nothing while the link styling implied otherwise. |
||
|
|
1dc0ee2ea4 |
Fix back-to-host-details button on report details page (#39727) (#45238)
Resolves #39727 Fixed bug on QueryDetailsPage's backPath() implementation, so the "Back to host details" button does not followed the stale filteredQueriesPath set when the user previously visited the reports page. |
||
|
|
9a5fae6f02 |
Scope windows mdm profile removal query (#45203)
**Related issue:** Resolves #44798 # 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. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. ## Testing - [x] Added/updated automated tests - [x] Where appropriate, [automated tests simulate multiple hosts and test for host isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing) (updates to one hosts's records do not affect another) - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Performance Improvements** * Optimized Windows MDM profile removal operations for improved performance when managing device profiles. * **Bug Fixes** * Enhanced Windows profile handling during host team transfers to ensure correct profiles are properly installed and removed based on team configuration. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45203) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
46784bbb52 |
Add host activity entries for retried software installs and script runs from policy automations (#45233)
Resolves #42930 - [X] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. Ready for review, pending [this](https://fleetdm.slack.com/archives/C084F4MKYSJ/p1778593457182719) UX question. ## Testing - [X] Added/updated automated tests - [X] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Host activity details are now recorded and displayed for every attempt — including queued and pending retries — of script executions and software installations triggered by policy automations. * **Tests** * Integration tests updated to assert activity creation for each failed attempt and retry flows. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45233) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
0276662545 |
Fix MDM SSO callback 'missing profile' error for Android enrollment (#45046)
Closes #45024 ## Summary - Fixed the MDM SSO callback handler returning a `"missing profile: missing profile"` error when an Android device enrolls via SSO (OTA enrollment) on a Fleet instance that does **not** have Apple MDM configured. - Refactored all MDM SSO initiator magic strings (`"ota_enroll"`, `"setup_experience"`, `"account_driven_enroll"`) into named constants (`fleet.SSOInitiatorOTAEnroll`, etc.) to prevent typos and missed cases — which is the class of bug that caused this issue. ## Code walkthrough ### The bug The bug is in `ee/server/service/mdm.go` in `mdmSSOHandleCallbackAuth()`. **The flow:** 1. Android enrollment hits `/enroll?enroll_secret=xxx` → frontend calls `InitiateMDMSSO` with initiator `"ota_enroll"` (`server/service/frontend.go:248`) 2. User authenticates at the SAML IdP 3. The SSO callback arrives at `MDMSSOCallback` → calls `mdmSSOHandleCallbackAuth` 4. After successful SAML auth, the function checks early-exit conditions: - Line 1133: account-driven enrollment (`originalURL == appleMDMAccountDrivenEnrollmentUrl`) → **no match** for OTA - Line 1139: `Initiator != "setup_experience"` → **true** for `"ota_enroll"` → enters the block 5. Line 1140: calls `getAutomaticEnrollmentProfile()` → returns `nil` because **no Apple MDM is configured** 6. Line 1144–1146: `depProf == nil` → **returns `"missing profile"` error** Note that `MDMSSOCallback` (the caller) already has a guard at line 931 that correctly skips the Apple MDM verification for `/enroll?` paths: ```go if !strings.HasPrefix(originalURL, "/enroll?") && ssoRequestData.Initiator != "setup_experience" { if err := svc.VerifyMDMAppleConfigured(ctx); err != nil { ... } } ``` But `mdmSSOHandleCallbackAuth` was missing the equivalent guard — it unconditionally tried to fetch the Apple DEP profile for any non-`setup_experience` initiator. ### The fix Adds an early return for OTA enrollments (where `originalURL` starts with `/enroll?`), matching the existing pattern for account-driven enrollments right above it. OTA enrollments don't use the Apple DEP profile token. ### The refactor Replaced all raw initiator string literals across the backend with named constants defined in `server/fleet/app.go`: | Constant | Value | Used by | |---|---|---| | `fleet.SSOInitiatorOTAEnroll` | `"ota_enroll"` | `/enroll` page (Android, BYOD iPhone/iPad) | | `fleet.SSOInitiatorSetupExperience` | `"setup_experience"` | Orbit agent (macOS Setup Assistant) | | `fleet.SSOInitiatorAccountDrivenEnroll` | `"account_driven_enroll"` | Apple account-driven MDM enrollment | Constants are in `server/fleet/` (not `server/sso/`) so orbit can import them without pulling in Redis dependencies. **Files changed:** - `ee/server/service/mdm.go` — 6 string replacements (switch cases + comparisons) - `server/service/frontend.go` — 1 replacement - `orbit/cmd/orbit/orbit.go` — 1 replacement - `server/service/testing_client.go` — 1 replacement - `server/service/integration_mdm_test.go` — 1 replacement ## Local reproduction ### Setup 1. Started dev server: `build/fleet serve --dev --dev_license` 2. Infrastructure: MySQL, Redis, SimpleSAML IdP via `docker compose up` 3. Created admin user and enroll secret 4. Configured MDM SSO (`entity_id: mdm.test.com`, SimpleSAML IdP at `localhost:9080`) 5. Set `enable_end_user_authentication: true` directly in DB (API blocks this without Apple MDM — matches customer state) 6. **Did NOT configure Apple MDM** — only SSO + EUA, simulating Android-only instance ### Steps 1. `GET https://localhost:8080/enroll?enroll_secret=test_enroll_secret` → 303 redirect to SimpleSAML IdP 2. Completed SAML login programmatically (user: `sso_user`, pass: `user123#`) 3. `POST https://localhost:8080/api/v1/fleet/mdm/sso/callback` with the SAMLResponse ### Before fix ``` === CALLBACK RESULT === Status: HTTP/2 303 Location: /mdm/sso/callback?error=true === SERVER LOGS === ts=2026-05-08T16:53:49Z level=error component=http method=POST uri=/api/v1/fleet/mdm/sso/callback took=12.148708ms err="missing profile: missing profile" ``` ### After fix ``` === CALLBACK RESULT === Status: HTTP/2 303 Location: /enroll?enroll_secret=test_enroll_secret&enrollment_reference=7c67326c-...&initiator=ota_enroll&profile_token= === SERVER LOGS === ts=2026-05-08T17:27:54Z level=info component=http method=POST uri=/api/v1/fleet/mdm/sso/callback took=15.973ms ``` No errors. Successful redirect back to the enrollment page with the enrollment reference. ## Integration test Added `TestOTAEnrollSSOWithoutAppleDEPProfile` which: 1. Configures SSO and creates a team with IdP enabled 2. **Deletes all Apple DEP enrollment profiles** to simulate an Android-only instance 3. Runs the full OTA enrollment SSO flow (GET `/enroll` → SAML IdP login → callback) 4. Verifies the callback redirects to `/enroll?...` with `enrollment_reference` and `initiator=ota_enroll` (not `?error=true`) Confirmed the test **fails without the fix** (`err="missing profile: missing profile"`) and **passes with the fix**. Also added a `LoginOTAEnrollSSOUser` test helper that drives the complete OTA SSO flow starting from `GET /enroll` through SAML IdP login to the callback, using a single cookie jar. ## Test plan - [ ] Verify Android SSO enrollment works on an instance with **only** Android MDM configured (no Apple MDM) - [ ] Verify Apple DEP enrollment with SSO still works (the DEP profile path is unchanged) - [ ] Verify Apple OTA enrollment with SSO still works (also uses `/enroll?` path) - [ ] Verify account-driven enrollment with SSO still works (has its own early return) - [ ] Verify setup experience SSO still works (uses `Initiator == "setup_experience"`) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Resolved a regression where OTA enrollment via SSO could return a "missing profile" error on Android when Apple MDM is not configured; OTA SSO now redirects correctly to the enrollment flow. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45046) <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Magnus Jensen <magnus@fleetdm.com> |
||
|
|
2935856f37 |
validate apple payload scope conflict, and unknown variable use in dry-run (#45139)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #44456 # 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. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [x] Timeouts are implemented and retries are limited to avoid infinite loops - [x] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Dry-run now performs Apple config profile payload scope conflict validation and reports unknown Fleet variables for all profile types before completing. * **Tests** * Added tests covering Apple config profile scope-conflict validation and dry-run/batch profile workflows to ensure conflicts are detected in both dry-run and live flows. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45139) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
b0dc97006c |
Dedupe network errors so usage_statistics cron stops failing (#45142)
**Related issue:** Resolves #42613 Dedupes errors that report HTTP 408 (request timeouts). As of now, I believe this only fires for timeouts on the **/api/v1/osquery/distributed/write** endpoint. This is so that we have a unique error hash with an incrementing count, instead of thousands of entries each with count: 1, which produces a huge JSON payload when passed to https://fleetdm.com/api/v1/webhooks/receive-usage-analytics for processing. Trade-off: - Before: every occurrence got its own Redis entry so thousands of near-identical examples coexisted. - After: they collapse into one entry whose :json value still contains a representative example, but we'd only keep the last IP+Port instead of all of them. # Checklist for submitter - [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 Build a ~5 MB JSON body in a temporary file: ```bash { printf '{"node_key":"'; head -c 5000000 /dev/zero | tr '\0' 'x'; printf '"}'; } > /tmp/distwrite-body.json ``` Clear out redis: ```bash docker exec fleet-redis-1 redis-cli FLUSHDB ``` Send a dummy request and throttle the upload at 100 KB/s → ~50s to send, read timeout fires at 25s. I sent this 3 times and got the "request body read error" error back after each request. ```bash curl -sk --limit-rate 100K -X POST -H 'Content-Type: application/json' --data-binary @/tmp/distwrite-body.json https://127.0.0.1:8080/api/v1/osquery/distributed/write { "error": "request body read error: i/o timeout", "uuid": "95937f50-1008-4625-9423-bc19c7be6818" } ``` Count the error keys containing "request body read error" as the value. ```bash docker exec fleet-redis-1 sh -c 'for k in $(redis-cli --scan --pattern "error:*:json"); do v=$(redis-cli GET "$k"); echo "$v" | grep -q "request body read error" && echo "$k count=$(redis-cli GET "${k%:json}:count")"; done'\ error:{Cco_JmAdBVVVJI9k0XjNNUCmG0z1IKguMQD4VDaejfc=}:json count=3 ``` Notice the single entry and count=3 (since I ran the dummy request 3 times). Running this on main outputs three entries each with count=1. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Network error deduplication for request-timeout errors now normalizes socket addresses, preventing the usage statistics cron from failing when many similar network errors accumulate. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45142) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
1213e5da12 |
Fixed validation that rejected enabling end user authentication on Fleet deployments without Apple MDM configured (#45162)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #44801 Note there is a related bug: https://github.com/fleetdm/fleet/issues/45170 # 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`. ## Testing - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * End user authentication can now be enabled for Windows-only and Linux-only fleets without requiring macOS MDM configuration. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45162) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
fe16654729 |
Allow glob literals in filenames (#44547)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #43598 # 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 - [X] added a script file `some-*-script[].sh` and referred to it in a gitops file using `path:`. Failed on main; on this branch it successfully uploaded the script - [X] still got expected error message when using `path: ` with a value that had glob characters that _didn't_ match an actual file - [X] `paths:` still worked and uploaded multiple files, including `some-*-script[].sh` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed path validation in fleetctl gitops so path values containing glob metacharacters (e.g., brackets, asterisks, question marks) are accepted when a literal file with that name exists on disk; missing files still produce the appropriate error. * **Tests** * Added regression tests covering glob metacharacter handling in path validation. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44547) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
c7364d555c |
Officially deprecated setup_experience.software (#44549)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #42503 # 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 - [X] setting `software:` under `macos_setup` or `setup_experience` triggers the expected warning. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Deprecations** * Using setup_experience.software or macos_setup.software now emits a deprecation warning. Migrate by setting setup_experience: true on individual software items (packages, App Store apps, or fleet-maintained apps). * **Tests** * Added test coverage to verify the deprecation warning is emitted when applicable and absent otherwise. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44549) <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> |
||
|
|
348fa47c84 |
Improve name key validation in GitOps (#44553)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves # # 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 - [X] omitted `name:` from a file without `org_settings:`, got: ``` * No `name` was provided in /tmp/testback/fleets/third-fleet.yml. If this file is intended to define org-level settings, add `org_settings:` as a top-level key. Otherwise, use `name` to specify the fleet name. ``` - [X] omitted `name:` from a file with `org_settings:`, got no error. - [X] omitted `name:` from `no-team.yml`, got: ``` * `name` must be `No Team` for `no-team.yml` ``` - [X] omitted `name:` from `unassigned.yml`, got: ``` * `name` must be `Unassigned` for `unassigned.yml` ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved error messages when GitOps YAML files omit the required `name` field, with specific remediation guidance tailored to each configuration file type * Enhanced validation error messaging when top-level `org_settings` is missing or incorrectly placed, providing clearer instructions on required YAML structure <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
8b779110a8 |
Remove verb and url from gitops errors (#44555)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #43721 # 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 Added a Google Calendar integration to gitops .yml with `client_email` missing from the `api_json_key`. - [X] on main, got error: ``` Error: applying fleet config: PATCH /api/latest/fleet/config received status 422 Validation Failed: client_email is required (API time: 13ms) ``` - [X] on this branch, got: ``` Error: applying fleet config: Validation Failed: client_email is required (API time: 134ms) ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Cleaner CLI error messages: removed extraneous HTTP path/status-code details from GitOps-related errors, making output easier to read. * **Tests** * Added tests to verify the improved error message handling and nil/non-wrapped error behavior. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44555) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
f5c59ae3b4 |
Fix google calendar key validation (#44556)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #42886 # 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 - [X] gitops run with extra keys (besides `client_email` and `private_key` in `api_key_json` fails on main, passes on this branch - [X] gitops run with missing `client_email` or `private_key` in `api_key_json` still fails gitops (including dry run) - [X] gitops run with extra keys sibling to api_key_json still fails as expected <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Corrected GitOps validation so Google Calendar API key JSON no longer rejects valid nested keys; required-field validation for the integration still enforced. * **Tests** * Added test coverage to ensure nested unknown keys are accepted while sibling-level unknown fields are reported as validation errors. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44556) <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Tim Lee <timlee@fleetdm.com> |
||
|
|
42210d0a96 |
inconsistent alignment fleet premium (#45125)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #43646 <img width="809" height="149" alt="image" src="https://github.com/user-attachments/assets/cf7b55ae-4d79-4686-a9e5-e9e68e4b2e65" /> <img width="851" height="190" alt="image" src="https://github.com/user-attachments/assets/0c70a2b6-091c-4222-b9a9-c4d46f9b0f5b" /> # 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. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [x] Timeouts are implemented and retries are limited to avoid infinite loops - [x] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes ## Testing - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed alignment inconsistency for premium feature messages in Fleet settings. Premium notifications across Disk Encryption and Passwords controls now display with proper alignment on Fleet Free tier. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45125) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
146f0c8589 |
LabelForm: replace 'teams' with 'fleets' (#44770)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> Ad-hoc issue detected when reviewing https://github.com/fleetdm/fleet/pull/44410 Resolves: #45141 # Checklist for submitter - [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 ### Before <img width="993" height="603" alt="Screenshot 2026-05-05 at 9 35 13 PM" src="https://github.com/user-attachments/assets/4c410c92-a44b-4018-b5a5-edba7b83e539" /> ### After <img width="982" height="569" alt="Screenshot 2026-05-05 at 9 50 26 PM" src="https://github.com/user-attachments/assets/36d45053-5595-4758-b515-7a8c854a3986" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **UI Updates** * Updated label form terminology to refer to "fleets" instead of "teams" throughout the label management interface * Modified field names, labels, and help text to use consistent fleet-related language * Updated copy on the Edit Label page to mention fleets when applicable * Streamlined form field layout for improved presentation [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44770) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
7742c82eb7 |
Fix upcoming activity count not refreshing after host software install (#37012)
Resolves #37012 Invalidate the upcoming-activities cache on software install/uninstall. |
||
|
|
714ae967fe |
Fix: SCIM user creation 500s when host already has a SCIM mapping (#44275)
**Related issue:** Resolves #43656 ## Summary When a new SCIM user is associated to a host that was previously associated to another SCIM user (different username/email), we the host_scim_user record is upserted with the new SCIM user's ID (instead of 500ing). # Checklist for submitter - [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. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually Setup: - Host associated with a SCIM user. I first enrolled a Linux host with end user authentication enabled, and logged in with **nico+testeua@fleetdm.com**. This creates a record in the **mdm_idp_accounts** table. - Provisioned the **nico+testeua@fleetdm.com** user from Okta to Fleet by following this guide: https://fleetdm.com/guides/foreign-vitals-map-idp-users-to-hosts#step-1-create-application-in-okta. This creates records in **scim_users** and **host_scim_user** tables. <img width="705" height="269" alt="Screenshot 2026-05-11 at 10 22 33 AM" src="https://github.com/user-attachments/assets/1f1a03ee-494c-4b09-a020-fe38b73a6b0b" /> <img width="502" height="136" alt="Screenshot 2026-05-11 at 10 26 59 AM" src="https://github.com/user-attachments/assets/42cd84d7-0a43-4937-90ed-0dbb0066ff32" /> #### Before (main branch) - Changed **username** to **nico+test500main** and **email** to **nico+test500main@fleetdm.com** on the **mdm_idp_accounts** record from the setup. - Replayed the **POST /api/v1/fleet/scim/Users** request from the Setup, but modified **username** and **email** to **nico+test500main@fleetdm.com**. This reproduced the 500. <img width="1201" height="599" alt="Screenshot 2026-05-11 at 10 30 26 AM" src="https://github.com/user-attachments/assets/abd4541a-b900-4171-9cee-03c7780045a0" /> #### After Performed the same steps as above, now with **nico+test500**: Request: <img width="1235" height="708" alt="Screenshot 2026-05-11 at 10 26 42 AM" src="https://github.com/user-attachments/assets/ef0fde5e-7b2f-48af-ac4b-ed2897a4e54b" /> UI: <img width="697" height="294" alt="Screenshot 2026-05-11 at 10 27 46 AM" src="https://github.com/user-attachments/assets/2c033f1c-483c-43c5-b901-d949a24a8a5a" /> DB: **scim_users** table contains both records and **host_scim_user** mapping was updated to the new scim_user ID. <img width="795" height="159" alt="Screenshot 2026-05-11 at 10 26 53 AM" src="https://github.com/user-attachments/assets/73ecfcd7-d6be-4e47-90ea-760d5f6d6cc3" /> <img width="501" height="134" alt="Screenshot 2026-05-11 at 10 27 05 AM" src="https://github.com/user-attachments/assets/a24140f9-070f-4236-b80d-910a21504efd" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed HTTP 500 errors on the SCIM Users endpoint when associating a user with a host that already had an existing SCIM user mapping; host mappings are now reassigned to the newly created SCIM user as needed. * **Tests** * Added a test ensuring creating a second SCIM user for the same host succeeds and does not create duplicate host–user mappings. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44275) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
89517cce2f |
Warn when labels key appears in no-team/unassigned GitOps files (#44865)
Closes #42522 ## Changes When `labels:` appears in a no-team/unassigned GitOps file, log a warning and skip label parsing. This matches the existing pattern used by `agent_options` and `reports` in no-team files. A warning (not an error) is used intentionally to avoid breaking existing customer GitOps pipelines that may already have `labels:` in their no-team file. **After fix:** ``` [!] 'labels' is not supported in unassigned.yml. This key will be ignored. ``` ## Testing ### Manual testing Built `fleetctl` from the fixed branch against a local Fleet server (premium license). | Scenario | Result | |---|---| | `unassigned.yml` dry-run | Warning printed, succeeds | | `unassigned.yml` real run | Warning printed, succeeds | | `no-team.yml` dry-run | Warning printed, succeeds | | `no-team.yml` real run | Warning printed, succeeds | | `unassigned.yml` without labels | No warning, succeeds (no regression) | ### Unit tests - **`TestLabelsIgnoredInNoTeamFile`**: Sub-tests for both `no-team.yml` and `unassigned.yml` assert: (1) no error, (2) `LabelsPresent` is true, (3) no labels parsed, (4) warning logged. --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> |
||
|
|
04d773f10f |
Fix get policy by id endpoint and unify access in UI (#45048)
**Related issue:** Resolves https://github.com/fleetdm/fleet/issues/44949. - [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 For unreleased bug fixes in a release candidate, one of: - [X] Confirmed that the fix is not expected to adversely impact load test results. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Policy retrieval now correctly enforces team authorization, preventing unauthorized cross-team access and ensuring team policies are returned properly. * **New Features** * UI uses a unified policy access path for viewing/editing policies, improving consistency for inherited/team-scoped policies, back-navigation, and fleet-name display (All fleets / No team). * **Tests** * Added unit and integration tests covering cross-team access rules and that policy automation fields are populated when policies are returned. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
d439cb1690 |
Fix missing deleted_policy activity for auto-cleaned patch policies (#45045)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #44286 Unset `patch_software_title_id` rather than deleting the policy in `BatchSetSoftwareInstallers`, so the orphaned policy gets picked up by the `policiesToDelete` loop in `server/service/client.go:3121`. As a result, the `deleted_policy` activity is now created properly, and gitops dry/real runs also report the deletion: ``` dry run: [-] would've deleted policy macOS - 010 Editor up to date [-] would've deleted 1 policy real run: [-] deleting policy macOS - 010 Editor up to date [-] deleting 1 policy [-] deleted 1 policy ``` # 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. - [ ] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [ ] Timeouts are implemented and retries are limited to avoid infinite loops - [ ] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes ## Testing - [x] Added/updated automated tests - [ ] Where appropriate, [automated tests simulate multiple hosts and test for host isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing) (updates to one hosts's records do not affect another) - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed missing deletion activity logs when patch policies are removed via GitOps so policy deletion events are now recorded. * **Behavior Changes** * Batch-updating installers now retains obsolete patch policies but clears their patch installer reference instead of deleting the policy. * **Tests** * Added integration coverage to verify deletion activities are emitted and installer batch behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
c85d40636e |
Fix gitops controls set criteria (#45007)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #NA Found this while just browsing the codebase and testing some gitops stuff. # 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. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [x] Timeouts are implemented and retries are limited to avoid infinite loops - [x] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes ## Testing - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed GitOps controls detection to correctly identify when controls are set with specific configurations, including BitLocker PIN requirements. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
d2033df253 | Fleet UI: Fix export button dependencies (#45020) | ||
|
|
f60ce942f8 |
Make activity list end-date filter consistent (#38437)
Resolves #38437 The list activities endpoint applied an implicit `created_at <= now` cap only when `start_created_at` was set, leaving the upper bound unbounded in every other case, this was changed so that we now apply that cap unconditionally and override only when the caller passes an explicit `end_created_at` (as peer the REST docs). |
||
|
|
99babf436a |
Don't write the secret.txt when the secret is the dummy placeholder value (#45041)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #44826 # 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. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. ## Testing - [x] Added/updated automated tests - [x] Where appropriate, [automated tests simulate multiple hosts and test for host isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing) (updates to one hosts's records do not affect another) - [x] QA'd all new/changed functionality manually For unreleased bug fixes in a release candidate, one of: - [x] Confirmed that the fix is not expected to adversely impact load test results ## fleetd/orbit/Fleet Desktop - [x] Verified compatibility with the latest released version of Fleet (see [Must rule](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/workflows/fleetd-development-and-release-strategy.md)) - [x] Verified that fleetd runs on macOS, Linux and Windows <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Windows MSI builds now correctly exclude placeholder secret values during installation, preventing unnecessary dummy configuration files from being created. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> |
||
|
|
ea3513a1e7 |
always assign profile to missing devices due to replica lag (#45008)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #44980 # 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. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [x] Timeouts are implemented and retries are limited to avoid infinite loops - [x] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes ## Testing - [x] Added/updated automated tests - [ ] QA'd all new/changed functionality manually (Not, outside of tests due to exercising replica lag is difficult) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Bug Fixes** * Improved reliability of device profile assignment by ensuring all devices receive profiles consistently, even when replica lag affects device synchronization from Device Enrollment Program services. * **Tests** * Added test coverage validating device profile assignment behavior under replica lag scenarios. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
034691966f |
check push cert staleness after 5 minutes of in-memory cache time (#44919)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #44376 I opted for an in-memory cache here, as it's not a critical cache piece, we are fine with the cache being different times on different containers (just means some might rotate to the correct cert faster than 5 minutes). It's also a small piece of work, rather than pulling in redis etc. Verified that it now logs, if the cert is stale after a 5 minute in-memory cache. ``` ts=2026-05-07T11:30:08Z level=info msg="push certificate is stale after re-checking" topic=com.apple.mgmt.External.34c4a9b0-6501-4ce6-afc6-32eac6420ee7 staleToken="\x90C\xe4K\xc6a\x97\xb5?\x1b\x9a\x04'\xe7b\x8d" newHash=".fP\xc7O7\xab\xab\x9d\x92\xd5#\xe4u\xe0\xf6" ts=2026-05-07T11:30:08Z level=info component=apple-mdm-push msg="retrieved push cert" topic=com.apple.mgmt.External.34c4a9b0-6501-4ce6-afc6-32eac6420ee7 ``` # 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. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [x] Timeouts are implemented and retries are limited to avoid infinite loops - [x] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * APNs push certificates now refresh in-memory when rotated; staleness is detected using certificate checksums with a short grace window. * **Tests** * Added tests for certificate retrieval, staleness detection/refresh behavior, and push-cert storage error handling. * **Documentation** * Updated docs to describe the APNs push-certificate refresh and staleness behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
f3f830bd9d |
Fix GitOps failure when moving labels from global to fleet scope (#44983)
Closes #44950 ## Local reproduction Reproduced locally using a MySQL integration test against the local test database. The test simulates the exact GitOps scenario from the issue: 1. Create a label and associate it with an MDM profile 2. Delete the label (FK `ON DELETE SET NULL` sets `label_id = NULL`) 3. Create a new label with the **same name** (simulates moving from global to fleet scope) 4. Call `batchSetProfileLabelAssociationsDB` with the profile referencing the new label **Before fix** (code from `main`, unfixed): ``` $ MYSQL_TEST=1 go test -run "TestMDMShared/TestBatchSetProfileLabelAssociations/same_label_name_recreated" -v -count=1 ./server/datastore/mysql/... === RUN TestMDMShared/TestBatchSetProfileLabelAssociations/same_label_name_recreated_after_deletion_darwin Error: selecting existing profile labels: sql: Scan error on column index 1, name "label_id": converting NULL to uint is unsupported === RUN TestMDMShared/TestBatchSetProfileLabelAssociations/same_label_name_recreated_after_deletion_windows Error: selecting existing profile labels: sql: Scan error on column index 1, name "label_id": converting NULL to uint is unsupported --- FAIL: TestMDMShared/TestBatchSetProfileLabelAssociations/same_label_name_recreated_after_deletion_darwin (0.02s) --- FAIL: TestMDMShared/TestBatchSetProfileLabelAssociations/same_label_name_recreated_after_deletion_windows (0.02s) FAIL ``` **After fix:** ``` $ MYSQL_TEST=1 go test -run "TestMDMShared/TestBatchSetProfileLabelAssociations/same_label_name_recreated" -v -count=1 ./server/datastore/mysql/... === RUN TestMDMShared/TestBatchSetProfileLabelAssociations/same_label_name_recreated_after_deletion_windows === RUN TestMDMShared/TestBatchSetProfileLabelAssociations/same_label_name_recreated_after_deletion_darwin --- PASS: TestMDMShared/TestBatchSetProfileLabelAssociations/same_label_name_recreated_after_deletion_windows (0.03s) --- PASS: TestMDMShared/TestBatchSetProfileLabelAssociations/same_label_name_recreated_after_deletion_darwin (0.03s) PASS ok github.com/fleetdm/fleet/v4/server/datastore/mysql 2.761s ``` ## Code changes When a label is deleted, MySQL's `ON DELETE SET NULL` foreign key constraint automatically sets `label_id = NULL` in the profile-label association row. The Go code then crashes trying to scan that NULL into a `uint` field. - **`server/datastore/mysql/mdm.go`** — Added `COALESCE(label_id, 0)` to the SELECT in `batchSetProfileLabelAssociationsDB`, so that NULL `label_id` values are returned as 0 instead of causing a scan error when Go tries to read NULL into a `uint`. - **`server/datastore/mysql/apple_mdm.go`** — Same `COALESCE(label_id, 0)` fix in `batchSetDeclarationLabelAssociationsDB`. Also added `OR label_id IS NULL` to the DELETE statement to clean up broken rows, matching the profile labels behavior from #42637. Other queries in the same codebase (e.g., `listProfileLabelsForProfiles`) already use `COALESCE(label_id, 0)` — these two were missed. ## Testing - `same_label_name_recreated_after_deletion_{darwin,windows}` — reproduces the exact bug: associates a profile with a label, deletes the label (NULL label_id), creates a new label with the same name, and verifies `batchSetProfileLabelAssociationsDB` succeeds, the broken row is cleaned up, and the correct label association exists - Full MDM test suite passes: `MYSQL_TEST=1 go test -run "TestMDM" ./server/datastore/mysql/...` (76s) - `make lint-go-incremental` passes |
||
|
|
e15f37d4e0 |
Optimize OSV vulnerability scanning (#44684)
**Related issue:** Resolves #44391 # 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. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. ## Testing - [x] Added/updated automated tests - [x] Where appropriate, [automated tests simulate multiple hosts and test for host isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing) (updates to one hosts's records do not affect another) - [x] QA'd all new/changed functionality manually I tested this locally number of ubuntu hosts: 6,252 average software per host: 2,302 distinct software items: 61,213 host_software rows: 14.4M generates software_cve rows 305,826 OS sub-versions: 25 The time before my optimization **10m53s** down to **4m26s** the optimization. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Optimized OSV vulnerability scanning to aggregate work by OS version and batch lookups, reducing redundant queries for faster scans. * **Refactor** * Restructured scanning flow to process OS versions in batched chunks with clearer logging and early exits when no work is required. * **Tests** * Added tests for querying, batching, source filtering, deduplication, and empty-input behaviors. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> |
||
|
|
361a5a402e |
Creating product index to speed up vulnerability scanning (#44910)
**Related issue:** Resolves #44391 # 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] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added release notes documenting vulnerability scanning performance improvements * **Refactor** * Optimized vulnerability scanning performance through enhanced CVE product matching efficiency <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
dc0c7bd72f | Recover stuck SCEP managed-cert state via matcher extension (#44691) |