eac1f4d3261941e2be21788dbe8a8e04f11a13d8
4687
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
0dc8c382c5 |
Add 'linux' as platform for labels (#50270)
Resolves #44088. - [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 * **New Features** * Added Linux as a label platform option. * Linux labels now apply across supported distributions, including Ubuntu, Debian, RHEL, CentOS, and generic Linux hosts. * Updated platform names for improved clarity and consistency. * **Bug Fixes** * Improved platform matching so Linux labels apply consistently to compatible hosts. * Removed the obsolete Zorin platform option. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
60e6827071 |
Fix Apple built-in label memberships during ADE (#50287)
**Related issue:** Resolves #50285 ## Summary - Restore the `All Hosts` and Apple platform built-in label memberships in the same transaction that clears stale host state during Automated Device Enrollment (ADE). - Backfill missing built-in memberships for existing macOS, iOS, and iPadOS hosts. - Add regression coverage confirming that an iPadOS update declaration remains targeted and reaches verified status after the enrollment reset. # Checklist for submitter - [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] 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 host's records do not affect another) - [ ] QA'd all new/changed functionality manually Automated verification: ```sh MYSQL_TEST=1 go test -run 'TestMDMApple/MDMAppleResetOnReenrollment' ./server/datastore/mysql MYSQL_TEST=1 go test -run TestUp_20260731100711 ./server/datastore/mysql/migrations/tables MYSQL_TEST=1 go test -run 'TestIntegrationsMDM/TestIPadOSUpdateDeclarationAfterMDMReset' ./server/service go test -run TestMDMTokenUpdateResetOnReenrollment ./server/service go vet ./server/datastore/mysql ./server/service go build ./server/datastore/mysql/migrations/... make test-schema ``` ## Database migrations - [x] Checked schema for all modified tables for columns that auto-update timestamps during migration. - [x] Confirmed that timestamp behavior is acceptable and will not cause unwanted side effects. The migration inserts only missing memberships and leaves existing membership timestamps unchanged. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Apple devices now retain their built-in label memberships after Automated Device Enrollment or MDM reset. * Label-scoped profiles, software, and operating system updates can now continue to be delivered after a reset. * Platform-specific memberships are restored for macOS, iOS, and iPadOS devices, including applicable hosts with unspecified platforms. * iPadOS update declarations now reconcile successfully after an MDM reset. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
7f1b330c90 |
Restrict deleting a fleet to global admins (#50271)
# 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** * Restricted fleet deletion to users with global write permissions, including global administrators and GitOps. * Corrected team deletion authorization to require global write access. * Prevented global technicians, team technicians, and observer-level users from deleting teams. * Updated authorization behavior to consistently enforce the required access level. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
3660b546f2 |
Fix FMA auto-update keeping the stale install script (#50200)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #50097 ## Summary FMA auto-update preserves an admin-customized install script by comparing the active script against the new manifest's, but FMA scripts hardcode the versioned installer filename, so a routine version bump looked like an edit and the old script (old filename) was kept against the newly downloaded installer, and the install failed. The fix neutralizes the installer filename in both scripts before comparing (mirroring the existing uninstall `$PACKAGE_ID` handling), so a filename-only difference adopts the new script while a genuine edit is still preserved. # Checklist for submitter - [x] Changes file added for user-visible changes in `changes/` (`changes/50097-fma-auto-update-keeps-stale-install-script`). ## Testing - [x] Added/updated automated tests (adopt-on-version-bump regression + preserve-genuine-edit counterpart). - [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 Fleet-maintained app auto-updates that could keep an outdated install script after downloading a newer version, causing install failures. * Improved install-script change detection by ignoring version-only installer filename differences. * Continued to preserve administrator-customized install scripts when updates change more than just the installer filename. * **Tests** * Added and expanded coverage for installer-script normalization and auto-update install-script selection behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
0594f653dd |
Propagate errors in macOS FMA install scripts (#50198)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #50056 ## Summary macOS FMA install scripts never checked the exit code of the install command (`installer -pkg` / `cp -R`) — the script's last statement is always `relaunch_application`, which exits 0 — so a failed install exited 0 and Fleet reported it installed. **Generated scripts.** The generator now propagates failure: both `installer -pkg` variants end with `|| exit $?`, and the `cp -R` path exits non-zero on a failed copy, removes the partial copy (so a failed fresh install isn't inventoried as the new version), and restores the app it moved aside. Regenerated `outputs/` for non-frozen generated apps are produced by the `ingest-maintained-apps` job, so they aren't committed here. **Custom scripts.** 9 of the 18 custom input scripts had the same bug and are fixed with the same pattern: Google Chrome, Zoom, Microsoft Edge, GitHub Desktop, Webex, Cycling '74 Max, Pd, Grammarly Desktop, and P4V. The DMG-based ones also now fail before removing/moving the existing app when the mount or staging copy fails, so a bad download can't leave a host with nothing. Their `outputs/*/darwin.json` are updated in the same commit (script content + recomputed 8-char sha256 ref, versions untouched), following the precedent of #49033. Docker Desktop (`set -euo pipefail`), 1Password/Slack/LogiTune (installer is the last statement), and the rest already propagated errors. **Frozen apps.** The ingest job never rewrites frozen outputs, so the 10 frozen apps with generated scripts (adobe-acrobat-pro, comet, evernote, firealpaca, keeper-password-manager, nvidia-geforce-now, pritunl, vnc-viewer, wins, worksheet-crafter) had the fix applied directly to their published `darwin.json` scripts — the exact text the current generator would emit, with pinned versions/URLs/hashes untouched. The 11th frozen app (logi-options+) uses a custom script that was already correct and in sync. # Checklist for submitter - [x] Changes file added for user-visible changes in `changes/` (`changes/50056-fma-install-scripts-ignore-errors`). - [x] Untrusted data interpolated into shell scripts is validated against shell metacharacters. (No new untrusted interpolation: the guard reuses the same curated cask-derived name the adjacent lines already interpolate.) ## Testing - [x] Added/updated automated tests (three generator tests: pkg, pkg-with-choices, cp-R restore — the last now pins the exact emitted block). - [x] All 19 updated output manifests validated: embedded scripts pass `bash -n`, refs match `sha256(script)[:8]`, refs map stays key-sorted like Go's encoder. - [x] QA'd all new/changed functionality manually. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * macOS Fleet-maintained app installations now fail fast when installers, DMG extraction/mounting, or app copy steps error. * If an upgrade fails, the system removes any partial app and restores the previously installed version when available. * Improved robustness during app staging/copying, including safer handling of paths with spaces or special characters. * **Tests** * Added unit coverage to verify installer failure propagation and rollback behavior. * **Documentation** * Clarified that the install-script error handling applies to both generated and custom scripts, including already-published frozen apps. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Allen Houchins <allenhouchins@mac.com> |
||
|
|
a442d7af3a |
Python script-only packages: follow-on QA fixes (#50143)
**Related issues:** Resolves #50068, Resolves #50106, Resolves #50107, Resolves #50108, Resolves #50110, Resolves #50114 Follow-on fixes from QA of #41470 (Python script-only packages): - Software-installer validation errors are action-neutral, so the Add and Edit flows each show the correct single verb, and the unsupported-file error names a content/format mismatch instead of blaming the extension (#50068, #50107). - `.py` packages accept `setup_experience_platform` (`darwin`/`linux`), matching `.sh` (#50106). - A failed-to-run install script (exit code `-1`) now renders a diagnostic instead of empty output, and orbit surfaces the underlying execve error (#50108). - The install-rejection message for `.sh`/`.py` packages says "macOS and Linux hosts" instead of "linux" (#50110). - Orbit writes each script's temp file with an extension matching its shebang (`.py`/`.sh`/`.ps1`), so tracebacks reference the right file type (#50114). # Checklist for submitter - [x] Changes file added for user-visible changes in `changes/`. ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually ## fleetd/orbit/Fleet Desktop - [x] If the change applies to only one platform, confirmed that `runtime.GOOS` is used as needed to isolate changes. - [x] Verified compatibility with the latest released version of Fleet (orbit-only change; the server↔agent `SoftwareInstallDetails` contract is unchanged). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved installer validation and rejection messaging for unsupported/invalid package contents (including correcting “add” vs “edit” wording and avoiding duplicated phrasing). * Added clearer diagnostics when install scripts fail to start (including empty output cases). * Corrected handling of script-only packages so Python scripts use the proper script type/extension, reducing misleading tracebacks. * Updated platform availability messaging so `.sh`/`.py` packages display macOS+Linux support. * **New Features** * Python script-only packages can now specify macOS and Linux setup experience platforms. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
294a172d11 |
Clarify maintained app download timeout errors (#50104)
**Related issue:** Resolves #48416 When adding a Fleet-maintained app, a large-installer download that's canceled or times out now returns a clear message pointing at the likely proxy/load-balancer timeout, instead of a raw `context canceled`. # 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** * Improved error messages when adding Fleet-maintained apps times out or is canceled during large installer downloads. * Added clearer guidance for configuring server, proxy, and load balancer timeouts. * Properly handles additional timeout and upstream cancellation responses, including HTTP 408, 499, and 504. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
554c62e470 |
Add apps installed through Windows app store to software inventory
Resolves #14717 Add apps installed through Windows app store to software inventory |
||
|
|
b06cbde1de |
Exclude non-existent host IDs from host transfer activity
The host transfer endpoint recorded raw requested host IDs in the transferred_hosts activity verbatim, letting an authorized user inject fabricated IDs into the audit trail. Derive the activity's host IDs and names only from hosts that actually exist, and skip the activity when none exist. |
||
|
|
e5b0f313f9 |
Fix password reset accepting case-mutated tokens
Reset tokens are base64url (case-sensitive) but the password_reset_requests.token column used case-insensitive utf8mb4_unicode_ci, so a case-mutated token copy still matched. Switch the column to utf8mb4_bin for byte-exact comparison. |
||
|
|
8a65ecf20b | Bound Android device reconciliation pagination loop (#49615) | ||
|
|
7f4ae81dc9 |
Moved changes file
46227-luks-key-escrow-any-slot changes were added as a Fleet server change, should be an orbit change. |
||
|
|
dcefd13130 |
Stop leaking live query campaign existence via the websocket results stream (#50210)
# 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** * Standardized websocket error responses when requested campaigns are unavailable. * Prevented campaign existence from being inferred through differing error messages. * Improved consistency for both nonexistent campaigns and campaigns inaccessible to the current user. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
c83ecc2231 |
Match Windows software with version in name to FMA software title
Resolves #44406 Windows programs report a version in their name (e.g. `Granola 7.373.2`), so each version created its own `software_title` and never linked to the Fleet-maintained app installer's title (`Granola`), hiding the uninstall action. macOS handles this via `bundle_identifier`; Windows had no join key. - Give matching Windows programs the canonical FMA name at ingestion (name-prefix match), so all versions collapse onto the title the installer owns. `software.name` is unchanged. - Merge already-mismatched versioned titles onto the canonical title in `ReconcileMaintainedAppSoftwareNames` (runs on FMA sync; no migration needed). --------- Co-authored-by: Tim Lee <timlee@fleetdm.com> Co-authored-by: Juan Fernandez <juan@fleetdm.com> |
||
|
|
a1b35aeb23 |
fix icon text gap across product (#50209)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #48217 This does update a couple of places, but I checked and it should only be for Status indicators. Figma spec with 4px rather than 8px: https://www.figma.com/design/gxvU745LfOdkE9AuRg64wi/%F0%9F%A7%A9-Product-design-system?node-id=858-23&t=QwTqGmpK0V3inArL-0 <img width="1119" height="407" alt="image" src="https://github.com/user-attachments/assets/8cae52d6-dbb9-4b8d-80d6-1a899790ad82" /> # 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 - [ ] 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** * Reduced the spacing between icons and text for a more compact, consistent layout across the product. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
1397531199 |
Authorize packs before returning them in query responses (#50148)
- [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 * **Bug Fixes** * Query responses now include pack details only when the requester has permission to view them. * Prevented pack metadata from being disclosed across fleets when query names overlap. * Corrected target selection labels and empty-state messaging for fleet-based targets. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
1a0f0101cc |
Fix gitops not updating FMA installer (#50000)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #49811 # 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 Fleet-maintained app updates when a rebuilt installer keeps the same version. * Rebuilt installers now update their files, hashes, filenames, and install scripts correctly. * Prevented installers from being incorrectly skipped when their contents differ despite matching versions. * **Tests** * Added coverage for same-version installer rebuilds and team-specific caching behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
9c2ef14947 |
Scrub device policy responses in Fleet Desktop (#50094)
- [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 ## 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 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 * **Security Improvements** * Updated device-authenticated policy and host-detail responses to omit policy author identity fields and any raw SQL/query data. * Device policy endpoints now return a device-safe policy representation consistently. * **Bug Fixes** * Prevented administrative policy information from appearing in device-authenticated host details and policy listings. * **Tests** * Strengthened integration coverage to verify device-safe responses (required user-facing fields present; sensitive fields absent). <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> |
||
|
|
f5ca4b5b0d |
Add Android support for custom host vitals (#49696)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #49421 Custom host vitals (`$FLEET_HOST_VITAL_<id>`) already worked in scripts and Apple/Windows configuration profiles, but Android configuration profiles and managed app configuration explicitly rejected them at upload to keep parity with `$FLEET_SECRET_*`. This left admins unable to inject per-host vitals (e.g. an asset tag) into Android MDM configuration the same way they can for every other platform. For more context, prior PRs: - https://github.com/fleetdm/fleet/pull/49334 - https://github.com/fleetdm/fleet/pull/49586 # 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 - Created an "Asset tag" host vital. - Enrolled an Android device. - Initially the test profile showed as "Failed" because no value was set for the vital. - Set a value for the vital, saw that it went from Enforcing to Verified. <img width="1446" height="510" alt="Screenshot 2026-07-24 at 8 57 46 AM" src="https://github.com/user-attachments/assets/c0e2348c-e521-48f3-85cd-6f884689b2cd" /> <img width="1520" height="936" alt="Screenshot 2026-07-24 at 8 56 56 AM" src="https://github.com/user-attachments/assets/169b9545-ec7a-429b-8f45-0e2740f61c77" /> <img width="1607" height="1136" alt="Screenshot 2026-07-24 at 8 57 30 AM" src="https://github.com/user-attachments/assets/a8213745-b224-4a36-a54d-32152a15c377" /> Also tested the rejection cases: - trying to upload a profile with an invalid custom host vital id (either a non-numeric value, a numeric but non-existent ID, and referencing a vital as a JSON key instead of a value) - deleting a vital referenced in a profile https://github.com/user-attachments/assets/e8b4acde-ddf4-41c0-b00a-5ab4945d0bc2 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit * **New Features** * Android app configurations and profiles now support custom host vital placeholders (`$FLEET_HOST_VITAL_<id>`). * Custom host vital values are expanded per device during Android delivery. * Managed Android profiles/configurations are automatically resent when a referenced vital value changes. * **Bug Fixes** * Added validation for malformed, missing, or undefined vital references during Android app association and profile/config uploads. * Prevented deletion of vitals referenced by Android profiles. * Improved error handling and delivery failure details when a device lacks a required vital value. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
5983f9de40 |
Require Fleet MDM enrollment before escrowing macOS disk encryption key (#50042)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #48965 ## Description Fleet was escrowing a macOS disk encryption key — and logging an "escrowed a disk encryption key" activity — for hosts that aren't enrolled in Fleet's MDM (e.g. still managed by Jamf, or with a leftover `/var/db/FileVaultPRK.dat`). Because Fleet never installed its FileVault escrow profile on such a host, the stored key is unusable: the cron marks it `decryptable = 0` and `GET /hosts/:id/encryption_key` returns 422, so "Show disk encryption key" never appears. The result is a misleading activity and a dead key row. Root cause: the macOS key ingestion (`directIngestDiskEncryptionKeyFileDarwin` and its `file_lines` fallback) gated only on the disk being encrypted and disk encryption being enabled for the host's team — it never checked Fleet MDM enrollment. The Windows/orbit key path (`SetOrUpdateDiskEncryptionKey`) already performs this check. - **`server/service/osquery_utils/queries.go`** — added an `IsHostConnectedToFleetMDM` guard to both macOS ingestion functions, skipping archival (no key stored, no activity) when the host isn't connected to Fleet MDM. Mirrors the existing Windows path. Prevention only — this stops new bad escrows; it does not delete keys previously escrowed for non-enrolled hosts. ## Testing - **Unit** (`queries_test.go`): added a "host not connected to Fleet MDM" case asserting neither ingestion function escrows when the host isn't Fleet-MDM-connected, and initialized the `IsHostConnectedToFleetMDM` mock so existing cases still pass. - **Integration** (`integration_mdm_test.go`): `TestMDMAppleHostDiskEncryptionWithDisabledEncryptionSetting` was creating an orbit-only host (no Fleet MDM) and expecting escrow to succeed — i.e. relied on the bug. Switched it to a Fleet-MDM-enrolled host (`createHostThenEnrollMDM`), which is now required for escrow. Passes. # 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). ## Testing - [x] Added/updated automated tests - [ ] QA'd all new/changed functionality manually <!-- covered by automated integration test; live no-device repro is impractical, flagged for reviewer --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - FileVault recovery keys are now archived/escrowed only for macOS hosts that are connected to Fleet MDM. - Hosts without an active Fleet MDM connection no longer attempt to archive encryption keys. - Disk-encryption key archival now cleanly reports MDM connectivity errors when checks fail. - **Tests** - Added/updated coverage to verify both connected and disconnected host scenarios, including ensuring no archival occurs when MDM is not connected. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
8f7a4ba2a0 | Redirect to software inventory on 404 when switching fleets on title (#48389) | ||
|
|
5bdbcc8495 | 48792 fix actions dropdown layout shift (#49430) | ||
|
|
360e4b74ff |
Update macOS disk encryption banner copy for ADE-enrolled hosts
Relates #47832 Both the Host details and My device pages told the reader to log out or restart when Fleet didn't have a Mac's FileVault key. That's wrong for ADE-enrolled hosts: they escrow the key automatically, and the only thing standing between the host and a cleared banner is the next vitals refetch. It stays correct for manual enrollment, where Escrow Buddy only generates a new key at next login. |
||
|
|
418fd60e9c |
Clarify "Not supported" on Hosts page by adding tooltip (#49301)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #39987 - Added tooltips to the "Agent," "Last restarted," and "Status" column headers on the Hosts page explaining which platforms are supported and why. - On the Host details page, vitals with a "Not supported" value are now hidden instead of shown. - Fixed the "Last restarted" vital showing on ChromeOS hosts, where it's not actually collected. - Updated the "Last opened" tooltip on the Host details Software table to explain why it's only supported for native macOS, Windows, and Linux apps and packages. - Remove cellProps.rows.length === 1 workaround (which suppresses the tooltip whenever the table has exactly one row) by adding the correct CSS which removes the tooltip overflowing if host table is only 1 row # 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** - Added/updated explanatory tooltips for Hosts table column headers (Agent, Last restarted, Status) with clearer supported-platform wording. - Clarified “Last opened” tooltip scope to native macOS, Windows, and Linux app/package entries. - **Bug Fixes** - Removed “Last restarted” from Host details for ChromeOS hosts when the value isn’t collected. - Prevented vitals rows from rendering when their values resolve to “Not supported,” and tightened “Last restarted” platform visibility. - Fixed tooltip overflow/positioning in the single-row Host software table case. - **Tests** - Updated and expanded vitals/header coverage to match the new display rules. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
5250936179 |
Consistent URL/email on-blur validation across forms (#40410 follow-up) (#49932)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #40410 Follow-up to #48854, which added on-blur validation to the software vulnerability automations webhook. QA found three more forms with inconsistent validation, in two flavors: - **Validated only on save** (no on-blur feedback): Policies > Manage automations > Other workflows > Destination URL. - **Errored before any input** (validation fired on mount/enable): Settings > Users > Add/edit user > Email, and the host status webhook Destination URL (both global and fleet settings). This makes them consistent with the rest of the app: no error on open/enable → validate on blur → clear the field's error as the user edits → validate on submit. - `OtherWorkflowsModal` — added an on-blur handler for the Destination URL (guarded by the field's disabled condition). - `UserForm` — on-blur now validates only the blurred field (so blurring the autofocused Name no longer flags the empty Email/Password); submit validates all fields. - `GlobalHostStatusWebhook` — removed the `useEffect` that validated the moment the webhook was enabled; validation now runs on blur and submit. - `TeamSettings` (fleet host status webhook) — the Destination URL error is no longer surfaced on change/enable; it validates on blur and submit. # 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 (URL and email fields validate on blur and on submit; no errors are shown before the user interacts). ## 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 webhook destination URL validation across integrations, team settings, and workflow automation forms. * Validation messages now appear after leaving the URL field, rather than prematurely while enabling or editing. * Prevented saving or submitting forms with missing or invalid destination URLs. * Correctly clears validation errors once a valid URL is entered. * Improved user form validation so field-specific errors appear only for the field being reviewed, while submit continues to validate the full form. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
24e64614aa |
Fix resource exhaustion in MSI metadata parser (#49739)
Resolves https://github.com/fleetdm/confidential/issues/16902 - [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 ## Reproduction **Attack vector:** An authenticated Fleet admin uploads a crafted `.msi` file via the software upload API. The server's MSI metadata parser (`pkg/file/msi.go` > `ExtractMSIMetadata` > `decodeStrings`) processes the file's `_StringPool` and `_StringData` streams during upload. A malicious `_StringPool` can claim arbitrarily large string sizes that trigger speculative memory allocation before the actual data is read. **Manual reproduction:** Wrote a standalone Go program that constructs the two raw byte streams the parser consumes (a 12-byte `_StringPool` claiming a 64 MB string, and an empty 0-byte `_StringData`), then measures heap allocation via `runtime.MemStats` before and after calling the vulnerable code path. **Before fix (vulnerable):** ``` Pool input size: 12 bytes StringData size: 0 bytes Claimed string size: 67108864 bytes (64 MB) Error returned: failed to read string data: EOF Heap allocated: 67117016 bytes (64.0 MB) Amplification: 12 input bytes -> 67117016 byte allocation (5593084x) ``` 12 bytes of pool input forced a 64 MB heap allocation via `buf.Grow()` before `io.CopyN` discovered there was no data to read. **After fix:** ``` Error returned: failed to read string data: EOF Heap allocated: 3072 bytes (3.0 KB) Memory amplification eliminated: true ``` Same input, 3 KB allocated instead of 64 MB. Without the speculative `buf.Grow()`, `io.CopyN` grows the buffer incrementally based on actual available data and immediately hits EOF. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Fixed a potential resource exhaustion issue when processing MSI metadata with unusually large string-size declarations. - MSI files with missing string data are now handled without excessive memory allocation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Lucas Manuel Rodriguez <lucas@fleetdm.com> |
||
|
|
f2662ccaf5 |
Default setup experience account type to admin when serving team config (#50034)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #49346 ## Description A fleet created before the managed local account keys existed (e.g. in 4.84.0) and never edited since has no `end_user_local_account_type` or `enable_managed_local_account` in its stored config. `GET /teams/:id` served these as `null`, so the *Setup experience → Users* card showed no account-type selection and a wrongly checked, greyed-out "Create hidden admin" box. - **`server/fleet/teams.go`** — `Team.MarshalJSON` now falls back to `"admin"` / `false` for these keys when they're unset, mirroring the existing `AppConfig.MarshalJSON` fallback that already covers the global ("No team") config. This is the one serve path that was missing the default; the save path (`TeamConfig.Value()`) already applied it, which is why only untouched pre-4.84.0 fleets were affected. Serve-time fallback only — no stored data is modified and the account-provisioning logic is untouched. > **Note for reviewers:** `Team.MarshalJSON` is also the serialization used by `fleetctl get teams` / GitOps, which had the same `null` bug. With this change those now emit `end_user_local_account_type: admin` and `enable_create_local_admin_account: false` for teams that previously showed `null` — matching what the global config already emits. The get→apply roundtrip stays idempotent because the save path already writes these defaults. Team goldens updated accordingly. ## Testing - **Automated:** `TestTeamMarshalJSONMacOSSetupDefaults` (`server/fleet`) — a team with the keys unset marshals to `"admin"` / `false`, and explicitly set values still round-trip. Updated the `fleetctl` team goldens (`TestGetTeams`, `TestApplyMacosSetup`, `TestApplyMacosSetupDeprecatedKeys`) to reflect the defaulted output. - **Manual:** simulated a 4.84.0 fleet by removing both keys from a team's stored `config` JSON. On `main` the Users card showed no selected radio and a checked, greyed hidden-admin box; on this branch the same fleet shows **Admin** selected and the box unchecked, matching what global "No team" already renders. # 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). ## 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** * macOS device setup now applies correct defaults when managed local account settings are missing from existing team configurations. * The end-user local account type now defaults to **admin** and managed local account creation defaults to **disabled** (false) unless explicitly configured. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
0504e5949e |
Add host_id and host_serial to Apple mdm_enrolled activity (#49969)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #49777 ## Description Adds `host_id` and `host_serial` to the Apple `mdm_enrolled` activity so IT admins can build automations on top of it, and surfaces the activity on the individual host's activity timeline. - **`server/fleet/activities.go`** — added `HostID` to `ActivityTypeMDMEnrolled` and a `HostIDs()` method (mirrors the existing `ActivityTypeMDMUnenrolled` pattern), so the activity is linked to the host and appears on its timeline. - **`server/mdm/lifecycle/lifecycle.go`** — populate `host_id` for macOS/iOS/iPadOS enrollments. Account-driven user (BYOD) enrollments have no hardware serial, so they report the enrollment ID as `host_serial` too, keeping `host_serial` populated for automations regardless of enrollment type. - **Frontend** — new `MdmEnrolledActivityItem` component, registered in the host past-activity component map (and the `IHostPastActivityType` union), renders the now-host-linked `mdm_enrolled` activity on the host details **Activity** card. There's no Figma, so the copy mirrors the sibling `mdm_unenrolled` item (e.g. "Mobile device management (MDM) was turned on for this host"). `host_id` uses `omitempty`, so Windows (`microsoft_mdm.go`) enrollments keep their existing activity payload unchanged — Windows is intentionally out of scope, handled in #47874, which also owns the audit-log documentation update for the shared field. > **For reviewer:** the ADUE `host_serial = enrollment_id` behavior comes from the issue's test plan. It means `host_serial` and `enrollment_id` carry the same value for BYOD. Flagging in case Product would rather leave `host_serial` empty for ADUE and have automations read `enrollment_id`. ## Testing - **Automated:** `TestMDMEnrolledActivityHostIDAndSerial` (`server/mdm/lifecycle`) covers device enrollment (`host_serial` = hardware serial) and ADUE (`host_serial` = enrollment ID), both asserting `host_id`/`HostIDs()`. Also verified `server/datastore/mysql` `TestMDMEnrollment`, `server/activity/internal/mysql` `TestListActivities`, and `server/service` `TestMDMTokenUpdate*` pass. - **Live (simulated) manual macOS enrollment** via `osquery-perf`: the `mdm_enrolled` activity recorded `host_id` + `host_serial`, and an `activity_host_past` row linked it to the host (confirmed it shows on the host timeline). - **Frontend:** `MdmEnrolledActivityItem.tests.tsx` covers the rendered copy for macOS/iOS/Android and the actor/no-actor variants; also visually confirmed the activity renders on a host's Activity card in the running app. `yarn jest`, `eslint`, and `tsc` pass. - Updated the MDM integration tests (`integration_mdm_test.go`, `integration_mdm_dep_test.go`, `integration_vpp_install_test.go`) whose activity-detail and host-feed assertions changed now that `mdm_enrolled` carries `host_id` and appears on the host timeline (feed assertions now filter by activity type). - **Pending on-device QA (next week):** DEP/ADE macOS and account-driven user enrollment (iOS/iPadOS) on real hardware, per the issue's test plan. - Regression: Windows `mdm_enrolled` payload is unchanged (`host_id` is omitted when zero); both platforms' `mdm_unenrolled` are unaffected. # Screenshot for the frontend change <img width="706" height="382" alt="Screenshot 2026-07-28 at 11 16 57 AM" src="https://github.com/user-attachments/assets/8f57d129-f819-4399-8754-18b397a49db8" /> # 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 - [ ] QA'd all new/changed functionality manually <!-- manual macOS verified via simulator; DEP + real-device ADUE pending next week --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit * **New Features** * Added support for rendering “MDM enrolled” in the host activity feed with platform- and actor-aware messaging. * **Bug Fixes** * Updated Apple “MDM enrolled” activity details to include the correct host identifier and serial/enrollment identifiers. * Ensured host-scoped activity behavior applies only when the host is known (host id present). * **Tests** * Expanded regression and integration coverage for “MDM enrolled” activity details and feed contents, including VPP-related assertion stability. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Magnus Jensen <magnus@fleetdm.com> |
||
|
|
bf3e1bab99 |
Add Apple marketing names to backend, frontend, and an osquery table (#46482)
**Related issue:** Resolves https://github.com/fleetdm/fleet/issues/46818 and https://github.com/fleetdm/fleet/issues/48524. # 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 ## 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 - [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** * Host lists and Host details now show human‑readable Apple hardware marketing names (macOS, iOS, iPadOS) where available (e.g., "MacBook Pro (16‑inch, 2021)"), replacing raw model identifiers. * Hardware model displays fall back to the original model identifier for non‑Apple or unmapped devices. * **Bug Fixes / CSV** * Exported host CSVs now align with the UI by using the marketing name for Apple devices when available. <!-- 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: Lucas Manuel Rodriguez <lucas@fleetdm.com> |
||
|
|
84896a5687 |
Add tooltip explaining missing Refetch button for Android hosts (#50017)
<img width="632" height="196" alt="Screenshot 2026-07-27 at 3 09 16 PM" src="https://github.com/user-attachments/assets/7bfc1440-48a4-4baf-8747-cc5e848a3a53" /> <!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #50001 # 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** * Added an explanatory tooltip to the “Last fetched” field for Android hosts. * The tooltip clarifies that Android hosts sync automatically and therefore do not have a “Refetch” button. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
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. |