dbb151b598edcd90567fea2a8b6e71eec0d2698a
4657
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
19efda2d1b |
Windows SCEP profiles now fail with non-printable chars (#49887)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #47492 Windows cert profile fails if challenge uses non-printable characters. <img width="987" height="329" alt="image" src="https://github.com/user-attachments/assets/04dc7c78-8e3e-41c8-823e-cb4a961a91eb" /> # 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] 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 ## Summary by CodeRabbit * **Bug Fixes** * Windows SCEP profiles now fail with a clear error when the certificate authority challenge includes characters not supported by Windows ASN.1 PrintableString. * Prevents misleading “Verified” status when no certificate is installed. * Preserves valid challenge values, including leading/trailing spaces. * Improves Windows error tooltips by showing raw certificate-install error details. * **Tests** * Added coverage for invalid/valid Windows SCEP challenge scenarios and the updated error tooltip behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
17669eca02 |
Center-align setup experience app icons (#49962)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #46973 > **Draft:** on-device QA (Mac/iPhone/iPad) is pending hardware, expected next week. Opening as draft for early review of the approach. ## Description FMA and custom-package app icons were misaligned on the macOS setup experience ("Setting up your device") screen — icons rendered at different sizes and their "Install …" labels didn't line up. **Root cause:** `SetupSoftwareProcessCell` forced `.software-icon__small { width: $pad-xlarge }` (32px, width only). That class lands on different elements in `SoftwareIcon`'s two render paths, so it hit them differently: - **Fleet-maintained / VPP apps (icon URL)** → the class is on the wrapper `<div>`; the 24px `<img>` inside stayed 24px, left-aligned. - **Custom packages (no URL)** → the class is on the fallback **SVG** itself, which got stretched to 32px wide. Result: different icon sizes/positions by app type → the misalignment. **Fix:** remove the width override so every app type renders `SoftwareIcon` at its consistent, vertically-centered 24px "small" size. ## Testing Verified in Storybook (added `SetupSoftwareProcessCell.stories.tsx`, `MixedAlignment` story) with real matched brand icons (Chrome, 1Password, VS Code, Zoom), a generic custom-package icon, and a URL/`<img>` icon stacked together: - **Before** (with the override): icons render at mixed 24/32px sizes; "Install …" labels don't align. <img width="1135" height="398" alt="before" src="https://github.com/user-attachments/assets/fe216ab4-0a7b-4211-b8aa-96e65e6ca3f5" /> - **After** (this change): all icons render at 24px, centered, labels aligned. <img width="1185" height="425" alt="after" src="https://github.com/user-attachments/assets/28257eb8-df6e-4168-a0bb-28dda4bb40ba" /> On-device QA to follow once hardware is available. ## Notes for reviewer - The `width: $pad-xlarge` (32px) was added in #33770, so 32px may have been the *intended* icon size. This change makes them a consistent **24px**. If a larger icon is desired, that's a follow-up done properly via a real `SoftwareIcon` size (not a width-only override) — flagging for PD input since this is `:product`-labeled. - Included a Storybook story for visual verification/regression; happy to drop it if that's not wanted here. # Checklist for submitter - [x] Changes file added for user-visible changes in `changes/`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. ## Testing - [ ] QA'd all new/changed functionality manually <!-- pending on-device QA --> - Added a Storybook story for visual verification (not an automated test). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved software process cell styling for more consistent icon sizing and alignment. * **Tests** * Added Storybook scenarios covering fleet-maintained apps, custom packages, uploaded icons, and mixed app layouts. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
af65282522 |
Align helper text with checkbox/radio labels (#49977)
Moves changes from #49920 to `main`. Originally targeting `docs-v4.91.0` — retargeted to this branch. **Related:** #49920 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved checkbox and radio button helper-text alignment so it lines up with the associated label. * Adjusted spacing between controls, labels, and helper text for a cleaner form layout. * **Documentation** * Added component examples demonstrating checkbox and radio buttons with helper text. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
d06a4c222c |
47700 abm token invalid errors (#49770)
**Related issue:** Resolves #47700 # 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. - [ ] Timeouts are implemented and retries are limited to avoid infinite loops ## Testing - [x] Added/updated automated tests - [ ] QA'd all new/changed functionality manually. **_Not able to do for all code paths yet_** <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added `token_invalid` for Apple Business Manager tokens, automatically tracked based on Apple responses. * Enhanced host DEP assignment API responses with a structured `dep_device_error` field to classify why device details couldn’t be retrieved. * **Bug Fixes** * Improved error handling for DEP device lookup, distinguishing invalid/rejected tokens, expired terms, not-found devices, server/API errors, and unavailable/unspecified failures. * Added regression and unit test coverage for ABM token invalidation and DEP device error classification. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
89f67544b4 |
Add support for fleet vars in scripts(controls scripts, software scripts/script-only packages and setup experience scripts) (#49781)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #49511 and #46837 as a whole # 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 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for Fleet built-in variables in host scripts, software installer scripts, setup-experience scripts, and maintained-app installer scripts. * Variables are resolved per host at execution time; saved content remains unexpanded. * **Bug Fixes** * Requests now validate Fleet variables up-front, with clear script-specific error messages for unsupported variables. * Added improved messaging when variable resolution fails during execution. * Enforced Fleet Premium licensing for script/installer flows that use Fleet variables. * **Documentation** * Documented supported variables and Premium requirements, including usage examples. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
5c127e5fe4 |
Fix software ingestion lock convoys and unbatched deletes (#49894)
**Related issue:** Resolves #49805, Resolves #48719 # 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 ## 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 --- ## Context A customer (~2,500 hosts, v4.89.1) had their DB writer slammed with `DELETE FROM host_software_installed_paths` statements carrying 30,000+ IDs each. These never completed, required repeated manual intervention, and the table grew from 14.5M to 14.8M rows in 2 days. This is #49805. While investigating, Victor linked #48719, a related `software_titles` INSERT lock convoy issue seen in load tests. Both are in the same software ingestion code path (`server/datastore/mysql/software.go`), so this PR fixes both. ## Root cause ### #49805: Unbatched DELETEs on `host_software_installed_paths` When a host's software changes, Fleet computes a delta and deletes stale rows from `host_software_installed_paths`. The function `deleteHostSoftwareInstalledPaths()` issued a **single** `DELETE FROM host_software_installed_paths WHERE id IN (?)` with all IDs expanded by `sqlx.In()`. With 30,000+ IDs and 14.8M rows in the table, these massive statements held row locks for minutes, timed out, and never completed. On the next agent check-in, the same (or larger) DELETE was retried, creating a feedback loop where the table grew unboundedly. Notably, the INSERT function for the same table (`insertHostSoftwareInstalledPaths`) already batched at 500 rows. The DELETE simply lacked the same treatment. ### #48719: INSERT IGNORE lock convoys on `software_titles` (related) When a host reports software that Fleet hasn't seen before, `preInsertSoftwareInventory()` runs `INSERT IGNORE INTO software_titles (...)` inside a `withRetryTxx` transaction. For homogeneous fleets (many hosts sharing the same software catalog, typical for imaged corporate Windows machines), hundreds of concurrent goroutines try to INSERT IGNORE the same title rows simultaneously. Even though `INSERT IGNORE` is a no-op when the row already exists, InnoDB still acquires row/gap locks on the unique index for the duration of the enclosing transaction. With many goroutines holding or waiting on the same index locks, the DB enters a "lock convoy" where sessions serialize on locks they don't actually need. In load tests (40 Fleet instances, 100K hosts, 141 identical Windows software items), this produced 690 average active sessions on the writer and 85s fleet-wide p99. The existing read-first check (`getIncomingSoftwareChecksumsToExistingTitles`) prevents the convoy at steady state. But on cold start (empty `software_titles`, e.g. after cleanup purges orphaned titles), the check finds nothing and all goroutines race to INSERT the same titles. ## How I reproduced it Started MySQL via `docker compose up -d mysql_test`, created a git worktree. ### #49805 `TestHostSoftwareInstalledPathsDeleteExplosion`: Created a host with 500 software items and installed paths, then replaced all software with an entirely new set. This triggers `deleteHostSoftwareInstalledPaths()` with all 500 old IDs in a single unbatched DELETE statement. At 500 IDs the local test completes quickly, but the structure confirms the problem: at 30K+ IDs on production Aurora with 14M rows, these never finish. ### #48719 `TestSoftwareTitlesInsertIgnoreLockConvoy`: Created 50 hosts, each reporting 100 identical software items (simulating a homogeneous fleet). Used a barrier to release all 50 goroutines simultaneously, then measured two phases: 1. **Cold start** (empty `software_titles`): All 50 hosts concurrently call `ds.UpdateHostSoftware()`. 2. **Steady state** (titles exist): Same 50 hosts re-ingest. **Before fix:** | Metric | Cold start | Steady state | |--------|-----------|-------------| | Wall time | 3.0s | 38ms | | Avg per-host | 1,981ms | 29ms | | **Convoy factor** | **79x** | | The 79x slowdown confirms the lock convoy. ## How I fixed it ### #49805: Batch the DELETE at 500 Changed `deleteHostSoftwareInstalledPaths()` from a single `DELETE ... WHERE id IN (all IDs)` to a loop that processes 500 IDs per batch, matching the existing INSERT batching pattern in the same file. ### #48719: Three-layer defense against lock convoys **Layer 1 - Move title INSERT IGNORE outside the transaction.** Previously, `INSERT IGNORE INTO software_titles` ran inside `withRetryTxx`, so locks were held for the full transaction duration. Now each title INSERT is executed via `ds.writer(ctx).ExecContext()` outside any transaction, auto-committing independently and holding locks for microseconds. **Layer 2 - singleflight per title key.** Added a `singleflight.Group` on the `Datastore` struct. For each title, only one goroutine actually executes the INSERT; concurrent goroutines wait and share the result. **Layer 3 - In-process cache (`sync.Map`).** After a title is inserted, its key is stored in `knownSoftwareTitleKeys`. Subsequent ingestions check the cache first and skip the INSERT entirely. `CleanupSoftwareTitles` clears the cache when it deletes orphaned titles. The three layers work together: the cache handles the common case (title already known), singleflight handles the cold-start race (only one INSERT per title), and auto-commit ensures even the winning INSERT holds locks for microseconds. ## How I tested that it works ### New reproduction tests - `TestSoftwareTitlesInsertIgnoreLockConvoy`: 50 concurrent hosts, 100 identical software items. Measures cold-start convoy factor and verifies all 100 titles are created. - `TestHostSoftwareInstalledPathsDeleteExplosion`: Full software replacement path with 500 items per host, including concurrent hosts. ### Existing test suite Ran all existing software tests including: - `UpdateHostSoftware`, `UpdateHostSoftwareDeadlock`, `PreInsertSoftwareInventory` - `SoftwareTitleUpgradeCodeDriftMatch`, `UpdateHostSoftwareSameBundleIDDifferentNames` - `CleanupSoftwareTitles` (validates cache invalidation works correctly) - `SaveHost`, `SyncHostsSoftware`, and ~80 other subtests All pass. ### After-fix measurements | Metric | Before fix | After fix | |--------|-----------|-----------| | Cold-start wall (50 hosts) | ~3.0s | ~1.4s | | Cold-start avg per-host | ~1,981ms | ~594ms | | Steady-state wall | ~38ms | ~7ms | | Titles created correctly | 100/100 | 100/100 | The remaining cold-start time is from other pipeline operations (`INSERT IGNORE INTO software`, host_software linking), not from `software_titles`. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Performance Improvements** - Improved software inventory ingestion under large, concurrent workloads, including more efficient handling of repeated software-title inserts. - Reduced lock contention when many devices report the same titles at the same time. - Batched deletions of installed software-path records to speed up large updates. - **Bug Fixes** - Ensured deterministic, collation-safe software-title deduplication to prevent incorrect or stale title mapping. - Strengthened orphan cleanup behavior so caches are cleared when orphan titles are removed. - **Tests** - Added stress/regression tests for software-title insert contention and large installed-path delete workloads. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> |
||
|
|
09fea47ce4 |
Fleet UI: Handle long fleet names across the Fleets UI (#49216)
## Issue Closes #47290 Also implements the "Cap free-text `maxLength` to the backend column length" pattern established in [#49041 (patterns.md thread)](https://github.com/fleetdm/fleet/pull/49041/files#r3572648691). ## Description Fleet name inputs had no `maxLength` cap and no service-layer length check, so a name >255 chars failed with a raw MySQL `Data too long` error, and several UI surfaces didn't handle long names gracefully. This PR fixes all four manifestations called out in the bug, plus a related label-overflow case on the host details page, and hardens adjacent name inputs across the app. **Frontend fixes for #47290:** - Create/Rename fleet name inputs now cap at 255 characters (matches `teams.name varchar(255)`). - Fleets table Name column uses `LinkCell` with `tooltipTruncate` + `className="w400"` so long names truncate with an ellipsis and full-name tooltip instead of overflowing across the Hosts/Users columns. - Fleet-detail page header (`.team-details__team-header`): h1 gets `overflow: hidden; text-overflow: ellipsis; white-space: nowrap;`, `__team-details` gets `min-width: 0; flex: 1`, and `.action-buttons` gets `flex-shrink: 0` + `white-space: nowrap` on buttons so *Manage enroll secrets / Rename / Delete* no longer wrap to a second line when the fleet name is long. - Manage enroll secrets modal body — `__description` gets `overflow-wrap: anywhere; min-width: 0` so a long `<b>{fleet name}</b>` wraps within the modal instead of spilling out the right edge. **Backend fixes for #47290:** - New `fleet.MaxTeamNameLength = 255` constant. - `NewTeam`, `ModifyTeam`, and `ApplyTeamSpecs` now return `fleet.NewInvalidArgumentError("name", "may not exceed 255 characters")` instead of surfacing a raw `Data too long` MySQL error. Covers UI, API, and GitOps entry points. **Broader consistency pass (per [#49041 thread](https://github.com/fleetdm/fleet/pull/49041/files#r3572648691)):** - New shared `MAX_ENTITY_CHAR_LENGTH = 255` constant in `frontend/utilities/constants.tsx`. - Refactored 8 existing files that had ad-hoc `NAME_MAX_LENGTH = 255` / `MAX_LABEL_NAME_LENGTH = 255` locals to use it. - Slotted it into 16 additional `InputField` name/description inputs that were missing a cap (API user, custom variable, certificate, label name + description, pack name + description, and all 5 CA forms — CustomEST, CustomSCEP, Smallstep, Digicert, Hydrant). - Pruned dead FE length validators that can no longer fire now that the DOM cap enforces the limit (certificate modal, custom variable modal, both label helpers, both category modals). Unusual/shorter caps (e.g. `varchar(64)`, custom business rules) still keep their inline validators — silent truncation is only appropriate for the common 255-char norm. **Bonus:** fixed the long-label overflow on the host details Labels card by capping the pill button `max-width` at 300px. ## Screenrecording https://github.com/user-attachments/assets/b917b72e-7437-4d0c-a1a1-c49b4b1c28ba https://github.com/user-attachments/assets/3a3efbb2-09d8-4f47-9fd4-f158b3453b9e https://github.com/user-attachments/assets/73e5e022-dc93-4381-82b3-be9549d050e6 Latest - max width 300px long label: <img width="1106" height="262" alt="Screenshot 2026-07-23 at 11 29 24 AM" src="https://github.com/user-attachments/assets/741fddbd-f78d-4578-a025-bddf64a81c25" /> ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually Test coverage: - `CreateFleetModal.tests.tsx`, `RenameFleetModal.tests.tsx` — new case per file asserting the name input's `maxLength === 255`. - `AddCertificateModal.tests.tsx`, `Variables.tests.tsx` — the existing "shows too-long error when pasting 256 chars" tests are now unreachable via the DOM cap; converted to `maxLength === 255` assertions. - `ee/server/service/teams_test.go` — `TestNewTeamNameValidation`, `TestModifyTeamNameValidation`, and `TestApplyTeamSpecsNameValidation` each get two new cases (accepts at the limit, rejects one over with the expected error message). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Limited fleet, team, and other user-entered names and descriptions to 255 characters. * Replaced database errors for oversized names with clear validation messages. * Prevented long fleet and label names from overflowing tables, headers, modals, and host details. * Improved modal and dropdown layouts for long text. * **Tests** * Added coverage for character limits, boundary values, and multibyte names. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
aeb56916ee |
Block host enrollment with empty enroll secrets
VerifyEnrollSecret matched by exact string, so an empty enroll_secret matched any stored empty secret and issued a valid node key. Guard the shared chokepoint: reject empty/whitespace secrets before matching, closing all enrollment paths (osquery, Orbit, Apple MDM, Android). Add a migration to delete pre-existing empty secrets. |
||
|
|
3e3097cf49 | Fleet UI: Drop I-beam cursor on non-underlined tooltips (#49859) | ||
|
|
6bb0b1ea52 |
Stop leaking cross-team software title names via the hosts endpoint (#49638)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves: N/A # 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 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Corrected `software_title_id` filtering for hosts so software title details are strictly scoped to the current team and never backfill mismatched or out-of-scope data. * Removed unintended debug output and ensured software title details remain unset when the title isn’t accessible. * **Tests** * Added an enterprise integration test verifying cross-team `software_title_id` behavior. * Updated existing integration expectations for team-scoped visibility. * Added datastore coverage for team-scoped software title name lookup behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> |
||
|
|
aa572dcca4 |
Show ABM organization name in edit-fleets success toast (#49877)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #48914 ## Description The success toast shown after editing fleet assignments for an Apple Business Manager (ABM) organization read: > Successfully updated fleets for AB token. The trailing "AB token" made the message unclear. It now names the organization instead, matching the modal's title: > Successfully updated fleets for `<org name>`. The organization name (`token.org_name`) was already available in the component (it's used as the modal title), so this is a copy-only change with no new data plumbing. Note: the issue's expected behavior left the exact wording to Product ("TODO — Product to decide"). This implements Product's written suggestion (`Successfully updated fleets for {org name}`) so the awkward wording isn't blocking; the string is trivial to adjust if Product/design prefer different phrasing in review. ## Testing - Manually QA'd in the UI: with a configured ABM organization, edited a fleet assignment and confirmed the toast now shows the org name. - Existing unit tests for the modal's helpers (`getOptions`, `getSelectedTeamIds`) still pass; no test asserts the toast string. - `eslint` and `prettier` pass on the changed file (added `token.org_name` to the `useCallback` dependency array to satisfy `react-hooks/exhaustive-deps`). # Checklist for submitter - [x] Changes file added for user-visible changes in `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] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Updated the success notification shown after fleet teams are saved to include the associated organization name. * Ensured the notification always reflects the currently selected organization. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
b22a046a96 |
Fix undeletable Apple DDM declarations when allowed types change (#49810)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #47535 ## Description `DeleteMDMAppleDeclaration` re-ran the upload-time validator (`ValidateUserProvided`) on the delete path. That validator enforces *upload-admission* rules — forbidden declaration types (`ForbiddenDeclTypes`) and the `AllowAllDeclarations` config flag — so any declaration that was accepted at upload time became **undeletable** through the API once the accepted set later shrank. Two ways this happens in practice: - A server config flag that had been enabled at upload time is later disabled (the original customer report, prod 4.86.1). - A declaration type is added to `ForbiddenDeclTypes` in a later release, after declarations of that type were already uploaded. In both cases the UI showed "Couldn't delete. Please try again." and the API returned `400` with an upload-validation message on a *delete* request. Whether a declaration is Fleet-managed (and therefore protected from deletion through this endpoint) is already determined by the Fleet reserved-name check that runs immediately above the offending block. This PR removes the upload-time validation from the delete path and relies solely on that reserved-name check, so: - A user can delete any declaration they previously uploaded, regardless of whether the current validator config would still accept it on upload. - Fleet-managed declarations (reserved names) remain protected from deletion. The `AllowAllDeclarations` flag and `ValidateUserProvided` are unchanged on the **add/upload** path — admission control still happens where it belongs. ## Testing Extended `TestMDMConfigProfileCRUD` (replacing the pre-existing `// TODO: Add tests for create/delete forbidden declaration types?`) with two cases: - A declaration whose type is in `ForbiddenDeclTypes` can be deleted (regression guard — fails before this change, passes after). - A declaration with a Fleet-reserved name remains protected from deletion (guards the reserved-name check that is now the sole Fleet-managed gate — a boundary that was previously untested). Manually verified end-to-end in the UI: reproduced the stuck declaration (upload a forbidden type with `FLEET_MDM_ALLOW_ALL_DECLARATIONS=true`, restart without the flag), confirmed the pre-fix `400`, then confirmed deletion succeeds after the fix with the flag off. # Checklist for submitter - [x] Changes file added for user-visible changes in `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 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved Apple MDM declaration deletion to avoid re-running upload-time validation during the delete flow. * Declaration deletion checks now rely on Fleet management status and reserved naming, preserving protection for Fleet-managed declarations. * Added/adjusted deletion behavior for restricted and Fleet-reserved declaration types. * **Tests** * Added regression coverage for Apple declaration profile deletion via the configuration profile delete endpoint, including strict-mode scenarios and cleanup behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
9cfd907be6 | Fleet UI: Hide empty host summary card on Free-tier Android hosts (#49848) | ||
|
|
e42dc7accf |
Improved the performance of the configuration profiles status summary (#48873)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #48340 Windows only. The fix is to use a rollup status table instead of recalculating the host profile summary on demand. Verified the fix in load test with 100k Windows MDM hosts. Note that this does not improve the host details page filtered by OS settings, which will be handled by the follow up https://github.com/fleetdm/fleet/issues/48996 # 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] Timeouts are implemented and retries are limited to avoid infinite loops ## 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`). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved Windows fleet configuration profile status summaries to avoid timeouts on large fleets. * Kept per-host Windows profile statuses accurate after profile updates, resends, certificate changes, cleanup, unenrollment, and host deletion. * Added automatic reconciliation to correct stale or orphaned status data. * **Data Integrity** * Improved Windows profile status reporting, including profile and BitLocker summaries, for more reliable results. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
83f3f4b560 |
Add clear error for Firefox / Firefox ESR conflict (#49714)
**Related issue:** Resolves #49682 Mozilla Firefox and Firefox ESR are distinct Fleet-maintained apps that share the macOS bundle identifier `org.mozilla.firefox`, so they resolve to one software title. Adding both to a fleet previously gave a generic conflict error (or no error at all). This adds a clear message — "Only one of Mozilla Firefox or Mozilla Firefox ESR can be added to the same fleet." — on both the single-add and GitOps/batch paths. The check is general (any two FMAs sharing a bundle identifier), with the app names filled in dynamically. # Checklist for submitter - [x] Changes file added for user-visible changes in `changes/`. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements). ## 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** - Prevented adding both Mozilla Firefox and Firefox ESR to the same fleet when they share a bundle identifier. - Updated the UI to show a specific conflict message explaining that only one of the two can be added. - Ensured existing workflows still work for adding new versions of the already-selected app. - **Tests** - Added backend and frontend test coverage for the new conflict detection and error-message formatting. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
f492a6a41d |
Enforce API-only endpoint restrictions on chart routes (#49477)
# 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 ## Summary Enforced API-only endpoint restrictions on chart endpoints, matching the pattern already used by the activity bounded context. Also added `RouteTemplateRequestFunc` to chart route server options so the middleware can read the matched mux route template from context. ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually ### Reproduction Created an API-only user with a restrictive endpoint allow-list (only `GET /api/v1/fleet/hosts`). Confirmed that: - Allowed endpoint (`/api/latest/fleet/hosts`) returns 200 - Non-allowed cataloged endpoint (`/api/latest/fleet/users`) returns 403 - Chart endpoint (`/api/latest/fleet/charts/uptime`) returned 200 before the fix (the bug) - After the fix, chart endpoint correctly returns 403 ### Unit test Added a test case in `server/service/middleware/auth/api_only_test.go` that verifies an API-only user with endpoint restrictions is denied access to chart endpoints not in their allow-list. The chart endpoint is included in the test catalog (matching production), so the test exercises the allow-list rejection path. All 17 tests in the auth middleware package pass. ### Local verification 1. Confirmed the chart middleware in `cmd/fleet/serve.go` previously called `auth.AuthenticatedUser(svc, next)` without `APIOnlyEndpointCheck` wrapping 2. Verified the activity bounded context (same file) already uses `auth.APIOnlyEndpointCheck(next)` as the correct pattern 3. Applied the same wrapping to the chart middleware 4. Added `RouteTemplateRequestFunc` to `server/chart/internal/service/endpoint_utils.go` so the route template is available in context (required by `APIOnlyEndpointCheck`) 5. Ran `go test ./server/service/middleware/auth/ -v` with all 17 tests passing 6. Ran `make lint-go-incremental` with 0 issues |
||
|
|
968ea20aeb | Fleet UI: Searchable fleets dropdown with add-fleet affordance (#49690) | ||
|
|
9d6f25acd7 |
Make MFA token redemption atomic to prevent multiple sessions
Resolves #16770 The MFA login token redemption path (`POST /api/latest/fleet/sessions`) read the one-time verification token with a non-locking `SELECT` on the read replica, then created a session and deleted the token in a *separate* transaction without verifying the token was still present. Concurrent requests carrying the same token each passed the `SELECT` and each minted a distinct session, breaking the single-use guarantee. `SessionByMFAToken` now consumes the token and creates the session inside a single transaction: - The token row is locked with `SELECT ... FOR UPDATE`, then deleted, and the delete's rows-affected count is confirmed non-zero before the session is created. - Concurrent redemptions serialize on the row lock; the loser re-reads after the winner commits the delete, finds no row, and aborts before creating a session. - The user is still loaded *before* the transaction, so a concurrently-deleted user or a transient read error leaves the token intact for retry (preserving the pre-fix atomicity behavior). --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Juan Fernandez <juan@fleetdm.com> |
||
|
|
62ed3583e6 |
Clear button styles (#49292)
**Related issue:** Resolves #49276 **New features** - Added new "Secondary" (bordered, off-white fill) and "Subdued" (borderless, low-emphasis) button variants to match the Figma spec, alongside the existing Primary style. - Allowed rows to be selected in Controls > OS updates. **Cleanup** - Once nothing referenced the old styles anymore, fully removed the old `text-icon`, `brand-inverse-icon`, `inverse-alert`, `inverse`, and `icon` button variants (type, styles, and Storybook entries) from the shared `Button` component. - Removed the `iconStroke` prop, which had become a no-op once the old variants it supported were gone. - Renamed `ActionsDropdown`'s variants (`button`/`brand-button`/`small-button`) to `subdued`/`primary`/`secondary` to match the same naming used everywhere else. - Replaced a one-off dropdown implementation on the Software title page with the shared `ActionsDropdown` component, instead of maintaining duplicate styling logic. - Changed the button name on Host details > Reports > Report details from "View data for all hosts" to "View report for all hosts" (to match the previous page's Actions drop-down options). # Checklist for submitter - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually <img width="1475" height="241" alt="Screenshot 2026-07-21 at 06 35 49" src="https://github.com/user-attachments/assets/7cfbd444-7837-40e8-854e-bc5989d57d85" /> <img width="661" height="306" alt="Screenshot 2026-07-21 at 06 37 18" src="https://github.com/user-attachments/assets/5d0c4873-8179-4089-b115-7e8cd3a53b4d" /> <img width="1427" height="423" alt="Screenshot 2026-07-21 at 06 37 30" src="https://github.com/user-attachments/assets/a4850a60-f44a-4902-b45e-0094f23a52f8" /> <img width="1427" height="640" alt="Screenshot 2026-07-21 at 06 37 46" src="https://github.com/user-attachments/assets/738a4a7f-cd7d-4162-b659-6f649c32204d" /> <img width="1445" height="479" alt="Screenshot 2026-07-22 at 07 03 22" src="https://github.com/user-attachments/assets/4f672dc0-5c6d-4eb8-8465-ed5233fcd1b2" /> <img width="811" height="871" alt="Screenshot 2026-07-21 at 06 41 20" src="https://github.com/user-attachments/assets/5421c96e-2dab-492a-af26-be0e5a7791ca" /> |
||
|
|
fbccb8cc59 |
Emit created/deleted activities for setup experience scripts
Setup experience script add/replace/delete now record activities (API and GitOps), skipping no-op re-submissions. |
||
|
|
e91a0b2987 |
Normalize login responses for MFA-enabled accounts
Make failed logins for MFA-enabled accounts return a consistent response and timing regardless of the cause, in line with authentication best practices. Guidance for CLI users whose client can't complete email verification is now surfaced by fleetctl on any login failure. Added a `user_mfa_requested` activity, recorded when valid credentials are submitted for an MFA-enabled account and a verification email is sent. |
||
|
|
d903ec58e1 |
Fix label update consistency issue
Persist label metadata and membership changes together in a single transaction so a failed update can't leave a partial change behind. |
||
|
|
a7eb747faf |
Flag to bypass end user auth (#49683)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #46644 Demo video: https://www.youtube.com/watch?v=svCaA-820yc Docs: https://github.com/fleetdm/fleet/pull/49713/changes # 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 ## 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] If the change applies to only one platform, confirmed that `runtime.GOOS` is used as needed to isolate changes - [x] Verified that fleetd runs on macOS, Linux and Windows - Did not verify macOS. - [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** * Added `--bypass-end-user-auth` to `fleetctl package` and Orbit. * Generated Linux and Windows installers can skip the end-user authentication prompt during enrollment. * Added `ORBIT_BYPASS_END_USER_AUTH` for environment-based configuration. * End-user authentication remains enabled when a supported EUA token is provided. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
95b535a622 |
Reverting printableCharacters SCEP validation (#49758)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #49756 # 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 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit * **Bug Fixes** * Custom SCEP proxy challenges can again include characters such as underscores. * Apple device enrollment works again with these challenges. * Removed the overly strict printable-character validation from the Custom SCEP configuration form. * The Challenge field now only enforces the required-value rule and no longer shows printable-character validation errors. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
b9136f4da5 |
Release from AB backend support (#49680)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #49367 # 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 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added “Release from Apple Business” for eligible Apple hosts, including per-device success/failure reporting and activity logging. * Added a new API endpoint to trigger the action and return results for each selected host with clear error details. * Introduced authorization rules for global admins and team admins to release only within allowed scope. * **Bug Fixes** * Improved validation and error handling: rejects oversized selections, reports unknown/ineligible hosts and DEP-related failures per device, and treats assignment-cleanup failures as non-blocking. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
ccaea1373b |
trim MDM SSO whitespace in GitOps and API (#49378)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #48003 # 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** - Fixed MDM SSO configuration handling to automatically remove leading and trailing whitespace from provider fields. - GitOps-applied MDM SSO settings are now normalized before validation, preventing otherwise invalid configurations caused by extra spaces. - Required-field and URL validation now operate on the cleaned values. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
10ac3c73a3 |
Harden password reset token handling
Ensure a password reset token can only be used once. |
||
|
|
e017eb6176 |
Allow bypassing network blocking in production via config (#49747)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #49751 A customer's egress proxy (an Envoy sidecar bound to loopback) was getting blocked by Fleet's SSRF network-blocking check, since the check applies to whatever address the HTTP transport dials, including the proxy hop itself, not just the ultimate destination. There was no supported way to disable this in production (the existing full-bypass mode was dev-only), leaving no path forward for environments where egress is already constrained by external infrastructure. # 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 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a production server setting to bypass outbound network blocking for integration requests when external egress controls are already in place. * The setting is disabled by default and can be configured through the server configuration. * **Documentation** * Clarified that bypassing network blocking disables SSRF protections for all outbound integration requests. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
932e82e856 |
Gitops mode disables android MDM connect and turn off buttons (#49685)
**Related issue:** Resolves #48226 |
||
|
|
8677e1cf53 |
Fix Add API-only user > Specific API endpoints table search (#49613)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #49707 # 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 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Improved API endpoint search with relevance-based ranking across endpoint names and paths. * Search results now prioritize exact, prefix, whole-word, and partial matches. * Added path-based matching and clearer empty-state behavior. * Removed pagination in favor of the existing results scrollbar. * **Bug Fixes** * Preserved relevance ordering instead of applying an incorrect default sort. * Excluded already-selected endpoints from search results. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
6d0ecf1b9f |
Clarify which OS supports OS Updates (#49716)
**Related issue:** Resolves #48960 |
||
|
|
f04430a5a6 |
Added redirect_uri validation for Windows TOS endpoint. (#49699)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves https://github.com/fleetdm/confidential/issues/16880 # 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 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit * **Bug Fixes** * Secured the Windows MDM Terms of Service endpoint against reflected cross-site scripting. * Strengthened validation for the `redirect_uri` used in Terms of Service rendering, allowing only approved `https` and `ms-appx-web` schemes. * Unsafe, malformed, or non-allowlisted redirect values are now rejected and not displayed. * **Tests** * Added integration and unit coverage to verify unsafe redirects are blocked while valid ones continue to work. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Sharon Katz <121527325+sharon-fdm@users.noreply.github.com> |
||
|
|
3b32a526ee |
Fix 500 on Apple MDM enroll when host has no DEP assignment (#47963) (#49623)
**Related issue:** Resolves #47963 # 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 - [ ] QA'd all new/changed functionality manually ## Summary Fixes a 500 seen via monitoring during `POST /api/mdm/apple/enroll`: ``` checking os updates settings serial [redacted]: getting team id for host: sql: no rows in result set ``` ### Root cause During DEP enrollment, `CheckMDMAppleEnrollmentWithMinimumOSVersion` → `shouldOSUpdateForDEPEnrollment` calls `GetMDMAppleOSUpdatesSettingsByHostSerial`, which joins `hosts` to `host_dep_assignments` by serial. When no matching row exists yet — e.g. the enrollment request arrives before the host / DEP assignment row is created or replicated (replica lag / ordering) — `sqlx.GetContext` returns `sql.ErrNoRows`. The service layer already handles this case gracefully (skip the OS-update check, allow enrollment to proceed) via `fleet.IsNotFound(err)`. But the datastore wrapped the raw `sql.ErrNoRows` with a plain `ctxerr.Wrap`, which does not implement the `IsNotFound()` interface, so the graceful path never triggered and the request 500'd. ### Fix Convert `sql.ErrNoRows` into a proper `notFound` error in the datastore method, matching the existing pattern used throughout `apple_mdm.go`. This lets the existing service-layer graceful-skip path take over so enrollment proceeds. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed Apple MDM enrollment to continue gracefully when OS update settings are missing because a host’s DEP assignment hasn’t been created yet or hasn’t replicated. * Prevented enrollment from failing with an unexpected 500 error by returning a clear “not found” outcome instead. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
ba0b1c3bea |
Fix resend button not showing on keyboard navigation in OS settings modal (#49728)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves none After: https://github.com/user-attachments/assets/cc9b73be-a015-49dd-adc3-5b516c02ea4c Before: https://github.com/user-attachments/assets/e870bc22-5984-4076-bb21-35699eda45bf # 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** * Improved keyboard accessibility in OS settings tables. * Resend and rotate actions now appear when their table row receives keyboard focus, in addition to mouse hover. * **Documentation** * Added a change note describing the accessibility improvement. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
edf4a45df9 |
Stop the delete host endpoint from revealing out-of-fleet host existence (#49645)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves: N/A # 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 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Updated host deletion behavior to return consistent “not found” responses when the host doesn’t exist or isn’t visible to the requester. * Prevented out-of-scope delete attempts from disclosing whether the target host exists (now returns “not found” instead of “forbidden”). * Preserved “forbidden” errors when the host is visible but the requester lacks delete permission. * **Tests** * Added/updated authorization and deletion coverage to verify the new response-masking behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
87c1a719c1 |
Support custom host vitals in host name templates (#49586)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #49489 Custom host vitals were skipped when host name template enforcement (#38806) shipped, since both features were in development at the same time. This adds `$FLEET_HOST_VITAL_<id>` support to host name templates, matching the existing secret-variable pattern (validation, per-host resolution, resend on value change). I also introduced a new `IsInvalidReferencedCustomHostVitalsError` call after Copilot's comment below. # 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 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit * **New Features** * Added support for `$FLEET_HOST_VITAL_<id>` in Apple host name templates. * Device-name template reconciliation now expands referenced per-host vital values and updates automatically when those values change. * **Bug Fixes** * Prevents deleting custom host vitals that are referenced by host name templates. * If a referenced vital has no value for a host, device-name delivery is marked failed for that host (retryable). * **Improved Error Handling** * Refined validation behavior so unknown/malformed vital references return user-facing invalid-argument errors, while infrastructure errors propagate unchanged. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
e7a0d702dd |
Generate CPE for Firefox Developer Edition on macOS
Resolves #48689 Adds a CPE translation so Firefox Developer Edition on macOS resolves to the standard `mozilla:firefox` product. Without it, `CPEFromSoftware` generates no CPE for the app, so it matches no Firefox CVEs and shows as vulnerability-free — a silent false negative. The root cause is that none of the standard matching paths fit Developer Edition: its bundle identifier `org.mozilla.firefoxdeveloperedition` splits to a product token (`firefoxdeveloperedition`) that has no NVD entry, and the sanitized-name and full-text fallbacks don't resolve to `firefox` either. Regular Firefox works only because its bundle (`org.mozilla.firefox`) splits cleanly to `mozilla`/`firefox`. The fix uses the same translation mechanism the existing Firefox ESR rule uses, mapping the Developer Edition bundle to `product: firefox`, `vendor: mozilla` — with no `sw_edition`, since Developer Edition tracks standard Firefox advisories (ESR is the special case that needs the `esr` edition). Match is on the bundle identifier rather than the display name so it's stable regardless of how the app name is ingested. **Out of scope:** Firefox Nightly (`org.mozilla.nightly`) has the same failure mode but uses pre-release version strings (e.g. `155.0a1`) that don't line up with NVD's per-version Firefox CPEs, so mapping it to `firefox` risks bad matches — it warrants separate handling. Firefox Beta already works today (its bundle is `org.mozilla.firefox`), so it needs no change. **Testing.** Two layers, matching how the codebase already tests CPE rules: - An offline unit test (`TestFirefoxDeveloperEditionTranslation`) loads the real shipped `cpe_translations.json` and asserts Developer Edition translates to `mozilla:firefox` with no `sw_edition`. It needs no CPE dictionary or network, so it runs in the fast suite. - A case in the network-gated `TestCPEFromSoftwareIntegration`, alongside the existing regular-Firefox case, asserts the full CPE string against the live NVD dictionary in CI. It reuses the known-good `105.0.1` Firefox entry. The downstream CPE→CVE step is unchanged and already covered for `mozilla:firefox` by `TestTranslateCPEToCVE`, so no new CVE-matching test is needed. # 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 — ran `TestFirefoxDeveloperEditionTranslation` locally against the shipped rule (passes); the full software→CPE resolution against live NVD data is exercised by the network-gated integration case in CI. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved recognition of Firefox Developer Edition on macOS so it maps to the expected Firefox vulnerability data. * Better handling of version matching for this app, helping scan results stay accurate. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
f89cde43b6 |
Harden user creation from invite
Fixed an issue where an SSO-only invitation could be accepted with a password, creating a local password-authenticated account and bypassing SSO enforcement. The authentication mode is now derived solely from the invite. Derive the authentication mode from the invite record instead of client input during invite acceptance. |
||
|
|
d9426402b2 |
Normalize LocURI values before validation in Windows profiles (#49708)
**Related issue:** Resolves fleetdm/confidential#16883 # 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 ## Summary Normalized LocURI target values before validation checks in Windows MDM profile handling. ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually - [x] Confirmed that the fix is not expected to adversely impact load test results ### Reproduction Wrote test cases that construct Windows SCEP profile XML with trailing whitespace appended to LocURI paths (e.g., `/Install/SubjectName ` with a trailing space). Before the fix, these profiles passed validation without the required renewal-id marker because `strings.HasSuffix` did not match the whitespace-suffixed path. The same bypass applied to Challenge and ServerURL LocURIs. ### Unit tests added 7 new test cases across two test functions: **`TestAdditionalNDESValidationForWindowsProfiles`** (3 new cases): - SubjectName LocURI with trailing whitespace is still validated for renewal id - Challenge LocURI with trailing whitespace still validates correctly - ServerURL LocURI with trailing whitespace still validates correctly **`TestAdditionalCustomSCEPValidationForWindowsProfiles`** (new function, 4 cases): - Valid custom SCEP profile passes - SubjectName missing renewal id is rejected - SubjectName with trailing whitespace in LocURI is still validated for renewal id - SubjectName with internal whitespace (not trailing) is rejected ### Local verification 1. Wrote failing tests first, confirmed the whitespace bypass existed (tests failed as expected before the fix) 2. Applied the fix (`strings.TrimSpace` on target before `HasSuffix` checks) 3. Confirmed all new tests pass after the fix 4. Ran full test suite: `go test ./server/service/ -run "TestAdditionalNDESValidation|TestAdditionalCustomSCEPValidation" -v` with all 14 tests passing 5. Ran `make lint-go-incremental` with 0 issues |
||
|
|
4d924e2f48 |
Show managed Android serial number on Hosts page (#49711)
**Related issue:** Resolves #48379 |
||
|
|
94d5a7d27c |
create new appCfg entry on AB fleet updates if not found (#49559)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #48653 # 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** - Improved Apple Business Manager configuration handling when updating team assignments, including creating the assignment entry when it doesn’t already exist. - Removing an Apple Business Manager token now also removes its corresponding assignment details and properly updates configuration status when no tokens remain. - Prevented `generate-gitops` from exporting an empty `apple_business` section when default fleets are configured only via the UI. - **Tests** - Expanded coverage for team assignment updates to validate creation of new configuration entries. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
966838b159 |
Don't queue profiles for non host_mdm.enrolled Apple hosts (#49611)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #48845 # 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** * Apple MDM reconciliation no longer queues profiles for deleted or non–MDM-enrolled hosts. * Apple MDM reconciliation batching/snapshots now include only hosts with confirmed active MDM enrollment, reducing incorrect or stale reconciliation candidates. * **Tests** * Added MySQL datastore coverage to validate reconcile snapshot selection and reconcile host lookup behavior. * Improved Apple MDM and related test setups to explicitly ensure required MDM server configuration exists before reconciliation assertions. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
ff7955c0f0 |
Fix race condition in one-time software installer download token
Token redemption consumed the key via a non-atomic read-then-delete, which allowed concurrent requests to redeem the same one-time token more than once. Made consumption atomic so a token can only be used once, even under concurrent access, and added coverage for the concurrent path. |
||
|
|
a156079d55 |
Fix SCIM deprovisioning edge case during user deactivation
Resolve the matching Fleet user from the persisted SCIM record rather than the incoming request state when handling deactivation, so deprovisioning still works when identifiers change in the same request. |
||
|
|
9f251c21fe |
Fix SCIM middleware persisting authorization failures to last_request
The LastRequestMiddleware already skipped 401 responses but not 403s, so unauthorized users could overwrite the admin-visible SCIM status. Skip both. |
||
|
|
e14ef67b55 |
Fix Windows Autopilot ESP hang: gate release on user-scope ack (#49134) (#49542)
The ESP release wrote the user-scope ServerHasFinishedProvisioning Replace and immediately committed awaiting_configuration=None. During OOBE the device rejects user-scope writes with SyncML 405 until its user MDM context initializes, so the Account setup phase never received its completion signal and the device hung until the 3-hour timeout, while Fleet believed the ESP had completed (and relaxed the DMClient poll, crippling remediation). The release path now stays Active until the device acks the user-scope Replace with a 200: a new resend phase re-sends the Replace once per session (bounded by the existing 3-hour timeout), and the Active->None transition commits only on the 200. Live-validated on Win11 26200 on both a fresh and a re-enrolled device: the 405 reproduced at release time in both flows, and the retried Replace acked 200 one session after the user context came up, releasing the ESP. <!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #49134 # 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] Timeouts are implemented and retries are limited to avoid infinite loops ## 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 Windows Autopilot enrollment could intermittently hang at **“Account setup”** on the Enrollment Status Page. - Updated Enrollment Status Page release handling so enrollment **stays active until the device acknowledges** the user-scope completion command. - When the user-scope completion is rejected or still unacknowledged, it is **retried in subsequent management sessions** until successfully acknowledged. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
15a0f4b201 |
48342 edit config profile endpoint (#49141)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #48342 # 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] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for editing existing Apple, Windows, and Android configuration profiles through the API. * Supports updating profile content, names where applicable, label targeting, and Fleet variable associations without replacing the profile identity. * Added support for editing Apple DDM declarations. * Added activity tracking for configuration profile edits. * **Bug Fixes** * Added validation for unsupported edits, invalid labels, duplicate names, missing profiles, and protected Fleet-managed profiles. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Jordan Montgomery <elijah.jordan.montgomery@gmail.com> |
||
|
|
900c54e822 |
Fix label membership being cleared when a label query errors (#49403)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #46399 When a label's query errors on a host (e.g. the extension socket is unavailable) instead of returning zero rows, Fleet was recording that error the same as a definitive "no match," clearing the host's existing label membership. This could unintentionally remove configuration profiles or other automations scoped to that label. The fix leaves existing label membership untouched when a label query errors. # 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 **Setup:** macOS VM enrolled as a Fleet host, with a dynamic label whose query targets a real, always-present table but with a deliberately invalid `WHERE` clause, so the query fails deterministically (a `no such column` SQL error). ```sql -- working version (label matches) SELECT * FROM os_version; -- broken version (query errors on every run) SELECT * FROM os_version WHERE this_column_does_not_exist = 1; ``` ### Before (bug reproduced on unpatched code) 1. Set the label's query to the working version and refetched the host — confirmed it shows up under the host's Labels. 2. Edited the label's query to the broken version. 3. Clicked **Refetch** on the host. 4. **Result:** the label disappeared from the host's Labels list — a query error incorrectly cleared existing membership. ### After (fix verified) 1. Reset the label's query to the working version and refetched — confirmed membership was restored. 2. Edited the label's query to the broken version again. 3. Clicked **Refetch** on the host. 4. **Result:** the label remained on the host's Labels list — a query error now correctly leaves existing membership untouched. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Preserved existing dynamic label memberships when label queries fail or yield unknown results. * Avoided treating unknown/failed evaluations as label removals. * Ensured label updates/removals are applied only when a definite match or non-match is returned. * **Tests** * Expanded coverage for label query errors across datastore, async processing, and distributed execution to confirm memberships remain unchanged. * Updated expectations for queued async updates to skip errored labels. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
7cb2399700 |
Redirect FMA installs to the active version after auto-update (#49525)
**Related issue:** Resolves #49495 Redirects queued Fleet-maintained app installs to the newly-active installer (canceling already-dispatched ones) atomically when an auto-update or pin change flips the active version, and re-resolves install retries to the active installer, so a host no longer installs a superseded cached version. # Checklist for submitter - [x] Changes file added for user-visible changes in `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 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fleet-maintained app installs now consistently use the currently active version after automatic promotions, preventing stale installer targeting. * Queued installs tied to an older promoted installer are redirected to the newly active installer instead of being canceled. * Install retry flows now re-resolve to the active installer at retry time, avoiding stale retries after version changes. * **Tests** * Added datastore coverage for active-installer redirection and updated retry tests to verify the correct installer ID is used. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
8a33fcd058 |
Fix FMA pinning not changing patch policy (#49519)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #49474 # 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 - Relied on integration test for testing changes made by the `maintained_apps_auto_update` job <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed patch policies for Fleet-maintained apps not updating when the active app version changes. * Patch policy queries now refresh to match the currently active (or pinned) installer version, including changes driven by pinning, cron, and GitOps. * Improved behavior when pins are cleared or switched, ensuring the policy continues referencing the correct version-specific query. * **Tests** * Expanded integration coverage to verify version-pinned patch policy queries across scenario updates. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |