6ce0f70ebcf2bbf00799cc9aa3fc781297540140
26617
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
6ce0f70ebc |
Not Now edge case fixes for Apple profiles (#50044)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #47411 (Speculative, but we will keep investigating if we get new reports) # 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 Apple MDM profile handling for devices that respond with “Not Now” by ensuring the response is issued only on first delivery and doesn’t trigger repeated retries. - Improved reconciliation so superseded InstallProfile commands are properly canceled and cleanup is correct for user-scoped and pending installs. - When host verification fails after an acknowledged install, devices now receive the appropriate RemoveProfile operation. - **Tests** - Added regression integration coverage for “Not Now” cancellation, scope changes, profile edits, undelivered installs, and failed verification cleanup. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
19af21dd1a |
Upgrade query-generator SQL step to Claude Sonnet 5 (#49187)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** N/A ## What this does The `/query-generator` page's osquery-SQL-generation step ([get-llm-generated-sql.js](website/api/controllers/query-generator/get-llm-generated-sql.js)) was on `claude-sonnet-4-6`, which is now one generation behind. This PR: - Bumps that call to `claude-sonnet-5`. The schema-filtration step stays on `claude-haiku-4-5`, which is already the latest Haiku release, so no change needed there. - Adds `effort` support to the shared [`ai.prompt` helper](website/api/helpers/ai/prompt.js), forwarded as `output_config.effort` on Anthropic requests, and sets it to `"low"` for the SQL-generation call. Effort controls how much the model deliberates (and how many tokens/how much latency that costs). `"low"` was chosen because the Haiku pre-filtering step already narrows the osquery schema down to relevant tables, so the Sonnet step isn't starting from scratch and doesn't need to spend much effort re-deriving that context. - Bumps `max_tokens` in the Anthropic branch of the helper from 4096 to 8192. Claude Sonnet 5 turns on adaptive thinking by default when the `thinking` param is omitted (which this helper does), and `max_tokens` is a hard cap on *total* output including thinking tokens — at 4096 there was a real risk of thinking tokens eating into the budget and truncating the JSON response the SQL step needs to return. - **Fixes a pre-existing bug found while making the above changes:** the `sqlReport` call passed the system prompt as a bare object-shorthand key named `systemPromptForQueryGeneration`, but the `ai.prompt` helper's declared input is `systemPrompt`. Sails silently drops unrecognized keys passed to `.with(...)`, so the "Return ONLY a raw JSON object..." system prompt was never actually reaching the model for this call. This has been broken since the query generator was switched to Anthropic (`f7c20c4731`); the sibling `filteredTables` call above it was unaffected since it passes `systemPrompt` positionally. Now fixed to `systemPrompt: systemPromptForQueryGeneration`. ## Why Claude Sonnet 5 follows structured/constrained instructions (don't alias tables, use `LIKE` with wildcards, only reference documented columns, etc.) more literally than 4.6, which should make the generated SQL more reliable. It's priced the same or cheaper than 4.6 during the current introductory period. ## Trade-offs called out for review - Thinking being on by default adds some latency versus the old (thinking-off) behavior on 4.6. This call is not currently streamed (`sails.helpers.http.post`, single blocking call over a socket), so any added thinking time is invisible wait time for the user rather than a visible "thinking" indicator. `effort: "low"` should keep this modest, but worth confirming with a manual QA pass on a few representative questions before merging. - Only the SQL-generation call was migrated. The schema-filtration call also runs on an Anthropic model, but Haiku 4.5 doesn't support `output_config.effort` (added `effort` is a no-op if passed to it), so it was left as-is. # Checklist for submitter If some of the following don't apply, delete the relevant line. - [ ] 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 - [ ] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes ## Testing - [ ] 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) - [ ] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * Improved AI-generated SQL responses with an updated language model. * Added adaptive effort controls for supported AI requests. * Increased response capacity to support more detailed generated results. * Improved handling of AI responses to provide more reliable results when content includes different response formats. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Eric <eashaw@sailsjs.com> |
||
|
|
033cb8843c |
Fix image captions breaking onto multiple lines when they contain links (#50441)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** NA Image captions on articles broke onto multiple lines whenever the caption contained an inline link. Reported on [Linux crossed 10% in North America, and your inventory might have missed it](https://fleetdm.com/articles/linux-crossed-10-percent-and-your-inventory-missed-it), where the source line under the Cloudflare Radar chart rendered as: ``` Source: Cloudflare Radar , captured August 3, 2026. ``` ## Cause Image captions (`img + em`) were styled as a column flex container: ```less display: flex; align-items: center; flex-direction: column; ``` Every child of a flex container becomes its own flex item on its own line — including bare text nodes, which get wrapped in anonymous flex items. That caption has three children (`"Source: "`, the `<a>`, and `", captured August 3, 2026."`), so it stacked into three rows. Every other image caption in `articles/` is a single plain-text run, which is why this hasn't surfaced before. This is the first caption on the site with an inline link. ## Fix ```less img + em { // Image captions position: relative; top: -12px; display: block; text-align: center; margin-bottom: 16px; } ``` `display: block` + `text-align: center` preserves the existing centered appearance for plain-text captions (visually identical) while letting inline content flow normally. ## Notes for the reviewer - **Six files, one rule.** The identical caption rule was copy-pasted into `basic-article.less`, `basic-webinar.less`, `basic-whitepaper.less`, `case-study.less`, `legal/privacy.less`, and `legal/terms.less`. Only `basic-article.less` is needed to fix the reported page; the other five carry the same defect, so all six are updated rather than leaving the trap for the next caption with a link. - **No markdown change.** The article source (`*Source: [Cloudflare Radar](...), captured August 3, 2026.*`) was already correct. This is purely a stylesheet fix. - **Mobile overrides untouched.** The second `img + em` block in each file (inside a media query) only adjusts `top` and `margin-bottom`, so it needed no change. - **Existing captions are unaffected.** All current captions are single text runs; block + centered text renders them the same as column flex + `align-items: center` did. # Checklist for submitter - [x] QA'd all new/changed functionality manually Verified on the live article by injecting the new rule into the rendered page: the caption went from 72px tall (three stacked lines) to 24px (one centered line), rendering as `Source: Cloudflare Radar, captured August 3, 2026.` I was not able to run `npm run lint` locally — `website/node_modules` is not installed in my working copy. The change follows `.lesshintrc` (one space after `:`, no `!important`), but CI's lint run is the authority here. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Style** * Improved image caption layout across articles and legal content. * Captions now display consistently as centered block text for better readability. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
b2b2081ad4 |
Remove Gadwin PrintScreen, PrintScreen Pro, and ScreenRecorder FMAs (expired TLS cert on download host) (#50470)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** NA Removes the three Gadwin Fleet-maintained apps: **Gadwin PrintScreen**, **Gadwin PrintScreen Pro**, and **Gadwin ScreenRecorder**. All three download their installers from `www.gadwin.com`, whose Let's Encrypt certificate **expired 2026-08-02** and has not been renewed: ``` subject=CN=gadwin.com issuer=C=US, O=Let's Encrypt, CN=R13 notBefore=May 4 13:06:54 2026 GMT notAfter=Aug 2 13:06:53 2026 GMT ``` Every FMA validation run now fails these three apps: ``` level=ERROR msg="Error downloading maintained app: downloading installer: performing request for URL https://www.gadwin.com/download/PrintScreen650_Win64.msi: tls: failed to verify certificate: x509: certificate has expired or is not yet valid" app="Gadwin PrintScreen" ``` This is not just CI: Fleet fetches the installer from that same URL when a user installs the app, so all three are currently uninstallable for customers. > [!NOTE] > The certificate expired only one day before this PR was opened. If Gadwin renews it, these apps become viable again and the alternative fix is `"frozen": true` in each winget input (which skips validation) rather than removal. Removing was chosen because a lapsed auto-renewing certificate means no one is maintaining the download host, and a broken installer URL is worse for users than an absent app. Happy to switch to a freeze if reviewers prefer to wait it out. ### What's removed Per app, all locations that applied: | Location | PrintScreen | PrintScreen Pro | ScreenRecorder | |---|---|---|---| | `ee/maintained-apps/inputs/winget/<slug>.json` | ✅ | ✅ | ✅ | | `ee/maintained-apps/outputs/<slug>/windows.json` | ✅ | ✅ | ✅ | | `ee/maintained-apps/outputs/apps.json` entry | ✅ | ✅ | ✅ | | `frontend/.../icons/<Name>.tsx` | ✅ | ✅ | — (none existed) | | import + mapping in `icons/index.ts` | ✅ | ✅ | — | | `website/assets/images/app-icon-<slug>-60x60@2x.png` | ✅ | ✅ | — (none existed) | All three are Windows-only (no Homebrew input or `darwin.json`), so no macOS counterpart is affected and no shared icons needed to be retained. `apps.json` goes from 1393 to 1390 apps. The diff is deletion-only. # Checklist for submitter - [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 Verification performed: - `apps.json` parses as valid JSON; no `gadwin` slugs remain. - Repo-wide grep for `gadwin` returns no dangling references. (The one remaining hit, `cmd/osquery-perf/software-library/software.sql`, is a simulated host-inventory fixture, not an FMA definition — intentionally left in place.) - `npx tsc --noEmit` reports no errors related to the removed icon components or the icon index. - `npx prettier --check` passes on `icons/index.ts` and `apps.json`. - `go build ./cmd/maintained-apps/... ./ee/maintained-apps/...` and `go test ./ee/maintained-apps/...` pass. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Removed Gadwin PrintScreen, Gadwin PrintScreen Pro, and Gadwin ScreenRecorder from the maintained Windows application catalog. * Removed their associated software listings, installation details, and product icons from the application interface. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
2431d580b0 |
Add QEMU as a Windows Fleet-maintained app (#50471)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #50126 Adds **QEMU** (`SoftwareFreedomConservancy.QEMU`) as a Windows Fleet-maintained app, requested by a customer in #50126. Windows-only: on macOS, Homebrew ships QEMU as a formula (CLI tools, no `.app` bundle), so it isn't a viable macOS FMA. ## App identity (verified against the real installer) - Downloaded `qemu-w64-setup-20260501.exe` from `qemu.weilnetz.de`; SHA256 matches the winget manifest. - QEMU's NSIS definition ([`qemu.nsi`](https://gitlab.com/qemu-project/qemu/-/blob/master/qemu.nsi)) writes the uninstall key `HKLM\...\Uninstall\QEMU` (64-bit view via `SetRegView 64`) with `DisplayName "QEMU"` and `DisplayVersion` set to the meson project version — which equals the winget `PackageVersion`, so the patch policy reconciles cleanly. - **No `Publisher` value is written to the registry**, so the default generated exists query (`... AND publisher = 'QEMU Community'`) would never match. The input overrides it with `exists_query: SELECT 1 FROM programs WHERE name = 'QEMU';` — exact name match, so entries like "QEMU guest agent" (virtio-win) are left alone. ## Install/uninstall scripts - NSIS installer, machine scope, x64. Install: standard silent `/S` (same pattern as AnyBurn). - Uninstall: registry lookup by exact DisplayName across both registry views, defensive UninstallString parsing, `/S _?=<installdir>` so the uninstaller runs in place (instead of relaunching from `%TEMP%` and returning immediately), verification that the ARP entry is actually gone, then sweep of the leftover uninstaller/install dir, `HKLM\SOFTWARE\QEMU`, and shortcuts. ## Version caveat winget's newest version dir for this package is **11.0.50 — a QEMU development snapshot** (QEMU uses `x.y.50` for post-release dev builds; only x64, no arm64), added upstream alongside the 11.0.0 stable release. The ingester picks the highest version, so this FMA currently ships the snapshot build; it will move to the next stable (e.g. 11.0.1/11.1.0) as soon as winget has it. The installer URL is date-pinned (`.../2026/qemu-w64-setup-20260501.exe`), so there's no hash-drift risk. If we'd rather not offer dev snapshots, that needs an ingester-level version filter — flagging for maintainer input rather than building it into this PR. ## Icon Official 128×128 QEMU icon from the upstream source tree (`ui/icons/qemu_128x128.png`), generated via `tools/software/icons/generate-icons.sh`. # Checklist for submitter If some of the following don't apply, delete the relevant line. - [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] Verified installer SHA256, registry identity (DisplayName/DisplayVersion/no Publisher), and silent switches against the real installer and upstream `qemu.nsi`/`meson.build` - [ ] `test-fma-windows-pr-only` validates QEMU install/uninstall in this PR's CI <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added QEMU to the Windows software catalog. * Added support for silent QEMU installation and reliable uninstallation. * Added QEMU version detection and upgrade validation. * Added a QEMU icon to the software interface. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
f736356f0e |
Website: update contact form button (#50477)
Changes:
- updated the submit button on the "Talk to us" form ("Talk to an
engineer" » "Pick a time")
- Updated the GitHub webhook to add ~ga4-annotation labels to pull
requests that change the contact page
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Updated the contact form button label to “Pick a time” for clearer
scheduling intent.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
77e090f71b |
Fix broken JSON examples, response docs, and parameter tables in REST API reference (#50457)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> ## Summary While working on a parser for the REST API docs, I found a number of broken spots in the reference. This PR fixes them. They all affect human readers too (invalid JSON in examples, missing response documentation, broken tables). - Fixed invalid JSON in 28 response examples (trailing commas, missing braces, stray tokens, `...` placeholders inside JSON). - Added missing `Default response` documentation to 6 endpoints. Status codes and body shapes were verified against the Go handlers rather than inferred. - Added missing `Status:` lines to 4 response blocks. One is a correction: `Rotate host's Recovery Lock password` was documented as returning `204`, but the server returns `200` (its response struct has no `Status()` override). - Fixed 3 malformed parameter tables (wrong column counts, one missing `In` value). - Restored the standard request line in `Get script result`. - Corrected the dual-key token examples (`abm_tokens`/`ab_tokens`, `teams`/`fleets`): the nested team objects use `team_id` in legacy containers and `fleet_id` in renamed containers on the wire, not bare `id`. # Checklist for submitter If some of the following don't apply, delete the relevant line. - [x] Manual QA for all new/changed functionality ### Test plan - Every JSON example touched by this PR was mechanically validated (valid JSON after stripping `//` comment annotations). - Added response blocks and status codes were checked against the Go handlers (response structs and `Status()` methods). - The full document was run through the parser to confirm every endpoint section now reads cleanly. |
||
|
|
e7a9456044 | Fleet UI: Align toast icon with first line of message (#50449) | ||
|
|
74c2b79f05 |
Website: add support for new usage statistics (#50466)
Changes: - Updated the website to support two new usage statistics sent by Fleet servers: `numHostsFleetMDMEnrolledWindows` and `numHostsFleetMDMEnrolledMacOS` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Usage analytics now track Fleet MDM-enrolled host counts separately for macOS and Windows. * Historical usage records include these platform-specific enrollment totals. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
bbbe93d1b7 |
Bump Zoom Rooms FMA (custom-tap) to 7.1.5.13403 (#50442)
**Related issue:** NA — routine custom-tap cask maintenance # Checklist for submitter - [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] `go test ./ee/maintained-apps/...` passes - [ ] QA'd all new/changed functionality manually (installer metadata, URL, and checksum verified as below; not yet deployed through a Fleet server) No `changes/` file, consistent with prior custom-tap cask-bump PRs (#49563, #48028, #45912). ## Version bump details | | Old | New | |---|---|---| | Version | 7.1.0.13088 | 7.1.5.13403 | - **Upstream source:** `https://zoom.us/client/latest/ZoomRooms.pkg` redirects to `https://cdn.zoom.us/prod/7.1.5.13403/ZoomRooms.pkg` (Zoom does not expose a parseable Zoom Rooms version feed, per the cask's `livecheck` block, so this is the standard manual-bump discovery method). - **New download URL:** `https://cdn.zoom.us/prod/7.1.5.13403/ZoomRooms.pkg` - **sha256:** `3b303bc150a3a5d639f09439abf84f2117784a2124ba660f7c73917ba5ef9ab6` - Downloaded installer verified: 587 MB, `xar archive` (matches expected `.pkg` format). **Reviewer note:** `api/zoom-rooms.json` was updated mechanically because `regenerate.sh` requires macOS. Before merging, run `ee/maintained-apps/inputs/homebrew/custom-tap/regenerate.sh` locally and confirm `git diff` is clean for `api/zoom-rooms.json`. --- _Generated by [Claude Code](https://claude.ai/code/session_01U8YEGYFy9Uc88wvyg96ySE)_ <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Updates** * Updated Zoom Rooms for macOS to version 7.1.5.13403. * Refreshed download links and package verification checksums. * Installation and uninstallation behavior remains unchanged. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
3ea4304126 |
Fix validation on account provisioning page to require secret (#50443)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #50248 Clears the secret field with a clear error, forcing the user to re-enter it, on a URL change, and displays the actual server error strings rather than a generic error(though the server errors are currently largely unreachable via frontend since validation has been tightened up). # Checklist for submitter If some of the following don't apply, delete the relevant line. Unreleased bug so no changes file - [ ] 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 For unreleased bug fixes in a release candidate, one of: - [x] Confirmed that the fix is not expected to adversely impact load test results <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added HTTPS validation for account provisioning token URLs. * Server-side validation errors now appear on the relevant form fields. * Update failures display helpful server-provided error messages. * **Bug Fixes** * Changing a token URL now clears masked secrets and requires the secret to be entered again. * Prevented form submission when required secret re-entry is missing. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
756295aabf | Fleet UI: Button icon padding correction (#50195) | ||
|
|
75db0f1adf | Fleet UI: Fix New user form dropdown layout shift (#50444) | ||
|
|
237a6d3040 | Bump postcss from 8.5.18 to 8.5.23 (#50452) | ||
|
|
183aa052d2 |
Defuse Docker Desktop's install-on-quit updater in macOS FMA install script (#50451)
**Related issue:** Customer reports of failed Docker Desktop updates from self-service on macOS. ## Details The reported error is Docker Desktop's own updater speaking, not Fleet's: ``` failed to back up /Applications/Docker.app before update: renaming (moving) file from /Applications/Docker.app to /Applications/Docker.app.back: rename /Applications/Docker.app /Applications/Docker.app.back: file exists ``` Hosts showing "update available" in self-service are exactly the hosts where Docker Desktop has already downloaded and staged its **own** self-update at `~/Library/Application Support/com.docker.install/in_progress/Docker.app`. When the FMA install script gracefully quits Docker Desktop, that quit triggers Docker's install-on-quit updater, which renames `Docker.app` → `Docker.app.back` and moves the staged copy into place — racing the script's own `mv`/`rm`/`cp` of `/Applications/Docker.app`. The script previously cleaned up after this race (leftover `.back` bundle and staged copy); this PR prevents it instead: - Remove the entire `com.docker.install` staging directory (staged bundle + updater state) **before** quitting the app, so the quit can't trigger Docker's updater. Same whole-directory removal the uninstall's `post_uninstall_scripts` already does. - Wait out (bounded, 30s) any updater already in flight before touching `/Applications/Docker.app`. - Output regenerated via `go run ./cmd/maintained-apps -slug docker-desktop/darwin`; version pinned at 4.85.0, installer URL/sha unchanged, only the install script ref changed. Hosts already wedged with a stale `Docker.app.back` self-heal: the script still removes `.back` before copying the new bundle. ## Local validation (macOS arm64, Docker Desktop 4.84.0 running) - shellcheck and `bash -n` clean; embedded output script matches input byte-for-byte with correct sha256[:8] ref - Downloaded the pinned 4.85.0 DMG; sha256 matches the manifest - Seeded affected-host state (non-empty `/Applications/Docker.app.back`, staged `com.docker.install/in_progress/Docker.app`) and ran the shipped script: staging dir removed before quit, running Docker Desktop (VM + active build) quit gracefully, wait loop did not hang - Wait loop unit-tested against a live process matching `com\.docker\.install`: waits until it exits, 30s cap # Checklist for submitter If some of the following don't apply, delete the relevant line. - [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] QA'd all new/changed functionality manually |
||
|
|
23a1d4746e | Bump brace-expansion from 1.1.16 to 1.1.18 (#50379) | ||
|
|
89acb97395 |
Add NVDA as a Windows Fleet-maintained app (#50450)
**Related issue:** Resolves #50125 Adds NVDA as a Windows Fleet-maintained app, from winget `NVAccess.NVDA` (2026.1.1, NSIS/nullsoft, x86 launcher). ## Identity — read out of the shipped installer, not the manifest I downloaded the 60 MB installer, extracted the NSIS payload, and read the identity fields from `_buildVersion.pyc` and the PE headers. The winget manifest is misleading in two ways: | Field | winget says | Actually is | Source | |---|---|---|---| | Architecture | `x86` | **x64** app behind a 32-bit NSIS launcher stub | `nvda_noUIAccess.exe` / `nvda_slave.exe` PE headers | | Registry DisplayName | PackageName `NVDA` | **`NVDA 2026.1.1`** | `source/installer.py` `getUninstallerRegInfo()`: `DisplayName=f"{name} {version}"` | | Publisher | `NV Access` | `NV Access` (matches) | `_buildVersion.pyc`: `publisher = "NV Access"` | Two consequences: - Because NVDA itself is a **64-bit** process, it registers under the native registry view, **not** `Wow6432Node` (the launcher's 32-bit-ness is irrelevant). Both scripts check both views anyway, for legacy 32-bit copies. - DisplayName carries the version, so this needs `fuzzy_match_name: true` → `name LIKE 'NVDA %'`. Publisher matches the locale manifest, so no `program_publisher` override. `installer_arch` stays `x86` because that's what the manifest declares and the ingester matches on it. ## Version reconciles without a validator exception DisplayVersion is the 4-part `2026.1.1.55980` (`version_detailed`) against winget's `2026.1.1`: - **Validator:** passes via the existing `strings.HasPrefix(result.Version, appVersion+".")` branch in `cmd/maintained-apps/validate/windows.go`. No new skip added — deliberately, since existence-only skips make patch policies always report "patched". - **Patch policy:** `version_compare('2026.1.1.55980', '2026.1.1')` is `> 0`, so an installed copy reads as newer, not outdated. No perpetual false "update available". ## The install script can't trust the exit code `source/gui/installerGui.py` `doInstall()` pops `winUser.MessageBox` / `gui.messageBox` on **every** install failure path with **no `if silent` guard**, and then falls through and exits **0**. Under SYSTEM in session 0 that means: 1. a failure **hangs forever** — nobody can click Retry/Cancel; and 2. if it were dismissed, a failed install would report **success**. So `nvda_install.ps1` uses a watchdog plus an Add/Remove Programs registration poll as the real success signal — the same shape as the existing `azure_data_studio_install.ps1`. Timeouts are 420 + 120 + 30 = 570s, under the caller's 10-minute cap. On timeout it kills only the launcher's `%TEMP%` children (`nvda_noUIAccess` / `nvda_uiAccess`), **deliberately not `nvda.exe`** — an installed NVDA runs as `nvda.exe`, and force-killing it would cut off a signed-in user's screen reader with no warning. ## Uninstall Vendor-documented `/S` (NVDA user guide, "Uninstalling NVDA"), plus `_?=` last so the NSIS uninstaller runs in place instead of relaunching from `%TEMP%` and returning immediately. NVDA writes **no** `QuietUninstallString`, and its `UninstallString` is an **unquoted path containing spaces** (`C:\Program Files\NVDA\uninstall.exe`), so the parser handles that form. The directory comes from NVDA's `InstallDir` value (not `InstallLocation`). Absence of the ARP entry is the success signal, since NVDA removes it via `nvda_slave.exe unregisterInstall`. ## Reviewer notes - **`installer_scope` is `""`, not `"machine"`.** NVDA genuinely installs machine-wide (`%ProgramFiles%\NVDA` + HKLM), but the winget manifest declares no `Scope`, so the ingester derives `""` and `"machine"` panics with "failed to find installer". The one-line ingester fix for this is designed in #48248 but isn't in `main`; I chose not to change shared installer-selection code for a single-app addition. Happy to land that fix here instead if preferred. - **Upgrade caveat:** if NVDA is running for a signed-in user, `--install-silent` refuses to overwrite its own running files by design (`installer.py` `install()`). The script fails with an actionable message rather than force-killing the screen reader. - Installer URL is version-pinned (`download.nvaccess.org/releases/2026.1.1/...`), not a "latest" redirect. SHA verified against my own download of the file. # Checklist for submitter - [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 - [ ] QA'd all new/changed functionality manually `go test ./ee/maintained-apps/...` passes; prettier and `tsc --noEmit` are clean. I have no Windows host or `pwsh`, so **the install/uninstall scripts are unexercised** until FMA validation CI runs them on a Windows runner. No changes file — consistent with other FMA additions (#50415, #50348, #50352). |
||
|
|
301e0e009b |
Improve Windows profile LocURI content validation (#49715)
**Related issue:** Resolves fleetdm/confidential#16881 # 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. - [ ] 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) - [ ] QA'd all new/changed functionality manually For unreleased bug fixes in a release candidate, one of: - [ ] Confirmed that the fix is not expected to adversely impact load test results - [ ] Alerted the release DRI if additional load testing is needed <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved Windows MDM validation for `LocURI`, ensuring full values are considered before checks. * Rejects empty or whitespace-only `LocURI` entries. * Strengthens `LocURI` validation for Fleet-reserved, SCEP-specific, and BitLocker-related formats after complete assembly. * **Tests** * Added new test cases for malformed BitLocker `LocURI` values split across CDATA and XML comment boundaries. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
da36a26f23 |
Update what's new from WWDC 2026 w/ Fleet support + Apple IT summit (#49440)
- So customers, and Fleet's Customer Success team know where Fleet's at with supporting new features in macOS and iOS/iPadOS 27 |
||
|
|
9d0edc592a |
Update Reference-Architectures.md for private network refernce (#50423)
Adds a reference to https://github.com/fleetdm/fleet/pull/50422 when using a proxy to consider the impact of `server_allow_private_network_integration` For #49727 |
||
|
|
388285c168 |
move guardduty to confidential (#49963)
This is to get this more consistent with other internal compliance terraform. While nothing here is problematic, this helps with a more centralized view of the config management. |
||
|
|
05bc7be89e |
Add Windows managed local admin account support to fleetd (#50088)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #48723 # Checklist for submitter If some of the following don't apply, delete the relevant line. - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. - [x] Timeouts are implemented and retries are limited to avoid infinite loops ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually ## 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 do macOS, but should be the same as Linux) - [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 support for Fleet-managed local administrator accounts on Windows. * When enabled, creates or updates a hidden `_fleetadmin` account, securely generates a password, and escrows it to Fleet. * Reports provisioning errors and supports safe retries without blocking other configuration updates. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
05ec868641 |
Website: Update logos on contact page (#50368)
Changes: - Replaced the logo carousel on the contact page with a grid of six logos. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Style** * Updated the contact page to display partner logos in responsive two- and three-column grids. * Improved logo sizing, alignment, spacing, and borders across desktop and mobile screen sizes. * Replaced the previous carousel presentation with a static, more consistent layout. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
51044325e7 |
Treat MSI reboot-required exit codes as success and quote the msiexec log path (#50407)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** NA ## What & why Two independent defects in the default MSI scripts. Neither has any server-side handling, so the script text is the only place either can be fixed. ### 1. Reboot-required exit codes reported as install failures The default MSI install script (`pkg/file/scripts/install_msi.ps1`) ended with `Exit $installProcess.ExitCode`, passing msiexec's raw exit code straight through. An install that **succeeded but requested a reboot** therefore reported as a failed install: - `3010` — `ERROR_SUCCESS_REBOOT_REQUIRED` - `1641` — `ERROR_SUCCESS_REBOOT_INITIATED` Both default MSI *uninstall* scripts (`uninstall_msi.ps1` and `uninstall_msi_with_upgrade_code.ps1`) already carve these out via `$successCodes = @(0, 3010, 1641)` — install was the only MSI script missing it. This change adds the same check, using the identical idiom and comment wording as the uninstall scripts. ### 2. Unquoted log file path in the `/lv` argument The default MSI install and remove scripts passed the log path unquoted: ```powershell -ArgumentList "/quiet /norestart /lv ${logFile} /i `"${env:INSTALLER_PATH}`"" ``` `Start-Process` appends a single-string `-ArgumentList` to the command line verbatim — it adds no quoting of its own. `${env:INSTALLER_PATH}` was already protected by escaped quotes; `${logFile}` was not. So when `TEMP` contains a space, msiexec tokenizes the path on whitespace: `/lv` receives only the chunk up to the first space (`C:\Users\John`), and the remainder (`Smith\AppData\...\fleet-install-software.log`) is left as a stray token, which msiexec rejects as an invalid command line (`1639`). The install fails outright rather than merely writing its log somewhere unexpected. The fix quotes it the way `${env:INSTALLER_PATH}` already was: ```powershell -ArgumentList "/quiet /norestart /lv `"${logFile}`" /i `"${env:INSTALLER_PATH}`"" ``` **On severity:** this is latent under normal fleetd operation. Install scripts inherit `os.Environ()` from orbit (`orbit/pkg/installer/installer.go`), which runs as a LocalSystem service, so `TEMP` is `C:\Windows\TEMP` — no spaces. It bites when the system `TEMP` is redirected to a path containing a space, or when an admin copies the script (Fleet renders it in the UI) and runs it in a user context whose profile name contains a space. Not reproduced on a Windows host; the analysis is from msiexec's whitespace tokenizing, not from an observed failure. The newer hand-written FMA scripts (`mozilla-vpn_install.ps1`, `egnyte_install.ps1`, `vnc-server_install.ps1`, `vnc-viewer_install.ps1`, `agent-ransack_install.ps1`) already used the quoted form. This brings the older ones in line with them. ## Scope `GetInstallScript("msi")` feeds two paths, both fixed by change 1: 1. The default install script for **user-uploaded MSI packages** (`ee/server/service/software_installers.go`). 2. The generated install script for **MSI-based Fleet-maintained apps** (`ee/maintained-apps/ingesters/winget/ingester.go`). Change 2 additionally covers `remove_msi.ps1` (the uninstall script used for packages added before the uninstall feature shipped) and the nine hand-written winget install scripts that still carried the unquoted form: `azure-functions-core-tools`, `bluej`, `crisisgo`, `delinea-connection-manager`, `geogebra-classic`, `google-ads-editor`, `gotomeeting`, `imageglass`, `sourcetree`. Notes: - **FMA outputs are not regenerated here.** `install_script_ref` is content-addressed, and existing `outputs/*/windows.json` files carry both the ref and the script text, so they stay internally consistent. The ingest workflow runs every 4 hours and will roll the refs for MSI-based apps forward on its own. Regenerating them in this PR would produce a huge diff and trigger Windows FMA validation for every MSI app. - Several per-app FMA install scripts exist **only** to add the exit-code carve-out and become redundant once this lands (for example `scribe_install.ps1` from #50341). They are harmless duplicates of the new default and can be removed in follow-up. Per-app scripts that do other work too (e.g. `delinea-connection-manager_install.ps1` forcing `ALLUSERS=1`) still need to keep their own copy — those got the quoting fix instead. - Neither change applies to `uninstall_msi.ps1` or `uninstall_msi_with_upgrade_code.ps1`: they already handle the reboot codes, and they build `-ArgumentList` as an array with no `/lv` argument at all. - `install_exe.ps1` deliberately left alone — EXE installers have no standard exit-code convention, which is why they use per-app scripts. - The per-app example scripts embedded in `articles/` (CrowdStrike, Cloudflare WARP, SentinelOne) are separate copy-paste content and are not touched. # Checklist for submitter - [ ] 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. No changes file is currently in this PR — the earlier one was removed. Both fixes change user-visible install/uninstall outcomes, so one may be warranted before merge. - [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. Change 2 is precisely this: a path interpolated into a command line is now quoted so whitespace can't split it into extra arguments. ## Testing - [x] Added/updated automated tests `pkg/file`'s golden test (`TestGetInstallAndRemoveScript`) covers the script contents; each script and its golden were changed in lockstep, so they remain byte-identical. `go test ./pkg/file/ -run Script` and `go test ./ee/server/service/ -run TestGetInstallScript` pass. Goldens can be regenerated with `go test ./pkg/file/... -update`. - [ ] QA'd all new/changed functionality manually Not QA'd on a Windows host. Change 1 needs an MSI that returns 3010 under Fleet's SYSTEM context to confirm the install now reports success. Change 2 needs an MSI install run with `TEMP` pointed at a path containing a space. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved MSI installation and removal reliability when log-file paths contain spaces. * MSI installations requiring a restart are now recognized as successful. * Standard MSI success and restart-required results are handled consistently while other errors remain available for troubleshooting. * Updated supported application installers to use the more reliable logging behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
5111bd9fb2 |
Update Fleet-maintained apps (#50439)
Automated ingestion of latest Fleet-maintained app data. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Updates** - Updated AdLock to version 2.1.9.2. - Updated AlDente to version 1.38.1. - Updated Cherry Studio to version 1.9.13. - Updated Docker Desktop to version 4.85.0. - Updated Elgato Camera Hub to version 2.3.0.7286. - Updated Firefox Nightly, Granola, and Hubstaff to their latest available macOS releases. - Refreshed download packages, checksums, and version detection for the updated applications. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com> |
||
|
|
4036f9bfcb |
Add Microsoft ODBC Driver 18 for SQL Server as a Windows Fleet-maintained app (#50348)
**Related issue:** Resolves #50327 Adds Microsoft ODBC Driver 18 for SQL Server as a Windows Fleet-maintained app, from winget `Microsoft.msodbcsql.18` (18.6.2.1, MSI, machine scope, x64, en-US). Sibling of #50342 (driver 17); the two install side by side and are separate products. ## Verification Identity read from the MSI Property table: ``` ProductName Microsoft ODBC Driver 18 for SQL Server Manufacturer Microsoft Corporation ProductCode {820A3DEC-9783-42AE-B12D-750FCCF07E10} UpgradeCode {ADA68B65-BFF8-4E6A-B082-CC6682D425B8} ALLUSERS 1 ``` - Installer SHA confirmed against a local download (`20314529…4b82`). - The UpgradeCode differs from driver 17's (`{0123A210-…}`), which confirms they are independent products rather than upgrades of one another. The generated uninstall script picked up 18's, so uninstalling one will not touch the other. - Because `ProductName` already carries the major version, the exists query is a simple equality — no `version LIKE '18.%'` pinning needed, and no risk of 17 and 18 matching each other. Like driver 17, the MSI refuses to install without `IACCEPTMSODBCSQLLICENSETERMS=YES`, which Fleet's default MSI script does not pass, so this ships a small custom install script. It is deliberately a **separate file** from driver 17's rather than a shared path, following the repo's one-script-per-app convention and keeping the two PRs independently mergeable. The icon comes from the MSI's own `ARPPRODUCTICON` stream. As with #50342 it is natively 32×32, so the 128×128 asset is an upscale — happy to drop it in favour of the generic fallback if reviewers prefer. The icon map key also needed the same manual correction (the generator derives it from the slug, which omits "for sql server"). The manifest declares a `Microsoft.VCRedist.2015+.x64` dependency, which the ingester ignores; we ship `vc-redist-x64/windows` and the redistributable is present on most hosts. # Checklist for submitter - [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 Microsoft ODBC Driver 18 for SQL Server to the maintained Windows software catalog. * Added support for version 18.6.2.1, including installation, upgrade, uninstall, detection, and license acceptance handling. * Added the software’s icon and catalog display details. * Included support for SQL Server and Azure SQL connectivity scenarios. * Installation now provides appropriate handling for successful completion, restart requirements, and installation failures. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Allen Houchins <allenhouchins@mac.com> |
||
|
|
3734c28980 |
Update Fleet-maintained apps (#50433)
Automated ingestion of latest Fleet-maintained app data. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Updated available versions and download metadata for 20 maintained applications across macOS and Windows. * Included the latest releases for Antigravity, Postman, Zoom Rooms, NordVPN, Wavebox, and others. * **Bug Fixes** * Improved CrystalDiskMark installation validation and ensured stalled uninstall processes terminate safely. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com> |
||
|
|
a586a53f9a |
Unfreeze Adobe Acrobat Pro (macOS) (#50402)
Automated unfreeze probe. Removes `"frozen": true` and regenerates the output manifest so `test-fma-darwin-pr-only` can validate `adobe-acrobat-pro/darwin` at its current upstream version. Frozen since: 2026-06-23 (#48089, automated FMA update run) Version: 26.001.21691 -> 26.001.21771 Upstream Homebrew reports 26.001.21771, newer than the pinned 26.001.21691 that #50370 set from the delivered installer, so this is a genuine forward bump rather than a regression. The cask uses a stable "latest" download URL with `sha256: no_check`, so the regenerated diff is version and `patched` query only. Draft until validation reports. Merge only if the FMA checks are green and the validate shard actually ran for this slug. <!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** NA # Checklist for submitter - [x] QA'd all new/changed functionality manually — pending CI validation, see above. --- _Generated by [Claude Code](https://claude.ai/code/session_01LvsXk65MD2s93jeGJuHAk5)_ Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
f27f1d9cf9 | Fix Helm chart duplicate FLEET_SERVER_PRIVATE_KEY env entry (#49546) (#49548) | ||
|
|
fd3da2ffeb |
Add VEX exclusions for fleetdm/wix (#50420)
Fixes: https://github.com/fleetdm/fleet/actions/runs/30791953163 New run: https://github.com/fleetdm/fleet/actions/runs/30802123748 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Security** * Added vulnerability assessments for six CVEs. * Documented that the affected products are not impacted because MSI package generation does not establish SSH connections. * Included supporting vulnerability metadata and assessment details for improved security transparency. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
98060b08a6 |
Add Windows managed local account server flow (#48721) (#49924)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #48721 Part 2 of https://github.com/fleetdm/fleet/issues/43488 # Checklist for submitter - [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 ## Database migrations - [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 * **New Features** * Windows devices can now create and securely escrow managed local account passwords during enrollment. * Added Windows managed local account status and password availability to host details. * Device-reported setup errors are surfaced with helpful details. * Account creation is automatically requested when supported by the device, plan, and configuration. * **Bug Fixes** * Windows accounts are excluded from password rotation workflows. * Re-enrollment correctly triggers account creation when needed. * Passwords remain available when settings change after enrollment. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
a4d058384c |
Add CrystalDiskMark as a Windows FMA (#50415)
**Related issue:** Resolves #50322 Adds CrystalDiskMark as a Windows Fleet-maintained app, from winget `CrystalDewWorld.CrystalDiskMark` (9.0.3, Inno Setup, machine scope, x64). Found in a customer's ManageEngine ServiceDesk Plus Windows deployment catalog with no Fleet equivalent. ## Identity — read out of the Inno header, not the manifest The winget manifest carries no `AppsAndFeaturesEntries`, so the ARP identity had to come from the installer itself. I LZMA-decompressed the Inno setup-data block and read the header directly: | Header field | Value | |---|---| | `AppName` | `CrystalDiskMark` | | `AppVerName` | `CrystalDiskMark 9.0.3` | | `AppVersion` | `9.0.3` | | `AppPublisher` | `Crystal Dew World` | | `AppId` | `CrystalDiskMark9` | | `UninstallDisplayName` | *(empty)* | | `DefaultDirName` | `{pf}\CrystalDiskMark9` | With `UninstallDisplayName` empty, Inno falls back to `AppVerName` for the ARP `DisplayName` — so this registers as **`CrystalDiskMark 9.0.3`**, version-suffixed, and the exists query is a prefix match (`fuzzy_match_name: true`). That the name is version-suffixed isn't inferred from "Inno usually does this." The Aoi edition's header sets `AppVerName` to `CrystalDiskMark 9.0.3 Aoi Edition` while its `AppName` is `CrystalDiskMark Aoi Edition` — the compiler's synthesized default would have been `CrystalDiskMark Aoi Edition 9.0.3`, so the script is setting `AppVerName` deliberately, and Setup will write exactly that string. `AppPublisher` matches the winget locale `Publisher` verbatim, so no `program_publisher` override is needed, and `DisplayVersion` is `AppVersion` = `9.0.3`, which reconciles with the FMA version with no validator exception. Generated query: ```sql SELECT 1 FROM programs WHERE name LIKE 'CrystalDiskMark %' AND publisher = 'Crystal Dew World'; ``` ## Silent flags — the `[Run]` entries were decoded, not assumed The header contains three `[Run]` entries with `{cm:LaunchProgram,CrystalDiskMark9}` descriptions (one per architecture), which is exactly the shape that has hung silent Inno installs for us before. I parsed the entry structure through to the flag bytes: - wait enum = `1` → `nowait` - flags = `0x14` → bit 2 `postinstall` + bit 4 `skipifsilent` So `/VERYSILENT /SUPPRESSMSGBOXES /NORESTART` will not launch the GUI, and there is no post-install hang to work around. The install script still uses the poll-and-kill wrapper rather than `-Wait`, plus an ARP-registration wait, since the installer can return before the registry entry lands. `/ALLUSERS` is deliberately omitted: `DefaultDirName` is `{pf}`, which requires admin install mode already, so the switch would be a no-op. ## Uninstall `UninstallString` is Inno's quoted `unins000.exe` path, but the script uses the three-branch defensive parser (quoted / unquoted-with-spaces / bare token) anyway. Two app-specific bits: - The 12 `DiskMark*.exe` binaries are stopped first — the uninstaller won't proceed while the `CrystalDiskMark9` mutex is held. - The script waits for the registry entry to disappear rather than trusting the exit code. Inno's uninstaller relaunches itself from a temp copy and the original process returns early, so its exit code is not a completion signal. ## Icon The setup exe's `MAINICON` is Inno's stock CD-and-box artwork, not the app's, so the icon was extracted from `DiskMark64.exe`'s own resources (`innoextract` → `wrestool -t 14 -n 130` → `icotool`, 256×256 32-bit). ## Two things for reviewers 1. **This carries a shared-code change to the winget ingester** (`normalizeSourceForgeURL`). A bare SourceForge project file URL serves non-browser clients a 133KB HTML landing page with a 200, so the first validator run downloaded that instead of the installer and failed on the hash. Only the `.../download` form serves the binary. WinSCP works today only because its manifest happens to carry the suffix, so the fix normalizes in the ingester rather than depending on manifest authors. WinSCP regenerates byte-identical and is the only other SourceForge-hosted app in the catalog; `TestNormalizeSourceForgeURL` covers both shapes. Details in [this comment](https://github.com/fleetdm/fleet/pull/50415#issuecomment-5162501140). 2. **The Aoi and Shizuku editions share this package's `AppId` and install directory.** They occupy the same ARP slot (`CrystalDiskMark9_is1`), can't be co-installed, and will match the exists query as `CrystalDiskMark 9.0.3 <Edition>`. I treated that as correct rather than something to exclude — it is the same product at the same version — but flagging it in case we'd rather pin to the plain edition. ## Verification - Inno header dumped offline; `AppVerName` / `AppPublisher` / `AppVersion` read directly, `[Run]` flag bytes decoded. - Generated SHA matches the winget installer manifest (`1a255154…917e5e`), and the download was verified through the exact code path the validator uses (`maintained_apps.DownloadInstaller` with `http.DefaultClient`) — 4,523,144 bytes, hash matches. - `apps.json` valid, description filled, icon generated and inserted alphabetically in `index.ts` under the key `crystaldiskmark`. - `go test ./ee/maintained-apps/...` passes; `GOOS=windows go build ./cmd/maintained-apps/validate/` builds; `gofmt`/`go vet` clean. `make lint-go-incremental` could not run in my environment (`custom-gcl` fails to clone golangci-lint, pre-existing and unrelated). - First validator run failed on the download issue above and is fixed; the full validator pass (install → detect → uninstall on a Windows host) still needs to go green before this leaves draft. # Checklist for submitter - [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 - [ ] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added CrystalDiskMark as a supported Windows application, including installation, uninstallation, detection, categorization, and software catalog details. * Added CrystalDiskMark branding to the software interface. * Improved SourceForge installer URL handling by automatically appending download paths when needed. * **Bug Fixes** * Preserved existing download URLs, query parameters, and unsupported or malformed URLs during normalization. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> |
||
|
|
e86fa44965 | Show button if there's only one action, instead of an actions dropdown (#48337) | ||
|
|
1dc1a51313 |
Fix Windows Git FMA patch policy never detecting outdated installs (#50424)
**Related issue:** Resolves #50283 Git for Windows registers itself in the Windows uninstall registry as exactly `Git` — its Inno Setup script has set `UninstallDisplayName={#APP_NAME}` since [build-extra#365](https://github.com/git-for-windows/build-extra/pull/365) (2021). The generated queries matched `programs.name LIKE 'Git %'`, which cannot match that name, so the patch policy's `NOT EXISTS (...)` was always true and every host reported `Pass` regardless of installed version — update automations never fired. The same mismatch meant an existing Git install couldn't be matched to the maintained app. The input now uses the custom fuzzy pattern `Git%`, which also covers the pre-2021 `Git <version>` DisplayName form (the oldest installs, which are exactly what a patch policy needs to flag), and relies on the existing `publisher = 'The Git Development Community'` guard to exclude GitHub Desktop, Git LFS, GitKraken and Git Extensions. This is the same match the app's own uninstall script and the FMA Windows CI workflow already use. Instances that already created this policy pick up the corrected query when the next Git version becomes active, since the patch policy query is regenerated from the active installer. # Checklist for submitter - [x] Changes file added for user-visible changes in `changes/`. ## Testing Verified the `LIKE` semantics in SQLite against real-world `programs` rows (old pattern misses `Git`, new pattern matches both DisplayName forms, publisher guard still excludes GitHub Desktop / Git LFS / GitKraken / Git Extensions), and confirmed winget's `PackageVersion` matches the registry `DisplayVersion` for Git so up-to-date hosts still pass. `outputs/git/windows.json` was regenerated with the ingester rather than hand-edited. Not manually QA'd on a Windows host — relying on `test-fma-windows` validation. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved Git for Windows detection across supported environments. * Outdated installations can now be correctly identified and included in update automation, including registrations named “Git.” * Existing publisher and version checks remain unchanged. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
f37e78f2f3 |
Edit image caption in Linux inventory article (#50429)
Removed unnecessary text from the image caption in the article. <!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves # # Checklist for submitter If some of the following don't apply, delete the relevant line. - [ ] 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 - [ ] 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) - [ ] QA'd all new/changed functionality manually For unreleased bug fixes in a release candidate, one of: - [ ] Confirmed that the fix is not expected to adversely impact load test results - [ ] Alerted the release DRI if additional load testing is needed ## Database migrations - [ ] Checked schema for all modified table for columns that will auto-update timestamps during migration. - [ ] Confirmed that updating the timestamps is acceptable, and will not cause unwanted side effects. - [ ] Ensured the correct collation is explicitly set for character columns (`COLLATE utf8mb4_unicode_ci`). ## New Fleet configuration settings - [ ] Setting(s) is/are explicitly excluded from GitOps If you didn't check the box above, follow this checklist for GitOps-enabled settings: - [ ] Verified that the setting is exported via `fleetctl generate-gitops` - [ ] Verified the setting is documented in a separate PR to [the GitOps documentation](https://github.com/fleetdm/fleet/blob/main/docs/Configuration/yaml-files.md#L485) - [ ] Verified that the setting is cleared on the server if it is not supplied in a YAML file (or that it is documented as being optional) - [ ] Verified that any relevant UI is disabled when GitOps mode is enabled ## fleetd/orbit/Fleet Desktop - [ ] 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)) - [ ] If the change applies to only one platform, confirmed that `runtime.GOOS` is used as needed to isolate changes - [ ] Verified that fleetd runs on macOS, Linux and Windows - [ ] Verified auto-update works from the released version of component to the new version (see [tools/tuf/test](../tools/tuf/test/README.md)) |
||
|
|
e83c2689f5 |
CIS Benchmarks: Update macOS benchmarks
Resolves #45644 Bring the macOS CIS benchmark policies up to the current CIS releases: - macOS 14 Sonoma: v3.0.0 -> v3.1.0 - macOS 15 Sequoia: v2.0.0 -> v2.1.0 - macOS 26 Tahoe: v1.0.0 -> v1.1.0 Policy changes: - 2.7.1: rescope the screen saver hot corners check to the current console user and move it to Level 1, per the updated CIS audit. - 3.4: relax audit log retention to >= 30 days (no size requirement); parse the day value anchored to `expire-after:` so a mixed directive such as `7d OR 30d` is correctly rejected. - 5.1.7: exclude the non-accessible /Library/AppStore directory and its descendants from the world-writable Library check. - 5.6: update for the new secure-token audit (verify root has no AuthenticationAuthority). - 5.3.1: add the internal APFS volume encryption check (Manual -> Automated) on macOS 26; remove the deprecated CoreStorage 5.3.2 check on macOS 14/15. - 2.10.1: correct the screen saver inactivity threshold to <= 900s (15 minutes) to match the CIS audit. Limitations documented (no reliable fleetd data source): - 5.3.2 (external APFS/HFS+ encryption): apfs_volumes exposes no internal/external indicator. - 5.3.3 (FAT32/ExFAT): CIS Manual audit. |
||
|
|
6c3de12f69 |
Base Orbit enrollment end user auth on server policy
EnrollOrbit now determines end user authentication requirements from
server policy rather than the client-supplied X-Fleet-Capabilities
header, which is treated as an informational hint.
Adds the mdm.allow_orbit_end_user_auth_bypass setting (enabled by
default) controlling whether hosts that do not complete end user
authentication may enroll into a team that requires it; set it to false
to strictly enforce end user auth. The setting also governs installers
built with fleetctl package --bypass-end-user-auth.
|
||
|
|
7abc0f6e7f |
Add article: Linux crossed 10% in North America, and your inventory might have missed it (#50412)
**Related issue:** NA New thought-leadership article pegged to Statcounter's July 2026 data showing Linux desktop share at 10.65% in North America. The angle is deliberately honest rather than triumphant: most of the month-over-month jump came from Statcounter reclassifying an "Unknown" traffic bucket, not from a mass migration. That measurement problem is the bridge into Fleet's argument, since the same blind spot that hid Linux from web analytics hides Linux hosts from asset inventories that discover devices through Apple and Windows enrollment channels. Includes a Cloudflare Radar chart as a second, independent data source. Cloudflare puts North American Linux desktop requests at 6.3% over the trailing year, well below Statcounter's figure, but both show a step change in the same weeks. The disagreement between the two sources reinforces the article's point that Linux is hard to count from the outside. Intended for use in ads and other traffic-driving placements. Notes for reviewers: - Capability claims (LUKS2 enforcement on Ubuntu/Kubuntu/Fedora with escrowed recovery keys, `.deb`/`.rpm`/`.tar.gz` and script-only packages, vulnerability detection including CISA KEV, remote script execution, remote lock and wipe, self-service, supported distro list) are grounded against `website/views/pages/linux-management.ejs`. Please confirm they are still accurate. - The article states that encryption enforcement covers a narrower set of distributions than the overall support list, which is intentional. - Statcounter figures are cited via Linuxiac; a Sources section attributes both Statcounter and Cloudflare Radar, and the chart carries inline attribution and a capture date. - `publishedOn` is set to `2026-08-02`. Bump if this merges later. - Byline is set to Allen Houchins. # Checklist for submitter - [ ] Content reviewed for Fleet voice and style (`content-style`) and article format (`fleet-article-formatting`) - [ ] Capability claims verified against the Linux management page and docs - [ ] Source attribution confirmed for Statcounter, Linuxiac, and Cloudflare Radar - [ ] Article renders correctly on the website, including the chart image |
||
|
|
86f4619faf |
Add Microsoft ODBC Driver 17 for SQL Server as a Windows FMA (#50342)
**Related issue:** Resolves #50326 Adds Microsoft ODBC Driver 17 for SQL Server as a Windows Fleet-maintained app, from winget `Microsoft.msodbcsql.17` (17.11.1.1, MSI, machine scope, x64, en-US). Found in a customer's ManageEngine ServiceDesk Plus Windows deployment catalog with no Fleet equivalent. ## The install would fail without a custom script The MSI refuses to install unless `IACCEPTMSODBCSQLLICENSETERMS=YES` is passed. This is not just a winget convention — the MSI carries the condition and the matching error string: ``` IACCEPTMSODBCSQLLICENSETERMS ~= IACCEPTMSODBCSQLLICENSETERMS=YES command-line parameter is missing. ``` Fleet's default MSI install script passes only `/quiet /norestart /i`, so without the small custom script in this PR every install would fail. Uninstall is still the auto-generated upgrade-code script, which is correct as-is. ## Verification Identity read from the MSI Property table: ``` ProductName Microsoft ODBC Driver 17 for SQL Server Manufacturer Microsoft Corporation ProductCode {ACBA503E-64A9-4A8A-A6CC-63656F395618} UpgradeCode {0123A210-9B73-46E7-B5CE-7F33630300E7} ALLUSERS 1 ``` - Installer SHA confirmed against a local download (`0f642870…bd4e`). - `ALLUSERS=1` means it always installs per-machine. - The generated uninstall script correctly picked up the **x64** UpgradeCode — note the x86 build uses a different one, so an arch mix-up here would silently fail to uninstall. **No version pinning is needed in the exists query.** When I scoped this I expected to need `AND version LIKE '17.%'` the way the Amazon Corretto FMAs do, but the `ProductName` already carries the major version, so `Microsoft ODBC Driver 17 for SQL Server` and `...18...` are naturally distinct entries. Simple equality is correct and unambiguous. ## Two notes for reviewers **Icon quality.** The MSI's `ARPPRODUCTICON` stream tops out at 32×32, so the 128×128 asset here is an upscale and looks soft. It is the authentic Add/Remove Programs icon, but if we would rather fall back to the generic software icon than ship a blurry one, drop the icon files and I will regenerate without them. **Icon map key needed a manual fix.** The generator derives its key from the slug and produced `"microsoft odbc driver 17"`, but lookups use the lowercased catalog name — `"microsoft odbc driver 17 for sql server"`. Corrected by hand. Same generator gap hit Paint.NET in #50340. **Dependency.** The manifest declares `Microsoft.VCRedist.2015+.x64`. The ingester ignores winget `Dependencies`, but unlike HandBrake (#50323) we do ship a matching FMA (`vc-redist-x64/windows`), and the redistributable is present on most Windows hosts already. Noting it rather than treating it as a blocker. # Checklist for submitter - [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 Microsoft ODBC Driver 17 for SQL Server to the maintained software catalog. * Added Windows installation and upgrade support for version 17.11.1.1. * Added the software’s icon and catalog display details. * Included silent installation, logging, license acceptance, and reboot handling. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
407db89ff5 |
Update Fleet-maintained apps (#50411)
Automated ingestion of latest Fleet-maintained app data. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Improved macOS uninstall cleanup for Dockside, ExifCleaner, Franz, LinearMouse, Safe Exam Browser, Smultron, Stats, Teleport Connect, and Zappy. - Uninstallation now removes additional app support files, caches, preferences, recent-document data, containers, logs, and related settings. - **Updates** - Updated Firefox Nightly to a newer macOS build. - Updated NetNewsWire from version 7.1.1 to 7.1.2 with refreshed download verification. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com> |
||
|
|
332d8a2cee |
Add Microsoft Access Database Engine 2016 Redistributable as a Windows Fleet-maintained app (#50365)
**Related issue:** Resolves #50325 Adds Microsoft Access Database Engine 2016 Redistributable as a Windows Fleet-maintained app, from winget `Microsoft.AccessDatabaseEngine2016` (16.0.5044.1000, x64). Found in a customer's Windows deployment catalog with no Fleet equivalent. ## No ingester change was needed after all When I scoped this I expected to need a one-line change, because winget types the installer as `portable`, which is not in the ingester's `vendorTypes` or `fileTypes`. I tested it first: `"installer_type": "portable"` with an empty scope matches cleanly, and since the generated output carries no installer type (Fleet infers `.exe` from the URL), the result is correct as-is. This is the first FMA input to use `portable`. If reviewers would rather not establish that precedent, adding `portable` alongside `wix`/`nullsoft`/`inno` in `vendorTypes` would let the type fall through to the URL extension and the input could then say `exe`. Both work. I chose the one that touches no shared code. ## Identity: winget's name is wrong twice over winget's locale manifest says `Microsoft Access Database Engine 2016 Redistributable`. The MSI says: ``` ProductName Microsoft Access database engine 2016 (English) Manufacturer Microsoft Corporation ProductCode {90160000-00D1-0409-1000-0000000FF1CE} UpgradeCode {00160000-00D1-0000-1000-0000000FF1CE} ALLUSERS 1 ``` Two traps: the real name is lowercase `database engine`, and it carries an `(English)` locale suffix with the LCID (`0409`) embedded in the ProductCode. osquery's `=` on TEXT is case-sensitive, so the winget-derived name would have matched nothing. ## x64 only, deliberately The customer deploys both architectures, but **x86 and x64 register the identical DisplayName**. I confirmed this by extracting both installers: | Arch | ProductName | UpgradeCode | |---|---|---| | x64 | `Microsoft Access database engine 2016 (English)` | `{00160000-00D1-0000-1000-0000000FF1CE}` | | x86 | `Microsoft Access database engine 2016 (English)` | `{00160000-00D1-0000-0000-0000000FF1CE}` | They differ only by product and upgrade code. Two FMAs could not be told apart by an exists query, so installing one would make the other report itself installed. Shipping x64 only avoids that. This also corrects my earlier note on the issue suggesting the architecture go in the catalog name; that would distinguish the catalog entries but not the detection queries, so it would not have helped. The uninstall script resolves the product from the x64 upgrade code rather than a product code, so it removes the x64 build and leaves an x86 install alone. ## The Office conflict is handled, not hidden This redistributable refuses to install when Office of the opposite bitness is present. Following the same approach @allenhouchins set out for HandBrake in #50323, the install script checks the Click-to-Run platform first and exits with an actionable message instead of a bare installer failure: ``` 32-bit Microsoft Office is installed on this host (Click-to-Run platform: x86). The 64-bit Access Database Engine cannot be installed alongside it. Use the 32-bit redistributable instead. ``` **A green validator here proves less than usual.** The CI runner has no Office installed, so it exercises the happy path only. The conflict this app is known for cannot be reproduced there. That is a limitation of the environment, not evidence the app is safe on managed hosts, and it is the main thing worth weighing before merging. ## Other notes - Installer SHA confirmed against a local download of `accessdatabaseengine_X64.exe` (`04e96c9f…03de`). - The download is a self-extracting package. Its `setup.cmd` runs `InstallUCRT.exe` and then `msiexec %1 /i AceRedist.msi`, which is why `/quiet` reaches the MSI. - **No icon.** The MSI has no `ARPPRODUCTICON` and no Icon table, so there is nothing to extract. The app falls back to the generic software icon, which suits a redistributable with no user-facing app. # Checklist for submitter - [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 Microsoft Access Database Engine 2016 Redistributable as a supported Windows application. * Added silent installation and uninstallation workflows with architecture checks, registration detection, timeout handling, and standard success-code support. * Included package metadata, version information, download verification, Developer tools categorization, and reliable installation-state detection. * Added handling for existing installations and validated installer outcomes. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Allen Houchins <allenhouchins@mac.com> |
||
|
|
5fa8a0a9ea |
Add Microsoft .NET Desktop Runtime 10 as a Windows FMA (#50361)
**Related issue:** Resolves #50360 Adds Microsoft .NET Desktop Runtime 10 as a Windows Fleet-maintained app, from winget `Microsoft.DotNet.DesktopRuntime.10` (10.0.10, WiX burn bundle, x64). This closes the gap opened by HandBrake (#50323 / #50352). HandBrake requires the .NET **Desktop** Runtime and its install script now hard-fails without it, but Fleet had no FMA that could satisfy that — we ship `microsoft-dotnet-runtime-8`/`-10`, which are the *base* runtime, a different package with its own Add/Remove Programs entry. The customer's ManageEngine catalog also deploys the Desktop Runtime directly. ## Verification The winget manifest supplies `AppsAndFeaturesEntries`, and I confirmed each value against the real installer by extracting the burn bundle's registration data: ``` Microsoft Windows Desktop Runtime 10.0.10 (x64) Publisher="Microsoft Corporation" Version="10.0.10.50000" ``` - Installer SHA confirmed against a local download (`e82fc901…84d1`). - The `DisplayName` carries both version and architecture, so the exists query uses the same `LIKE 'Microsoft Windows Desktop Runtime 10.%' AND name LIKE '%(x64)'` shape as the existing base-runtime FMAs. - The bundle exposes several ProductCodes (the bundle plus its MSI components), which is exactly the shape the existing uninstall script already documents and handles. **`use_display_version_for_patch` is required here.** The registry `DisplayVersion` is `10.0.10.50000` but the winget package version is `10.0.10`. Without the flag the patch policy would compare against the marketing version and mis-order against what osquery reports. The generated patched query correctly compares against `10.0.10.50000`. ## Reuse rather than duplication - **Scripts:** this reuses `microsoft_dotnet_runtime_install.ps1` / `_uninstall.ps1` unchanged. The Desktop Runtime is the same burn bundle shape, and the uninstaller already resolves the bundle from the injected `$PACKAGE_ID` with a Package Cache fallback. Those scripts are already shared by the two base-runtime FMAs, so this follows the existing pattern rather than adding a near-identical copy. - **Icon:** reuses the existing `MicrosoftDotnetRuntime` component and its `.NET` artwork. The burn bundle only carries a 32×32 icon, so extracting one would have meant shipping a blurry upscale of the same logo. The new map key is `"microsoft .net desktop runtime"` (no version). Icon lookup is a loose *prefix* match — `s === key || s.startsWith(key + " ")` — so one key covers 10 and any future major, mirroring how `"microsoft .net runtime"` already serves both base-runtime FMAs. It is longer than that key, and lookup sorts longest-first, so the desktop runtime cannot be mis-matched to the base runtime icon. # Checklist for submitter - [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 Microsoft .NET Desktop Runtime 10 to the Windows software catalog. * Added support for installing and uninstalling the x64 desktop runtime, including version detection and reboot handling. * Added a dedicated Microsoft .NET Runtime icon for the software listing. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
b35904ccfa |
Add HandBrake as a Windows FMA (#50352)
**Related issue:** Resolves #50323 Adds HandBrake as a Windows Fleet-maintained app, from winget `HandBrake.HandBrake` (1.11.2, NSIS, machine scope, x64). Found in a customer's ManageEngine ServiceDesk Plus Windows deployment catalog with no Fleet equivalent. Per @allenhouchins' guidance on the issue, the `.NET Desktop Runtime 10` prerequisite is handled in the install script with a clear failure message rather than left to fail silently after install. ## The prerequisite check HandBrake's own installer text states it plainly: > HandBrake requires Microsoft .NET *Desktop* Runtime 10. If this is not installed, you will be prompted to install it when you first run the app. The installer neither bundles nor installs that runtime, and the FMA ingester drops winget's `Dependencies` field. Without a check, Fleet would install HandBrake, register it in Add/Remove Programs, report success, and the user would hit a runtime prompt on first launch. The script now checks `%ProgramFiles%\dotnet\shared\Microsoft.WindowsDesktop.App\10.*` and exits 1 with an actionable message when it is absent. Two things worth reviewers' judgement: - **We fail rather than warn.** The vendor does prompt the user at first run, so an install without the runtime is recoverable by hand. I chose to fail because in a SYSTEM-context managed deployment an end-user runtime prompt is a support ticket, and a truthful "install failed, here is why" is more useful than a silently unusable app. Easy to soften to a warning + `Exit 0` if we would rather defer to the vendor's prompt. - **We ship no `.NET Desktop Runtime` FMA today.** Fleet has `microsoft-dotnet-runtime-8`/`-10`, but those are the *base* runtime, not the Desktop runtime — a separate package with its own ARP entry. So there is currently no in-product way to satisfy this prerequisite; an admin has to deploy the runtime by other means. That gap is worth its own issue. ## Identity — two traps, both from reading the vendor's NSIS script HandBrake's [`Installer64.nsi`](https://github.com/HandBrake/HandBrake/blob/master/win/CS/HandBrake.Nsis.Installer/Installer64.nsi) writes only four values: ```nsis Name "${PRODUCT_NAME} ${PRODUCT_VERSION}" ... WriteRegStr HKLM "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)" WriteRegStr HKLM "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe" WriteRegStr HKLM "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\HandBrake.exe" WriteRegStr HKLM "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}" ``` 1. **`DisplayName` is version-suffixed** (`HandBrake 1.11.2`), so the exists query is a prefix match, not equality. 2. **No `Publisher` is ever written.** The default generated query would have pinned `publisher = 'The HandBrake Team'` from the winget locale manifest and matched nothing, forever, while the validator still passed. The exists query is overridden to drop the publisher clause. `UninstallString` is also an unquoted path containing spaces (`C:\Program Files\HandBrake\uninst.exe`), which the defensive parser in the uninstall script handles by capturing through `.exe`. The uninstall script additionally waits for the registry entry to disappear: a silent NSIS uninstaller returns before removal completes, so its exit code alone is not a reliable completion signal. ## Verification - Installer SHA confirmed against a local download (`6becb8e5…f8cd`); the URL is GitHub Releases, so none of the SourceForge trouble from #50322 applies. - **No icon work needed.** Reusing the catalog name `HandBrake` means this shares the existing `handbrake` icon with `handbrake-app/darwin`, and the two group together in the FMA library. # Checklist for submitter - [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 HandBrake 1.11.2 to the Windows maintained applications catalog. * Added support for silent installation and uninstallation, including version detection and installer verification. * Added validation for the required .NET Desktop Runtime 10 prerequisite. * Added handling for installation completion, reboot-required results, and uninstall status reporting. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
194df72c90 |
Add Scribe as a Windows Fleet-maintained app (#50341)
**Related issue:** Resolves #50331 Adds Scribe as a Windows Fleet-maintained app, from winget `ColonyLabs.ScribeDesktopCapture` (6.7.23.0, MSI, machine scope, x64). Found in a customer's ManageEngine ServiceDesk Plus Windows deployment catalog with no Fleet equivalent. The simplest of this batch: a plain machine-scope MSI, so the install and upgrade-code uninstall scripts are auto-generated and no custom scripts are needed. ## Verification Identity read directly from the MSI Property table rather than inferred from winget: ``` ProductName Scribe Manufacturer Colony Labs, Inc ProductCode {87a51b1f-554d-414d-92a4-002a0916c91c} UpgradeCode {351EF756-3AF5-4117-8697-53AB61427040} ALLUSERS 2 ``` `Manufacturer` matches the winget locale `Publisher` exactly, so no `program_publisher` override is needed. `ALLUSERS=2` confirms per-machine install when elevated, which is how Fleet runs it. No `ARPSYSTEMCOMPONENT`, so this is a real product entry and not a bootstrapper. - Installer SHA confirmed against a local download of `Scribe_6.7.23.msi` (`41004c21…9b74`). - Icon extracted from the MSI's own `Scribe for Windows.exe` resource, not sourced from the web. ## Note on the name `Scribe` is a generic `DisplayName`, so the exists query pins `publisher = 'Colony Labs, Inc'` to avoid matching an unrelated product of the same name. This is **not** related to `timescribe/darwin`, which is already in the catalog — different vendor, different product. It deliberately does not share that catalog name or icon. # Checklist for submitter - [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 Scribe to the maintained applications catalog for Windows. * Added support for installing and uninstalling Scribe MSI packages, including version detection and installer metadata. * Added reliable installation handling with logging, elevated execution, restart control, and support for standard successful installer exit codes. * Added the Scribe app icon to the software interface. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Allen Houchins <allenhouchins@mac.com> |
||
|
|
da1947cd1f |
Add Paint.NET as a Windows Fleet-maintained app (#50340)
**Related issue:** Resolves #50330 Adds Paint.NET as a Windows Fleet-maintained app, from winget `dotPDN.PaintDotNet` (5.1.12, machine scope, x64). Found in a customer's ManageEngine ServiceDesk Plus Windows deployment catalog with no Fleet equivalent. ## Identity: winget's metadata is wrong here The winget locale manifest gives `PackageName: paint.net` (lowercase). The actual registry `DisplayName` is **`Paint.NET`**, read straight out of the MSI Property table: ``` ProductName Paint.NET Manufacturer dotPDN LLC UpgradeCode {04A40F40-A207-4B48-AED7-6AA532E43275} ALLUSERS 2 ``` There is no `ARPDISPLAYNAME` override and no `ARPSYSTEMCOMPONENT`, so `ProductName` is what lands in Add/Remove Programs. Taking the winget name at face value would have produced an exists query that silently never matches. `ALLUSERS=2` confirms it installs per-machine when run elevated, which is how Fleet runs it. ## This is a zip-wrapped installer Paint.NET publishes **only** `.zip` assets — there is no bare `.exe` or `.msi` on the vendor's GitHub releases. So this uses `installer_type: zip` with custom scripts, following the existing precedent of `agent-ransack`, `adobe-acrobat-pro`, `vnc-server`, and `vnc-viewer`. The install script extracts the archive and runs the nested installer with `/auto`, the vendor's silent switch per the manifest's `InstallerSwitches`. **Uninstall resolves the product from the UpgradeCode, not the ProductCode.** Paint.NET's ProductCode changes with every release, and the `.exe` and `.msi` variants register *different* ProductCodes. The UpgradeCode is stable — I verified it is identical across 5.1.10 and 5.1.12 — so `RelatedProducts` on it removes whichever variant is present. ## One thing reviewers may want to change The manifest offers six installers; three are x64/machine/zip and differ only by `NestedInstallerType` (`exe`, `wix`, `portable`). The ingester's selection loop takes the **first** match and breaks, so it picks the `.install.x64.exe` bootstrapper. The `.winmsi.x64.zip` variant is arguably the better FMA target — a plain MSI with predictable ARP behaviour — but there is no way to express "prefer this nested type" in the input today. Selecting it would need an ingester change, so I did not do it here. Worth a follow-up if we hit trouble with the bootstrapper. ## Verification - Zip SHA confirmed against a local download (`3cd861b5…c867`); archive contains exactly one file, `paint.net.5.1.12.install.x64.exe`. - Icon extracted from that installer's own 256px resource, not sourced from the web. - Icon map key is `"paint.net"`, the lowercased catalog name. The icon generator derives its key from the slug and produced `"paint dot net"`, which would never have matched at runtime — corrected by hand. # Checklist for submitter - [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 Paint.NET to the Windows software catalog. * Added support for installing, upgrading, detecting, and uninstalling Paint.NET. * Added Paint.NET branding and an icon to the software interface. * Included Paint.NET version 5.1.12 with verified download metadata and Productivity categorization. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Allen Houchins <allenhouchins@mac.com> |
||
|
|
2833401d12 |
Add Dante Controller as a macOS FMA (#50378)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #50377 # What this does Adds **Dante Controller** as a macOS Fleet-maintained app, from Homebrew cask [`dante-controller`](https://formulae.brew.sh/cask/dante-controller) (4.18.1.1). The cask ships a DMG containing `DanteController.pkg`, so `installer_format: "dmg"` with the standard mount-and-`installer -pkg` install script — the same shape as AdGuard, Adobe Acrobat Pro, and other existing DMG+pkg FMAs. Uninstall is fully generated from the cask's directives (2 `launchctl` services, 8 `pkgutil` receipt IDs, 3 zap trash paths) — no custom scripts. Windows is out of scope: no `Audinate.DanteController` winget package exists. See #50377 for the full feasibility analysis, including why Dante Virtual Soundcard was excluded on both platforms. ## Notes - **Identity verified against the real installer**, not cask metadata. Extracted `DanteController.pkg` from the DMG and read the app bundle's `Info.plist`: `CFBundleIdentifier` = `com.audinate.dante.DanteController`, confirming the input's `unique_identifier`. This needed checking because the cask's preferences path uses a *different* domain (`com.audinate.dante.controller`). - `CFBundleShortVersionString` and `CFBundleVersion` are both `4.18.1.1`, matching the cask version, so the exists/patched queries reconcile with osquery's `apps` table. - Installer SHA confirmed against a local download of the DMG (`4515cd12…38ff`) — matches both the cask and the generated output. - **Arch split.** The cask ships separate arm64/x64 DMGs; the brew API's top-level URL (which the ingester pins) is the arm64 build. This matches the behavior of the ~173 existing darwin FMAs with arch-specific URLs. - **`auto_updates true`.** Dante Updater self-patches, so hosts may drift ahead of the FMA-pinned version. - Ships a new catalog icon, extracted from the app bundle's own `.icns` — not sourced from the web. # Checklist for submitter - [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] FMA CI validator (install → detect → uninstall) **passes** on the macOS runner — [run 30682752130](https://github.com/fleetdm/fleet/actions/runs/30682752130/job/91322957939) (`Found app: 'Dante Controller' at /Applications/Dante Controller.app, Version: 4.18.1.1` → `All 1 apps were successfully validated.`) - [x] Generated output verified locally: installer SHA matches the cask, exists/patched queries checked against the app bundle's `Info.plist`, `apps.json` is valid JSON with a description filled in. - [x] QA'd all new/changed functionality manually --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
31e3f51fa4 |
Update Fleet-maintained apps (#50406)
Automated ingestion of latest Fleet-maintained app data. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Updates** - Updated app catalogs with the latest releases for Actual, BoltAI, Bome Network, DBeaver Community, Dockside, ExifCleaner, Firefox Nightly, LinearMouse, Ocenaudio, OpenRCT2, Spokenly, Stats, WinDirStat, and Zed. - Added refreshed installer links, version detection, and integrity checks for the updated packages. - Updates cover macOS and Windows, including DBeaver Community and Zed on both platforms. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com> |
||
|
|
001b57cb9d |
Optimize memory usage in CVE chart cron job (#50385)
Resolves #50266. At production numbers the table looks like this - 20,691 CVEs × 83,000 hosts, ~268M raw (cve, host) rows (software + OS joins combined): ``` ┌─────────────────────────┬─────────────────────────┬───────────────────────┐ │ Shape of host IDs │ Old (map[string][]uint) │ New (roaring bitmaps) │ ├─────────────────────────┼─────────────────────────┼───────────────────────┤ │ Dense (contiguous runs) │ 2,479 MB │ 4.5 MB │ ├─────────────────────────┼─────────────────────────┼───────────────────────┤ │ Sparse (random) │ 2,488 MB │ 282 MB │ └─────────────────────────┴─────────────────────────┴───────────────────────┘ ``` A few things worth noting about how these map to your real data: - The old cost is shape-independent: ~2.5 GB retained just for the result map (268M rows × 8 bytes plus append slack), and the peak during collection is higher still because append doubling leaves garbage behind. That's the number that was blowing up the cron. - The new sparse figure is an overstated worst case. Your 268M rows include duplicates — multiple vulnerable software rows per host for the same CVE (the multi-kernel case) and overlap between the software and OS joins. The old code retained every raw row; the bitmap dedupes on Add, so it's bounded by unique pairs, and real fleets with AUTO_INCREMENT host IDs sit much closer to the dense row than the sparse one. - The new representation also has a hard ceiling the old one doesn't: a roaring bitmap over 83k host IDs maxes out around 16 KB per CVE regardless of contents, so even a pathological dataset caps at ~330 MB for all 20,691 CVEs — versus the old form growing linearly with join rows, unbounded. TL;DR: At scale the change is roughly a 550× reduction in the realistic (dense) case, and at minimum ~9× in the theoretical worst case. - [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 For unreleased bug fixes in a release candidate, one of: - [X] Confirmed that the fix is not expected to adversely impact load test results - [X] Alerted the release DRI if additional load testing is needed <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Performance** - Reduced memory usage for CVE chart data collection. - Improved efficiency when processing large CVE and affected-host datasets. - **Bug Fixes** - Preserved correct CVE filtering, duplicate-host handling, disabled-fleet exclusions, and empty-result behavior. - Added coverage for CVEs sourced from both software and operating-system data. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
1ed4b5c89a |
Update Evernote macOS version to 11.27.5 (#50395)
**Related issue:** Resolves # # Checklist for submitter - [ ] 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 - [ ] QA'd all new/changed functionality manually --- ## Summary Updates the Evernote macOS application version from 11.20.2 to 11.27.5 in the maintained apps configuration. This change updates both the version identifier and the corresponding SQL query that checks for patched versions. ## Changes - Updated `ee/maintained-apps/outputs/evernote/darwin.json`: - Version bumped from `11.20.2` to `11.27.5` - Updated the `patched` query to check against the new version `11.27.5` instead of `11.20.2` This ensures that Fleet's vulnerability detection and patching workflows correctly identify whether Evernote on macOS is up-to-date with the latest version. https://claude.ai/code/session_01F85XismGHNQj3ZEn7zPNpD Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
352d1f9070 |
Unfreeze NVIDIA GeForce NOW (macOS) (#50392)
Automated unfreeze probe. Removes `"frozen": true` and regenerates the output manifest so `test-fma-darwin-pr-only` can validate `nvidia-geforce-now/darwin` at its current upstream version. Frozen since: 2026-06-15 (#47645, automated FMA update run) Version: 2.0.85.133 -> 2.0.87.131 Upstream Homebrew cask reports 2.0.87.131, which is newer than the pinned 2.0.85.133, so this is a genuine forward bump rather than a regression. Note: the regenerated manifest also picks up a newer `uninstall_script_ref`, because the frozen output missed the script-template updates that landed on main while it was pinned. Draft until validation reports. Merge only if the FMA checks are green and the validate shard actually ran for this slug. **Related issue:** NA # Checklist for submitter - [x] QA'd all new/changed functionality manually — pending CI validation, see above. --- _Generated by [Claude Code](https://claude.ai/code/session_01F3HnFWdGjLMbqHdxWZXBAo)_ Co-authored-by: Claude <noreply@anthropic.com> |