Commit Graph
4672 Commits
Author SHA1 Message Date
Lucas Manuel Rodriguez 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 -->
2026-07-29 13:35:47 -03:00
Jonathan Katz 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 -->
2026-07-29 10:00:16 -04:00
Lucas Manuel RodriguezandCopilot Autofix powered by 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>
2026-07-29 09:34:31 -03:00
Nico 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 -->
2026-07-29 08:22:57 -03:00
Rajendra Kadam 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 -->
2026-07-29 14:01:35 +05:30
Rahul Raghunathan 8f7a4ba2a0 Redirect to software inventory on 404 when switching fleets on title (#48389) 2026-07-28 13:58:55 -07:00
Rahul Raghunathan 5bdbcc8495 48792 fix actions dropdown layout shift (#49430) 2026-07-28 13:56:50 -07:00
Juan Fernandez 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.
2026-07-28 15:33:26 -04:00
LeAnn 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 -->
2026-07-28 10:30:21 -07:00
Carlo 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 -->
2026-07-28 13:23:48 -04:00
Sharon KatzandLucas Manuel Rodriguez 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>
2026-07-28 12:26:40 -04:00
Rajendra Kadam 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 -->
2026-07-28 20:04:41 +05:30
Rajendra KadamandMagnus Jensen 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>
2026-07-28 14:27:42 +05:30
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>
2026-07-27 22:26:30 -03:00
LeAnn 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 -->
2026-07-27 15:39:22 -07:00
Victor Lyuboslavsky 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 -->
2026-07-27 12:49:14 -05:00
Rajendra Kadam 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 -->
2026-07-27 19:42:22 +05:30
melpike 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 -->
2026-07-27 08:07:54 -06:00
Andrew Mellor 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 -->
2026-07-27 10:35:27 +01:00
Jordan Montgomery 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 -->
2026-07-27 11:24:42 +02:00
Sharon Katzandcopilot-swe-agent[bot] 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>
2026-07-24 15:46:14 -04:00
RachelElysia 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 -->
2026-07-24 11:22:06 -04:00
Juan Fernandez 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.
2026-07-24 10:29:46 -04:00
RachelElysia 3e3097cf49 Fleet UI: Drop I-beam cursor on non-underlined tooltips (#49859) 2026-07-24 07:01:48 -07:00
NicoandCopilot Autofix powered by AI 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>
2026-07-24 10:39:13 -03:00
Rajendra Kadam 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 -->
2026-07-24 13:30:57 +05:30
Rajendra Kadam 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 -->
2026-07-24 11:10:38 +05:30
RachelElysia 9cfd907be6 Fleet UI: Hide empty host summary card on Free-tier Android hosts (#49848) 2026-07-23 12:54:18 -07:00
Victor Lyuboslavsky 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 -->
2026-07-23 11:59:37 -05:00
Carlo 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 -->
2026-07-23 12:39:17 -04:00
Sharon Katz 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
2026-07-23 10:44:13 -04:00
RachelElysia 968ea20aeb Fleet UI: Searchable fleets dropdown with add-fleet affordance (#49690) 2026-07-23 07:26:04 -07:00
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>
2026-07-23 09:52:07 -04:00
Steven Palmesano 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"
/>
2026-07-23 07:11:59 -05:00
Juan Fernandez 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.
2026-07-23 06:41:51 -04:00
Juan Fernandez 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.
2026-07-23 06:41:27 -04:00
Juan Fernandez 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.
2026-07-23 06:41:07 -04:00
Victor Lyuboslavsky 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 -->
2026-07-22 15:32:58 -05:00
Victor Lyuboslavsky 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 -->
2026-07-22 13:46:47 -05:00
Magnus Jensen 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 -->
2026-07-22 20:01:41 +02:00
Magnus Jensen 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 -->
2026-07-22 19:19:48 +02:00
Juan Fernandez 10ac3c73a3 Harden password reset token handling
Ensure a password reset token can only be used once.
2026-07-22 12:46:16 -04:00
Nico 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 -->
2026-07-22 13:23:21 -03:00
Dante Catalfamo 932e82e856 Gitops mode disables android MDM connect and turn off buttons (#49685)
**Related issue:** Resolves #48226
2026-07-22 11:31:27 -04:00
LeAnn 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 -->
2026-07-22 08:10:02 -07:00
Dante Catalfamo 6d0ecf1b9f Clarify which OS supports OS Updates (#49716)
**Related issue:** Resolves #48960
2026-07-22 10:48:28 -04:00
Victor LyuboslavskyandSharon Katz 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>
2026-07-22 09:24:40 -05:00
George Karr 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 -->
2026-07-22 09:18:57 -05:00
Magnus Jensen 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 -->
2026-07-22 16:12:29 +02:00
Nico 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 -->
2026-07-22 11:12:16 -03:00