imgbot
532
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
051d12718c |
Add JetBrains ReSharper as a Windows Fleet-maintained app (#50659)
**Related issue:** Resolves #50567 Adds JetBrains ReSharper as a Windows Fleet-maintained app (winget `JetBrains.ReSharper`, version `2026.2.0.2`). ReSharper is a Visual Studio extension rather than a standalone app, so it does not follow the pattern of the other JetBrains FMAs (Rider, PhpStorm, DataGrip, etc.), which are plain NSIS installers that take `/S`. Reviewers should read the risks below before approving — a couple of things can only be confirmed from a validator run. ## What's here - `ee/maintained-apps/inputs/winget/resharper.json` - `ee/maintained-apps/inputs/winget/scripts/resharper_install.ps1` / `resharper_uninstall.ps1` - Generated `ee/maintained-apps/outputs/resharper/windows.json` + `apps.json` entry - Icon (`Resharper.tsx`, website PNG, alphabetical `index.ts` entries), generated from JetBrains' own brand asset ## Decisions that differ from the other JetBrains FMAs **`use_display_version_for_patch` is omitted.** Every other JetBrains winget input sets it, but the ReSharper manifest has no `AppsAndFeaturesEntries`, so the ingester hard-errors with `use_display_version_for_patch is set but no DisplayVersion found in winget manifest`. The patch policy therefore compares against winget's `2026.2.0.2`. **Custom `exists_query` instead of `fuzzy_match_name`.** The prefix is loose enough to match a possible per-VS-instance suffix, and excludes the separate ReSharper C++ and ReSharper SDK products: ```sql SELECT 1 FROM programs WHERE name LIKE 'JetBrains ReSharper%' AND name NOT LIKE 'JetBrains ReSharper C++%' AND name NOT LIKE 'JetBrains ReSharper SDK%' AND publisher = 'JetBrains s.r.o.'; ``` **Install script detects Visual Studio.** It builds `/VsVersion` from the instances `vswhere` reports and runs the installer with `/Silent=True /PerMachine=True /SkipEtwService=True`: - `/PerMachine=True` — the installer otherwise targets `%LocalAppData%`, which under Fleet's SYSTEM context would land in the SYSTEM profile instead of the developer's. The path is not configurable ([RSRP-428991](https://youtrack.jetbrains.com/issue/RSRP-428991)). - `/SkipEtwService=True` — JetBrains documents that `EtwHostService.msi` always raises a UAC prompt, so a fully silent install of every component is not possible ([SUPPORT-A-3189](https://youtrack.jetbrains.com/articles/SUPPORT-A-3189)). - It then waits for the uninstall registry entry (what osquery reads), because the web bootstrapper can outlive its own exit code, and logs the resulting ARP entries. **Uninstall removes every matching entry**, since ReSharper registers one per Visual Studio instance, using the defensive `UninstallString` parser and appending `/Silent=True` rather than the NSIS `/S`. Switches come from [JetBrains' silent install/uninstall article](https://resharper-support.jetbrains.com/hc/en-us/articles/207241485-How-to-use-silent-install-and-silent-uninstall-of-ReSharper-via-Command-Line), not guesswork. ## `unique_identifier` is provisional `program_publisher` is verified — `JetBrains s.r.o.` is hard-coded next to the ARP value names (`DisplayName`, `DisplayVersion`, `UninstallString`, `Publisher`) in `JetBrains.Platform.Installer.exe`, extracted from the installer. The **DisplayName is not verifiable offline.** The winget URL is a two-stage web bootstrapper: the 69 MB `.web.exe` contains `JetBrains.Platform.Installer.Bootstrap.exe`, which downloads the JetBrains dotUltimate installer, which downloads the product packages. The ARP entry is written by that downloaded stage under `Software\Microsoft\Windows\CurrentVersion\Uninstall\{GUID}`, with `DisplayName` taken from a per-VS-host `PresentableName`. So `JetBrains ReSharper` is a best-supported guess. It can be confirmed from a validator run: `cmd/maintained-apps/validate/windows.go` searches `programs` with a loose `LOWER(name) LIKE '%…%'` on both the catalog name and `unique_identifier`, and logs `Found app: '<DisplayName>' … Version: <ver>` after running `MutateSoftwareOnIngestion`. That reveals both the true DisplayName and the post-mutation version. The install script prints the same information. **Expect a follow-up commit correcting `unique_identifier` (and possibly the exists query) once that log lands.** ## Risks 1. **Payload is not pinned.** The SHA covers only the 69 MB bootstrapper; roughly 1.7 GB is fetched from `download.jetbrains.com` at install time. JetBrains publishes only a `windowsWeb` download for ReSharper, so there is no offline installer to point at. Install duration may exceed script timeouts. 2. **Requires Visual Studio.** With no VS present the installer has nothing to install, so the script exits 1 with a clear message. `windows-latest` runners ship Visual Studio 2022 Enterprise, so validation should be able to install. 3. **`/PerMachine=True` conflicts with pre-existing per-user installs.** JetBrains states machine-wide mode "is not compatible with existing installations in user profiles"; one must be removed first. 4. **`/SkipEtwService=True` omits the ETW host service**, so dotTrace/dotMemory profiling integration is incomplete. This is the documented tradeoff for an unattended install. 5. **Version reconciliation unconfirmed.** If the DisplayName ends in a marketing version, the JetBrains name-based version mutation fires and the validator's prefix check passes; a VS-suffixed name would instead fall back to the registry `DisplayVersion`. # 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; both output JSON files parse; generated SHA matches the winget manifest. - [ ] QA'd all new/changed functionality manually — **not done.** Install/uninstall need a Windows host with Visual Studio; relying on the FMA Windows validator, which is also how `unique_identifier` gets confirmed. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added ReSharper to the maintained Windows applications catalog. * Added support for silent machine-wide installation and uninstallation. * Added Visual Studio compatibility checks and installation failure reporting. * Added a ReSharper icon for display in the software catalog. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
616f9ab108 |
Update scripts in Fleet-maintained apps (#50756)
Automated ingestion of latest Fleet-maintained app data. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Updates** - Refreshed macOS and Windows installer metadata for numerous maintained applications, including AltTab, Arc, Calibre, ChatGPT, Chrome, Kiro, Loom, Postman, Prisma Access Browser, RustRover, and others. - Updated release versions, download links, version detection, and integrity checks. - **Bug Fixes** - Improved Evernote removal verification on Windows. - Enhanced Krita and Proton Drive macOS cleanup, including related support files and background services. - **Configuration** - Webex is now marked as frozen. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com> Co-authored-by: Allen Houchins <allenhouchins@mac.com> |
||
|
|
9b5e9775ce |
Unfreeze XnConvert (macOS) (#50700)
Automated unfreeze probe. Removes `"frozen": true` and regenerates the output manifest so test-fma-macos-pr-only can validate `xnconvert/darwin` at its current upstream version. Frozen since: not recoverable from this checkout (squashed/shallow history — every input file is attributed to the same import commit) Version: 1.112.0 -> 1.115.0 Draft until validation reports. Merge only if the FMA checks are green and the validate shard actually ran for this slug. --- _Generated by [Claude Code](https://claude.ai/code/session_01Hx5UA4Dhqh2UUCX8h6k6Vv)_ Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
5db78a63e3 |
Add Visual Studio 2022 (Community/Professional/Enterprise) as Windows FMAs (#50717)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #50653 Adds **Visual Studio 2022 Community, Professional, and Enterprise** as Windows Fleet-maintained apps. customer-universitas needs all three editions. ## What's here - Three input files, one per edition, each pointing at its own winget package (`Microsoft.VisualStudio.2022.{Community,Professional,Enterprise}`, all at `17.14.37`). - A shared install script (`visual_studio_2022_install.ps1`) — the downloaded file is a ~4 MB bootstrapper, not the IDE. The real multi-GB payload downloads from Microsoft *during* the install script, so install time depends on the host's network speed and counts against Fleet's 1-hour software-install timeout. `--wait` is required or the bootstrapper forks the real install to a background process and returns almost immediately. - Three uninstall scripts (one per edition) that resolve the install path via `vswhere.exe -products Microsoft.VisualStudio.Product.<Edition>` and call `vs_installer.exe uninstall --installPath <path> --quiet --norestart --wait`, since VS has no normal `UninstallString`. - Both scripts map winget's documented `3010`/`1641` (reboot pending/initiated) to a successful exit, and fail clearly on `1001`/`1618` (another VS Installer operation already running). - Default install ships the bare IDE shell (no `--add` workloads) — matches plain `winget install` behavior, per the issue's own conclusion that this needs no special-casing. - Icons: no scriptable source (no Windows host to extract the real per-edition `.exe` icon, and Microsoft's own download pages don't expose one) turned up distinct Community/Professional/Enterprise badge art, so all three currently use the same public Visual Studio mark ([Wikimedia Commons](https://commons.wikimedia.org/wiki/File:Visual_Studio_Icon_2022.svg), marked public domain). **Flagging for #g-software Product Designer** to swap in the real per-edition badges if we have them. ## What I could not verify (no Windows host in this environment) - `unique_identifier`/publisher (`Visual Studio Community/Professional/Enterprise 2022`, publisher `Microsoft Corporation`) are taken from the winget locale manifest, not confirmed against a live registry entry. - The version-string quirk the issue calls out: winget's `AppsAndFeaturesEntries.DisplayVersion` is `"17.14.37 (July 2026)"`, not a clean version. I deliberately did **not** set `use_display_version_for_patch` — feeding that non-numeric string in as the patch target would break `version_compare` ordering across future version bumps (see the comment in `ingester.go`). Instead the patch policy compares against the plain winget `PackageVersion` (`17.14.37`), same as most winget FMAs. This should hold up if `version_compare` reads leading numeric-dot segments and ignores the trailing text, but I can't confirm that against real `programs.version` output without a host. - Whether `vs_installer.exe` actually honors `--wait` for `uninstall` the way the bootstrapper does for `install` — Microsoft's own docs say `--wait` "can only be passed into the bootstrapper; the installer (setup.exe) doesn't support it," which is in tension with the exact command this issue asked for and what I've seen used in the wild. Worth watching in validation logs. - End-to-end install timing on a normal (non-datacenter) connection, within the 1-hour timeout. # Checklist for submitter - [ ] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. <!-- Not added — no precedent for a changes file on FMA-addition PRs (e.g. #50553, TeamViewer Host). --> - [ ] 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] `apps.json` is valid JSON with descriptions filled in for all three editions - [x] Generator output reviewed: exists/patched queries, SHA256 (matches the live winget manifest), installer URLs - [x] `go build`/`go test ./ee/maintained-apps/...` pass; no shared ingester/validator code changed - [ ] FMA validator: install → detect → uninstall on a Windows host — **pending, needs a Windows host** - [ ] QA'd all new/changed functionality manually — **pending, same reason** ## FMA-specific (from issue #50653's acceptance criteria) - [x] Edition scope decided and recorded on the issue (all three: Community, Professional, Enterprise) - [x] Input added under `ee/maintained-apps/inputs/winget/` - [x] Custom install script handles `3010`/`1641` as success and fails clearly on `1618`/`1001` - [x] Custom uninstall script resolves the install path via `vswhere` and calls `vs_installer.exe uninstall` - [ ] Identity fields verified against a real installed host — **not yet, see above** - [ ] Patch policy verified against actual `programs.version` — **not yet, see above** - [ ] Install verified end to end within the 1-hour timeout on a normal-speed connection — **not yet** - [ ] Passes the FMA validator: install → detect → uninstall — **not yet** - [x] Icon exists (shared placeholder mark across all three editions — flagged for PD) No shared/ingester/validator code changed. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added Visual Studio 2022 Community, Professional, and Enterprise editions to the software catalog. - Added support for installing and uninstalling each edition with quiet execution, installation detection, error handling, and reboot handling. - Added version 17.14.37 metadata and update detection. - Added Visual Studio branding and edition-specific icons throughout the software interface. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Allen Houchins <allenhouchins@mac.com> |
||
|
|
01f9e534f7 |
Fix Genesys Cloud FMA: winget dropped x86, ship x64 MSI (#50742)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> # 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. ## Testing - [x] QA'd all new/changed functionality manually # Details The nightly maintained-apps ingestion job panicked with `failed to find installer for app` on Genesys Cloud: ``` {"time":"2026-08-07T03:17:22.787715966Z","level":"INFO","msg":"ingesting winget app","name":"Genesys Cloud"} panic: ingesting winget app: failed to find installer for app ``` ## Why Genesys.GenesysCloud **2.53.923.0** stopped publishing x86 installers upstream. Previous versions (e.g. 2.51.916.0) shipped two x86 installers (a burn `.exe` and a wix `.msi`); the latest manifest ships only a single **x64** wix MSI. Our input pinned `installer_arch: "x86"`, so the ingester filtered out the only available installer and panicked. ## What changed - `ee/maintained-apps/inputs/winget/genesys-cloud.json`: `installer_arch` `x86` → `x64` - `ee/maintained-apps/outputs/genesys-cloud/windows.json`: regenerated with `go run ./cmd/maintained-apps -slug genesys-cloud/windows` — version 2.51.916.0 → 2.53.923.0, installer URL now the x64 MSI, sha256 matches the winget manifest's `InstallerSha256` ## Notes for reviewers - Exists/patched queries are unchanged (still keyed on ARP `name = 'GenesysCloud'`, `publisher = 'Genesys Inc.'`), and install/uninstall script refs are identical since it's still a machine-scope MSI — detection and remediation carry over for existing installs. - The MSI `UpgradeCode` is unchanged upstream (`{A0E8C487-C337-441C-83AF-90364DA4B793}`), so the x64 MSI upgrades existing x86 installs in place (ProductCode is new, install dir moves from `ProgramFiles(x86)` to `ProgramFiles`). - The new manifest declares a `Microsoft.VCRedist.2015+.x64` dependency (the old x86 MSI declared the x86 variant). Fleet doesn't resolve winget dependencies; the FMA validator run on this PR will confirm whether the installer tolerates its absence. |
||
|
|
ec59e20971 |
Regenerate Fleet Desktop FMA manifests for v1.4.0 (#50674)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** NA — follow-up to #49910 ## What changed Regenerates `api/fleet-desktop.json` and `outputs/fleet-desktop/darwin.json` for Fleet Desktop v1.4.0. No cask changes. ## Why #49910 bumped `Casks/fleet-desktop.rb` to 1.4.0 but never ran `regenerate.sh` or the ingester, so the generated manifests — the files Fleet actually serves — were still on 1.3.4 and still pointed at the old `allenhouchins/fleet-desktop` GitHub release URL. That release feed is stale (it stops at v1.3.4); 1.4.0 is hosted at `download.fleetdm.com`. The `.rb` bump had no effect in production, and nothing in CI catches this kind of drift. This was found during a routine custom-tap maintenance pass. All four casks (druva-insync, fleet-desktop, xcreds, zoom-rooms) are at their latest upstream versions, so this is the only change needed: | Cask | Version | Upstream | | |---|---|---|---| | druva-insync | 8.1.3,110967 | `inSync-8.1.3r110967` | current | | fleet-desktop | 1.4.0 | 1.4.0 (1.4.1 → 404) | **manifests were stale** | | xcreds | 5.9,9148 | `tag-5.9(9148)` | current | | zoom-rooms | 7.1.5.13403 | `cdn.zoom.us/prod/7.1.5.13403/` | current | ## Notes for reviewers Verified the 1.4.0 installer against the cask stanzas before regenerating: - sha256 of the downloaded pkg matches the cask's `c920b983…` - receipt id `com.fleetdm.fleet-desktop` (from `PackageInfo`) matches both the `pkgutil:` and `quit:` stanzas - `CFBundleShortVersionString` is `1.4.0`, matching the cask version — so the `patched` query won't produce a perpetual false "Update available" - the `pkg` stanza filename `fleet_desktop-v1.4.0.pkg` matches the downloaded filename `regenerate.sh` rebuilds all four api JSONs; only fleet-desktop changed, so there was no brew schema drift to absorb on the others. The `install_script_ref` changes (`5d021f75` → `0341b271`) only because the pkg filename inside the script changed; `uninstall_script_ref` is unchanged. Unrelated, not addressed here: brew emits a deprecation warning on three casks for `depends_on macos: ">= :ventura"` (string comparison) vs `depends_on macos: :ventura`. It doesn't affect the generated JSON. # Checklist for submitter - [x] QA'd all new/changed functionality manually ## fleetd/orbit/Fleet Desktop - [x] If the change applies to only one platform, confirmed that `runtime.GOOS` is used as needed to isolate changes This is a macOS-only FMA manifest regeneration — no Go code, no schema, no fleetd/orbit runtime changes. The remaining template sections (changes file, SQL/input validation, timeouts, automated tests, migrations, config settings, fleetd compatibility/auto-update) don't apply; prior custom-tap bumps (#49563, #50651) likewise carry no changes file. |
||
|
|
600fbf461d |
Update fleet desktop FMA to v1.4.0 (#49910)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #45524 Release alongside v4.90.0 release. Don't release prior FMA update of Fleet Desktop macOS to 1.4.0 https://github.com/fleetdm/fleet/actions/runs/30112916197 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Updated the Fleet Desktop Homebrew cask to version 1.4.0. * Downloads now use the official Fleet Desktop distribution URL. * Updated the project homepage reference. * **Maintenance** * Adjusted automatic update detection to use manual, release-based versioning. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
ecdf1ff003 |
Add TeamViewer Host as a Windows Fleet-maintained app (#50553)
**Related issue:** Resolves #50332 Adds **TeamViewer Host** as a Windows Fleet-maintained app. ## The issue's premise was wrong — this needed no new capability #50332 was blocked on "not in winget." It is in winget: `TeamViewer.TeamViewer.Host`, published continuously since **June 2023** (v15.42.8), currently **15.80.4** (merged upstream as microsoft/winget-pkgs#409335, 2026-07-29). I downloaded the live x64 installer and its SHA256 matches that manifest byte-for-byte. It reads as absent because it's nested a level deeper than you'd expect — `manifests/t/TeamViewer/TeamViewer/Host/`, a sibling of the full client's *version* directories rather than of the publisher's package directories. Consequence: this comes off the dependency on #50364, and that FR loses one of its three examples. The other two (#50328, #50329, OLE DB Driver 18/19) still hold — there is no OLE DB package under any winget publisher. ## Identity verified against the installer, not winget metadata Per the `new-fma` golden rule, from the x64 MSI's `Property` and `Registry` tables: | Field | Value | Evidence | |---|---|---| | `unique_identifier` | `TeamViewer Host` | MSI `ProductName`; no `ARPDISPLAYNAME`, empty `Registry` table, so this is the ARP DisplayName | | publisher | `TeamViewer` | MSI `Manufacturer`, equal to the winget locale `Publisher` → no `program_publisher` override | | `installer_scope` | `machine` | `ALLUSERS=1` | | bootstrapper? | No | no `ARPSYSTEMCOMPONENT` | Corroborated independently by [silentinstallhq's PSADT script](https://silentinstallhq.com/teamviewer-host-install-and-uninstall-powershell/), which detects the app with `Get-InstalledApplication -Name 'TeamViewer Host'` and uses `/S` for both install and uninstall. Generated exists query: ```sql SELECT 1 FROM programs WHERE name = 'TeamViewer Host' AND publisher = 'TeamViewer'; ``` No collision with the existing `teamviewer/windows` FMA, which generates an exact `name = 'TeamViewer'`. ## Why exe + `ignore_hash`, matching the full client winget offers Host as an NSIS exe and as a nested `wix` MSI inside a zip. The ingester can't select the zip (`installer.InstallerType` is `zip`, which never normalizes to `msi`), so the exe is the only reachable installer. TeamViewer publishes no version-pinned Host exe — `TeamViewer_Host_Setup_x64_15.80.4.exe` and the x86 equivalent both 404 — so the manifest's URL is the unpinned `TeamViewer_Host_Setup_x64.exe` and `ignore_hash: true` is required. This is vendor asymmetry, not a fixable winget defect: the *full* client does publish pinned exe URLs. Same reason `teamviewer/windows` already sets `ignore_hash`. ## Correcting the coexistence note in #50332 The issue assumed Host and the full client can co-exist. They can't. The Host MSI's `LaunchCondition` table blocks the install outright: > Error 25001: An incompatible TeamViewer package was detected that conflicts with the current MSI package: TeamViewer_Full 64-bit. Please manually uninstall this package. …plus equivalents for Full 32-bit/ARM64, Host ARM64, and the NSIS installs. **Relevant to validation: the validator host must not already have `teamviewer/windows` installed.** ## Icons No `index.ts` change needed — `matchLoosePrefixToKey` treats keys as whole words at the start, so `"teamviewer host"` matches the existing `teamviewer` key and inherits the TeamViewer brand icon. Verified against the real 1,163-key map. The website resolves its icon from the slug (`app-icon-${slug}-60x60@2x.png`) with no such fallback, so `app-icon-teamviewer-host-60x60@2x.png` is added — a copy of the existing TeamViewer brand asset, since Host ships the same logo. ## Two things for review 1. **The PowerShell is unverified.** Authored on macOS with no PowerShell available, so install/uninstall have not been executed. The uninstall script searches ARP by DisplayName instead of a hardcoded key, and uses the three-shape `UninstallString` parser (TeamViewer's is unquoted and contains a space in `C:\Program Files\...`, which the older `.Split('"')` approach in `teamviewer_uninstall.ps1` mishandles). Validator run is the real check. 2. **Category mismatch with the macOS side.** This uses `Communication`, matching the merged `teamviewer/windows`. #47121 adds `teamviewer-host/darwin` with `Productivity`. Worth reconciling — and that PR will want this same website PNG, so expect a trivial conflict. `name` is `TeamViewer Host`, matching #47121 so both platforms group together in the FMA library. ## Testing - [x] `go test ./cmd/maintained-apps/... ./ee/maintained-apps/...` passes - [x] Generator is idempotent — re-running produces no diff and preserves the `apps.json` description - [x] `apps.json` is valid JSON with no empty descriptions - [x] Live installer SHA256 confirmed against the winget manifest - [ ] FMA validator: install → detect → uninstall on a Windows host **(pending — needs a host without the full TeamViewer client)** No shared code changed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: Allen Houchins <allenhouchins@mac.com> |
||
|
|
bc3eee5f32 |
Re-add Dell Display and Peripheral Manager Windows FMA, validate on client-OS runner (#50313)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** NA (Windows FMA workstream; follow-up to #49127, which dropped DDPM) Re-adds **Dell Display and Peripheral Manager** (`Dell.DisplayAndPeripheralManager` 2.2.2.8) as a Windows Fleet-maintained app, and adds a `requires_client_os` routing override so its CI validation always runs on the `windows-11-arm` runner. ## Why DDPM was dropped before, and why it's viable now DDPM was dropped from the earlier re-add because its InstallShield setup aborted with `0x80042000` under every documented silent switch, which was diagnosed at the time as a .NET-prerequisite/headless-chaining problem. A new debug run with Dell's own `/CreateDebugLog` switch shows the real cause: the setup evaluates the OS at `OFUIBefore` and terminates because the runner reports **Microsoft Windows Server 2025**. DDPM is a Windows 10/11 client application and refuses to install on Server SKUs — which is exactly what GitHub's x64 `windows-latest` image is. ``` OSetUMode() 0 AP:2.2.2.8 OFUIBefore Os Major10 Minor0 OS - 44444 // End Log File... ``` ## `requires_client_os` CI routing - New optional winget input field `requires_client_os: true` (documented in `ee/maintained-apps/README.md` and on the Go input struct; ignored by ingestion). - `.github/scripts/partition-fma-apps.sh` routes any app with this flag to `windows-11-arm` — the only GitHub-hosted client-OS Windows runner — regardless of `installer_arch`. The x64 installer runs there under Prism emulation; DDPM's gate is the OS SKU, not the architecture. - Verified locally: partitioning the full 421-app Windows catalog reroutes only `dell-display-and-peripheral-manager/windows`. ## App identity (verified against the real installer) - Downloaded `DDPM-Setup_2.2.2.8.exe` from `dl.dell.com` (Chrome UA per #49123); SHA256 matches the winget manifest. - Embedded InstallShield `[Application]` block: `Name=Dell Display and Peripheral Manager`, `Company=Dell Technologies`; ProductCode matches the manifest GUID. The setup log reports `AP:2.2.2.8` as the registering version. - Installs with Dell's documented managed-deployment switches `/Silent /HeadlessMode=true /TelemetryConsent=false /TurnOffCA` — the final pre-drop iteration (6d0f2c00af), which also declines telemetry and disables DDPM's self-updater on Fleet-managed hosts. Uninstalls via `msiexec /x` on the ProductCode looked up in the registry by DisplayName. Input/uninstall script/icon are restored from the pre-drop state; the install script is the final pre-drop iteration with its root-cause comment corrected (Server-SKU OS gate, not headless-SYSTEM chaining). Output regenerated (winget still at 2.2.2.8; script refs verified). # 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 (partition script exercised locally over the full catalog and a mixed PR-style slug list; ingester regenerated with no output drift; `go test ./ee/maintained-apps/ingesters/winget/` passes) - [ ] `test-fma-windows-pr-only` validates DDPM on the `windows-11-arm` runner in this PR's CI <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added Dell Display and Peripheral Manager to the Windows software catalog, including installation, uninstallation, detection, metadata, and an app icon. * Added support for routing applications that require a Windows client operating system to the appropriate Windows 11 ARM test environment. * **Documentation** * Documented Windows client operating system routing behavior and test environment architecture details. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
33b4efe9c1 |
Update install script and Fleet-maintained apps (#50499)
Automated ingestion of latest Fleet-maintained app data. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Chores * Updated numerous maintained application definitions with newer releases, download links, version checks, and checksums across Windows and macOS. * Improved Windows installation reliability by recognizing successful installations that require a restart. * Corrected installer log-path handling for paths containing spaces. * Refreshed metadata for applications including Firefox, Docker Desktop, Discord, Tailscale, and many others. * Adjusted Google Credential Provider validation settings to support its installer distribution. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com> Co-authored-by: Allen Houchins <allenhouchins@mac.com> |
||
|
|
4d6dbf8639 |
Fix Gpg4win FMA ingest panic after winget relabeled 5.1.0 as x64 (#50494)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** NA — caught from a failing `Update Fleet-maintained apps` ingest run. # What this does Changes `installer_arch` from `x86` to `x64` for the Gpg4win Windows FMA, and regenerates its output (5.0.2 → 5.1.0). ## Why the ingest was failing ``` {"level":"INFO","msg":"ingesting winget app","name":"Gpg4win"} panic: ingesting winget app: failed to find installer for app ``` This is **not** a removed winget package — Gpg4win is still published as `GnuPG.Gpg4win`. The manifest was fetched and parsed fine; the failure is the `selectedInstaller == nil` check in `ee/maintained-apps/ingesters/winget/ingester.go`, which means no installer entry matched all four selector fields from our input. Upstream flipped the architecture label between versions: | | 5.0.2 (last ingested) | 5.1.0 (new) | |---|---|---| | `Architecture` | **x86** | **x64** | | Manifest generator | `wingetcreate 1.10.3.0` | `YamlCreate.ps1 Dumplings Mod` | Our input pinned `x86` to match 5.0.2, so nothing matched once 5.1.0 landed in `winget-pkgs` (2026-08-03 18:11 UTC, microsoft/winget-pkgs#409397). The ingester only walks to an older version directory on a genuine 404 of the installer manifest — never because the newest version's installer failed to match — so it panics instead of falling back. ## The new x64 label is the correct one Verified against the real installer rather than trusting either manifest: - The NSIS stub's PE header is i386, which is very likely what `wingetcreate` guessed `x86` from. Installer stubs are almost always 32-bit, so stub arch says nothing about the payload. - The payload ships 64-bit binaries in `bin/` (PE machine `0x8664`) alongside a 32-bit `bin_32/` compatibility set. So 5.0.2's `x86` was the inaccurate manifest and the bot corrected it. Regenerated `sha256` also matches a fresh download of `gpg4win-5.1.0.exe` bit-for-bit (`9682f282…20a2e`). ## Blast radius Worth flagging: this one field blocked **the entire FMA ingest**, not just Gpg4win. `failed to find installer for app` isn't matched by `isTransientGitHubError`, so it returns up to `panic(err)` in `cmd/maintained-apps/main.go`, which aborts the process before `processOutput` writes *any* app's manifest. Because the `ingesters` map is iterated in random order, this could take out the homebrew side too. Any future upstream flip of `installer_arch` / `installer_scope` / `installer_type` / `installer_locale` on any single app will do the same thing — worth a follow-up to make non-transient per-app ingest errors skip-and-report instead of fatal. ## Why no changes file The net user-visible effect is a routine FMA version bump (Gpg4win 5.1.0), which the scheduled ingest PR delivers without changelog entries. Happy to add one if you'd rather it be called out. # 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: - `go run ./cmd/maintained-apps -slug gpg4win/windows` completes with no panic (previously fatal). - Diff is scoped to the two expected files; `outputs/apps.json` is untouched, since name/description didn't change. - Regenerated `sha256` matches a fresh download of the upstream installer. - Install/uninstall scripts need no changes — both already enumerate the native *and* `Wow6432Node` registry views across `HKLM`/`HKCU`, so detection survives the 32→64-bit flip. - `installer_arch` is only a manifest selector plus CI runner routing in `.github/scripts/partition-fma-apps.sh`, where x64/x86/neutral all land on the same x64 runner. No routing change, and the field is never written into `outputs/`, so no user-visible arch claim changes. Still needs the FMA validator's install/uninstall run on a Windows runner to confirm 5.1.0 installs and is detected — that's what the draft is for. |
||
|
|
b668734d5c |
Remove Fig FMA (cask removed from Homebrew upstream) (#50483)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** NA Removes the **Fig** Fleet-maintained app. Its Homebrew cask no longer exists. Homebrew deleted the `fig` cask in [`a36fac3b75`](https://github.com/Homebrew/homebrew-cask/commit/a36fac3b75f633a9c787c4c73fc46606939947a3) on **2026-08-04**, the end of a long deprecation: | Date | Upstream change | |---|---| | 2024-08-03 | `fig: deprecate` | | 2025-08-02 | `fig: disable` | | 2026-08-04 | `fig: remove cask` | `https://formulae.brew.sh/api/cask/fig.json` now returns **404**, so the nightly ingester panics and no maintained apps are generated at all: ``` {"time":"2026-08-04T02:38:58.15272663Z","level":"INFO","msg":"ingesting homebrew app","name":"fig"} panic: ingesting homebrew app: app not found in brew API ``` Note that `"frozen": true` does **not** fix this — that flag only gates the output write, and the ingester still fetches the cask first and panics on the 404. Removing the input is the fix. There is no successor cask to migrate to. Fig was acquired by AWS and folded into Amazon Q Developer CLI, which is not distributed via Homebrew (`amazon-q`, `amazon-q-developer-cli`, `q-cli`, and `codewhisperer` all 404), and `fig.io` itself now returns 503. ### Changes - Deleted `ee/maintained-apps/inputs/homebrew/fig.json` - Deleted `ee/maintained-apps/outputs/fig/darwin.json` - Removed the `fig/darwin` entry from `ee/maintained-apps/outputs/apps.json` - Deleted the `Fig` icon component and its `index.ts` import/map entry - Deleted `website/assets/images/app-icon-fig-60x60@2x.png` The output file is deleted rather than orphaned so the PR validator's changed-app detector doesn't keep validating a removed app. # 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. ## Testing - [x] QA'd all new/changed functionality manually Verified `apps.json` still parses and the `fig/darwin` slug is gone (1390 apps remain, `figma` untouched), `tsc --noEmit` is clean after removing the `Fig` icon import, and no references to `fig`, `com.mschrage.fig`, `fig/darwin`, or `repo.fig.io` remain anywhere in the repo. > [!NOTE] > Existing hosts with Fig installed will no longer see it as a Fleet-maintained app. The app is end-of-life upstream, so there is no version for Fleet to track or patch to. |
||
|
|
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 --> |
||
|
|
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> |
||
|
|
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 |
||
|
|
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). |
||
|
|
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 --> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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 --> |
||
|
|
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 --> |
||
|
|
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> |
||
|
|
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> |
||
|
|
24b24ae699 |
Unfreeze Logi Options+ (macOS) (#50372)
Automated unfreeze probe. Removes `"frozen": true` and regenerates the output manifest so `test-fma-darwin-pr-only` can validate `logi-options+/darwin` at its current upstream version. Frozen since: 2026-04-03 (#42984, automated FMA update run) Version: 2.4.903778 -> 2.5.926888 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_01EBxhs5D65LRUwCEJejBLJH)_ Co-authored-by: allenhouchins <allen@fleetdm.com> |
||
|
|
2747d82328 |
Unfreeze Keeper Password Manager (macOS) (#50371)
Automated unfreeze probe. Removes `"frozen": true` and regenerates the output manifest so `test-fma-darwin-pr-only` can validate `keeper-password-manager/darwin` at its current upstream version. Frozen since: 2026-02-10 (#39623, automated FMA update run) Version: 18.2.1 -> 18.5.0 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_01EBxhs5D65LRUwCEJejBLJH)_ Co-authored-by: allenhouchins <allen@fleetdm.com> |
||
|
|
f082237518 |
Add Lenovo System Update as a Windows FMA (#50339)
**Related issue:** Resolves #50324 Adds Lenovo System Update as a Windows Fleet-maintained app, from winget `Lenovo.SystemUpdate` (5.08.03.59, Inno Setup, machine scope, x86-only). Found in a customer's ManageEngine ServiceDesk Plus Windows deployment catalog with no Fleet equivalent. Distinct from `lenovo-dock-manager/windows`, which we already ship. ## Verification - Installer SHA confirmed against a local download of `system_update_5.08.03.59.exe` (`e66794dc…53e0d`), served from `download.lenovo.com` — a pinned vendor URL, so none of the SourceForge mirror trouble from #50322 applies. - Registry `DisplayName` determined offline as a bare `Lenovo System Update`: `innoextract --info` reports `AppVerName` when set and falls back to `AppName`, and Inno writes that same value to `DisplayName`. This installer reports no version suffix, unlike CrystalDiskMark in #50322 which reports `"CrystalDiskMark 9.0.3"`. That is why the exists query here is an exact match rather than a prefix. - Icon extracted from the installer's own `Tvsukernel.exe` resource, not sourced from the web. - The uninstall script targets the Inno registry key directly via the manifest's `ProductCode` (`TVSU_is1` — a key name, not a GUID) using the `$PACKAGE_ID` substitution, rather than string-matching `DisplayName`. ## Two things reviewers should weigh in on **1. The exists query deliberately omits the publisher.** House style usually pins `publisher = '...'`, but the registry `Publisher` is not determinable offline for Inno, and the validator's log prints only the name and version — so I could not confirm it. A wrong publisher makes the exists query silently never match while the validator still passes, which is the exact failure mode called out in the FMA docs. `name = 'Lenovo System Update'` is unambiguous on its own. Happy to add the publisher clause if someone can confirm the registry value on a real Lenovo host. **2. This may not be validatable on the CI runner.** Lenovo System Update is a vendor tool for Lenovo hardware, and the runner is a generic Azure VM. If the installer refuses to run on non-Lenovo hardware this will fail the way Dell Display and Peripheral Manager did in #50020 (which was dropped for exactly this reason, and is being retried on a client-OS runner in #50313). Leaving this in draft until the validator reports. # 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 Lenovo System Update to the maintained Windows software catalog. * Added support for silent installation and uninstallation, including status verification and reboot-success handling. * Added Lenovo System Update metadata, download information, categorization, and application icon. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
7837b8ec8f |
Add AOMEI Backupper Standard as a Windows Fleet-maintained app (#50021)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** #50020 # What this does Adds **AOMEI Backupper Standard** as a Windows Fleet-maintained app. One of the 11 apps split out of #48501 that failed the FMA validator; #50016 shipped the 6 that passed. ## Why it was failing Install and detection were already fine on the SYSTEM-context Windows runner — the validator installed it and osquery found `AOMEI Backupper` 8.4.0. **Uninstall** was the failure: ``` ERROR msg="Error uninstalling app: exit status 1" app="AOMEI Backupper Standard" ERROR msg="Output: Uninstaller for 'AOMEI Backupper Standard' not found." ``` AOMEI unified the ARP `DisplayName` across editions around v7.4 — the registry entry reads `AOMEI Backupper`, with no `Standard` suffix. The uninstall script searched for the catalog name and matched nothing. `unique_identifier` was already corrected to `AOMEI Backupper`; this fixes the uninstall script to match. ## Notes - **Edition matching.** `AOMEI Backupper` also matches the paid Pro/Workstation/Server editions — AOMEI shares the DisplayName across editions and no registry value distinguishes them. Detecting the free edition specifically isn't possible from inventory. - **Non-pinned installer URL.** `https://www2.aomeisoftware.com/download/adb/AOMEIBackupperStd.exe` is a "latest" URL, so the pinned SHA will drift when AOMEI ships a new build until the FMA auto-update bumps it. - x86-only installer, so it lands in `C:\Program Files (x86)`. The validator's "no changes detected in `C:\Program Files`" line is an expected warning, not a failure. # 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] FMA CI validator (install → detect → uninstall) **passes** on the SYSTEM-context Windows runner — [run 30383902487](https://github.com/fleetdm/fleet/actions/runs/30383902487) (`All checks passed`) - [x] Generated output verified locally: manifest SHA matches the winget manifest, exists/patched queries reviewed for name + publisher correctness, `apps.json` is valid JSON with a description filled in. - [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 **AOMEI Backupper Standard** (version **8.4.0.0.0**) to the Windows software catalog, including verified installer download (SHA-256). - Introduced dedicated silent **install** and **uninstall** support, with version gating and idempotent uninstall behavior when the app isn’t present. - Added a **new software icon** and updated the listing so the correct icon now appears for this product. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Allen Houchins <allenhouchins@mac.com> |
||
|
|
43bff98998 |
Add Gpg4win as a Windows FMA (#50026)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** #50020 # What this does Adds **Gpg4win** as a Windows Fleet-maintained app. One of the 11 apps split out of #48501 that failed the FMA validator; #50016 shipped the 6 that passed. ## Why it was failing Same root cause as GNU Privacy Guard (#50025) — Gpg4win bundles GnuPG. The install worked; the *script* never returned: ``` 20:30:53 INFO msg="Executing install script..." app=Gpg4win 20:40:53 ERROR msg="Error executing install script: exit status 1" # exactly 10:00 later 20:40:53 INFO msg="New application detected at: C:\Program Files\Gpg4win" ``` Ten minutes on the nose is the validator's `executeScript` timeout. **`Start-Process -Wait` waits for the process *and all of its descendants***, and Gpg4win leaves `gpg-agent`, `dirmngr`, `keyboxd` and `scdaemon` resident (plus Kleopatra), so `-Wait` never returns. The same run left `gpg4win-5.0.2.exe` locked in the validator's temp dir, confirming a live child process. The install script now follows the pattern already established by [`ollama_install.ps1`](ee/maintained-apps/inputs/winget/scripts/ollama_install.ps1): start with `-PassThru` (no `-Wait`), wait on the installer process alone with a 7-minute cap (below the caller's 10-minute script budget), poll for the Add/Remove Programs entry, then stop the leftovers. The uninstall script stops those processes up front (they hold file locks that make the uninstall fail), uses NSIS's `_?=<dir>` switch so the uninstaller runs in place rather than relaunching itself detached from `%TEMP%`, and polls the ARP key to confirm removal. ## Notes - **Versioned ARP name.** The registry `DisplayName` is `Gpg4win (5.0.2)`, so the input uses `fuzzy_match_name` and the exists query is `name LIKE 'Gpg4win %'`. The uninstall script matches the same prefix. - x86-only installer. Publisher `The Gpg4win Project`. - Ships a new catalog icon and website asset. # 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] FMA CI validator (install → detect → uninstall) **passes** on the SYSTEM-context Windows runner — [run 30384125610](https://github.com/fleetdm/fleet/actions/runs/30384125610) (`All checks passed`) - [x] Generated output verified locally: manifest SHA matches the winget manifest, exists/patched queries reviewed for name + publisher correctness, `apps.json` is valid JSON with a description filled in. - [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 Gpg4win as a supported Windows application. - Added Gpg4win version 5.0.2 with Security categorization. - Added a Gpg4win icon to the software interface. - Introduced silent install and uninstall support with process cleanup, timeouts, and registry-based verification to confirm install/removal outcomes. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
0177c98f9a |
Regenerate macOS FMA install scripts (#50264)
Automated ingestion of latest Fleet-maintained app data. --------- Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com> Co-authored-by: Allen Houchins <allenhouchins@mac.com> |
||
|
|
0594f653dd |
Propagate errors in macOS FMA install scripts (#50198)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #50056 ## Summary macOS FMA install scripts never checked the exit code of the install command (`installer -pkg` / `cp -R`) — the script's last statement is always `relaunch_application`, which exits 0 — so a failed install exited 0 and Fleet reported it installed. **Generated scripts.** The generator now propagates failure: both `installer -pkg` variants end with `|| exit $?`, and the `cp -R` path exits non-zero on a failed copy, removes the partial copy (so a failed fresh install isn't inventoried as the new version), and restores the app it moved aside. Regenerated `outputs/` for non-frozen generated apps are produced by the `ingest-maintained-apps` job, so they aren't committed here. **Custom scripts.** 9 of the 18 custom input scripts had the same bug and are fixed with the same pattern: Google Chrome, Zoom, Microsoft Edge, GitHub Desktop, Webex, Cycling '74 Max, Pd, Grammarly Desktop, and P4V. The DMG-based ones also now fail before removing/moving the existing app when the mount or staging copy fails, so a bad download can't leave a host with nothing. Their `outputs/*/darwin.json` are updated in the same commit (script content + recomputed 8-char sha256 ref, versions untouched), following the precedent of #49033. Docker Desktop (`set -euo pipefail`), 1Password/Slack/LogiTune (installer is the last statement), and the rest already propagated errors. **Frozen apps.** The ingest job never rewrites frozen outputs, so the 10 frozen apps with generated scripts (adobe-acrobat-pro, comet, evernote, firealpaca, keeper-password-manager, nvidia-geforce-now, pritunl, vnc-viewer, wins, worksheet-crafter) had the fix applied directly to their published `darwin.json` scripts — the exact text the current generator would emit, with pinned versions/URLs/hashes untouched. The 11th frozen app (logi-options+) uses a custom script that was already correct and in sync. # Checklist for submitter - [x] Changes file added for user-visible changes in `changes/` (`changes/50056-fma-install-scripts-ignore-errors`). - [x] Untrusted data interpolated into shell scripts is validated against shell metacharacters. (No new untrusted interpolation: the guard reuses the same curated cask-derived name the adjacent lines already interpolate.) ## Testing - [x] Added/updated automated tests (three generator tests: pkg, pkg-with-choices, cp-R restore — the last now pins the exact emitted block). - [x] All 19 updated output manifests validated: embedded scripts pass `bash -n`, refs match `sha256(script)[:8]`, refs map stays key-sorted like Go's encoder. - [x] QA'd all new/changed functionality manually. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * macOS Fleet-maintained app installations now fail fast when installers, DMG extraction/mounting, or app copy steps error. * If an upgrade fails, the system removes any partial app and restores the previously installed version when available. * Improved robustness during app staging/copying, including safer handling of paths with spaces or special characters. * **Tests** * Added unit coverage to verify installer failure propagation and rollback behavior. * **Documentation** * Clarified that the install-script error handling applies to both generated and custom scripts, including already-published frozen apps. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Allen Houchins <allenhouchins@mac.com> |
||
|
|
e383c42da6 |
Update Fleet-maintained apps (#50230)
Automated ingestion of latest Fleet-maintained app data. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Updated Proton Drive for Windows to version 3.0.4. * Refreshed the installer download reference and checksum verification. * Improved uninstall behavior by adding a pre-uninstall stop for running Proton Drive processes and introducing a timeout-based “watchdog” to prevent the uninstaller from hanging. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com> Co-authored-by: Allen Houchins <allenhouchins@mac.com> |
||
|
|
344e5aa5a2 |
Remove Dynalist macOS Fleet-maintained app (cask deleted from homebrew-cask) (#50215)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** NA — fixing a failing scheduled "Update Fleet-maintained apps" run. Removes the **macOS** Dynalist Fleet-maintained app. The Windows (winget) FMA is unaffected and stays. ## Why The `dynalist` cask was deleted from homebrew-cask on 2026-07-30 ([commit `adac21ffc4`](https://github.com/Homebrew/homebrew-cask/commit/adac21ffc401)), completing Homebrew's full deprecation lifecycle: - `deprecate!` 2024-07-29, `because: :unmaintained` - `disable!` 2025-07-29 - cask file removed 2026-07-30 `https://formulae.brew.sh/api/cask/dynalist.json` now returns 404, so the scheduled ingester panics: ``` {"level":"INFO","msg":"ingesting homebrew app","name":"Dynalist"} panic: ingesting homebrew app: app not found in brew API ``` Marking the app `"frozen": true` does **not** fix this — the ingester fetches the cask JSON before the frozen flag is consulted (`cmd/maintained-apps/main.go`), so removal is the only fix for a dead upstream cask. ## What changed Deletions only (39 lines, no additions): - `ee/maintained-apps/inputs/homebrew/dynalist.json` — deleted - `ee/maintained-apps/outputs/dynalist/darwin.json` — deleted - the `dynalist/darwin` entry in `ee/maintained-apps/outputs/apps.json` — removed; `dynalist/windows` remains ## Deliberately kept Because the Windows FMA still needs them: - `ee/maintained-apps/outputs/dynalist/windows.json`, `ee/maintained-apps/inputs/winget/dynalist.json`, and its install/uninstall scripts - `frontend/pages/SoftwarePage/components/icons/Dynalist.tsx` and its `dynalist:` mapping in `icons/index.ts` — the map is keyed by lowercased app name and is shared across platforms - `website/assets/images/app-icon-dynalist-60x60@2x.png` — keyed by slug token, still serving the Windows entry in the app library ## Note for reviewers Hosts that currently have the macOS Dynalist FMA installed will lose the maintained-app entry on the next sync. This matches the behavior of prior FMA removals (Nocturnal #50050, Dell Display Manager #47420, Messenger #46541). # Checklist for submitter - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. Not applicable — consistent with prior FMA removal PRs, which do not add a changes file. ## Testing - [x] QA'd all new/changed functionality manually Verified that `ee/maintained-apps/outputs/apps.json` still parses as valid JSON (1381 apps) and that `Dynalist` now resolves to only `dynalist/windows`. Confirmed the 404 against the brew API and read the pre-removal cask at `adac21ffc4~1` to establish the deprecation reason. `git diff` confirms the change is deletions-only. |
||
|
|
ddf3e96fa9 |
Update Fleet-maintained apps (#50150)
Automated ingestion of latest Fleet-maintained app data. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Versions** * Updated release metadata and installer details for AnyBurn, BetterDisplay, Blender, ChatGPT, ChatWise, CLion, DataGrip, Dataspell, Draw.io Desktop, Elgato Camera Hub, Firefox, Firefox Nightly, GIMP, GoLand, IntelliJ IDEA (and variants), Keka, Kitty, LibreOffice, MacPacker, MuseScore, Nudge, OBS, PhpStorm, PyCharm (CE), Rider, RubyMine, RustRover, Spyder, Typinator, Visual Studio Code, VLC, WebStorm, Wispr Flow, XLD, and others. * Refreshed app version detection and package checksums accordingly. * **Bug Fixes** * Improved uninstall reliability on macOS and Windows by removing unintended extra cleanup actions while keeping application and user-data removal. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com> Co-authored-by: Allen Houchins <allenhouchins@mac.com> |
||
|
|
f4d7064f9a |
Add Rtools as a Windows FMA (#50028)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** #50020 # What this does Adds **Rtools** as a Windows Fleet-maintained app. One of the 11 apps split out of #48501 that failed the FMA validator; #50016 shipped the 6 that passed. ## Why it was failing The install script hit the validator's 10-minute `executeScript` cap exactly: ``` 20:41:22 INFO msg="Executing install script..." app=Rtools 20:51:22 ERROR msg="Error executing install script: exit status 1" # exactly 10:00 later 20:51:22 WARN msg="failed to remove rtools45-6768-6492.exe: ... Access is denied." ``` The locked installer in the temp dir shows a process was still alive. `Start-Process -Wait` waits for the process *and all of its descendants*, which is the same root cause as the other install-timeout apps in this batch. Rtools is also the one app in the batch where a **slow unpack** is a plausible second cause — the installer is ~460 MB and expands a full toolchain. So rather than assume, the script now waits on the installer process alone with a 480s cap (under the caller's 10-minute budget) and logs elapsed time plus Add/Remove Programs registration state on every poll. If the cap is reached: - **registered** → the install finished and only a lingering child remains, so it stops that process and succeeds; - **not registered** → the unpack genuinely didn't finish, and it fails with that stated explicitly. Either way the CI log now says which one happened instead of just timing out. ## Notes - **Identity verified against the installer**, not winget metadata. The setup stub's PE version resource reads `CompanyName: The R Foundation`, `ProductName: Rtools`. Inno derives `VersionInfoCompany` from `AppPublisher`, so the ARP publisher is `The R Foundation` — which is what the exists query uses. - **Versioned ARP name.** The registry `DisplayName` is `Rtools 4.5 (6768-6492)`, so the input uses `fuzzy_match_name` and the exists query is `name LIKE 'Rtools %'`. - Installs to `C:\rtools45`, not Program Files, so the validator's "no changes detected in `C:\Program Files`" line is an expected warning, not a failure. - Ships a new catalog icon and website asset. # 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] FMA CI validator (install → detect → uninstall) **passes** on the SYSTEM-context Windows runner — [run 30384196159](https://github.com/fleetdm/fleet/actions/runs/30384196159) (`All checks passed`) - [x] Generated output verified locally: manifest SHA matches the winget manifest, exists/patched queries checked against the installer's PE version resource, `apps.json` is valid JSON with a description filled in. - [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 Rtools as a supported Windows application. * Added installation and uninstallation support with silent setup and silent removal. * Added Rtools version metadata, installer verification, and Developer tools categorization. * Added a dedicated Rtools icon for software listings. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
ea3f95ccc5 |
Add Google Earth Pro as a Windows FMA (#50022)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** #50020 # What this does Adds **Google Earth Pro** as a Windows Fleet-maintained app (a Windows counterpart to the existing `google-earth-pro/darwin` FMA). One of the 11 apps split out of #48501 that failed the FMA validator; #50016 shipped the 6 that passed. ## Why it was failing Install and detection were already fine on the SYSTEM-context Windows runner — osquery found `Google Earth Pro` 7.3.7.1155. **Uninstall** was the failure: ``` INFO msg="Executing uninstall script for app..." app="Google Earth Pro" INFO msg="Found app: 'Google Earth Pro' at , Version: 7.3.7.1155" ERROR msg="App still present after uninstall (expected no match for version '7.3.7.1155' in programs)" ``` The EXE wraps a WiX MSI, so the ARP `UninstallString` is `MsiExec.exe /X{ProductCode}` — with **no quiet switch**. The old script ran that string verbatim, which raises a confirmation dialog in session 0 where nothing can click it, so the uninstall silently no-ops. The uninstall script now resolves the MSI product code (from the `UninstallString`, falling back to the registry key name) and runs `msiexec /x <code> /quiet /norestart` with a bounded 5-minute wait, then drains child `msiexec` processes. `3010`/`1641` are treated as success. ## Notes - **Identity verified against the real installer**, not winget metadata. The installer's embedded MSI Property table reads: `ProductName` = `Google Earth Pro`, `Manufacturer` = `Google`, `ProductVersion` = `7.3.7.1155`, `ALLUSERS` = `1`, `ProductCode` = `{E3B69BB6-FFD8-441C-933E-BB8A3136ED8F}`. No `ARPSYSTEMCOMPONENT`, so it is not a bootstrapper. That confirms `unique_identifier` = `Google Earth Pro` and the exists-query publisher `Google` (not "Google LLC"). - Installs to `C:\Program Files (x86)`, so the validator's "no changes detected in `C:\Program Files`" line is an expected warning, not a failure. - Reuses the existing `google earth pro` catalog icon — no new icon needed. # 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] FMA CI validator (install → detect → uninstall) **passes** on the SYSTEM-context Windows runner — [run 30383934805](https://github.com/fleetdm/fleet/actions/runs/30383934805) (`All checks passed`) - [x] Generated output verified locally: manifest SHA matches the winget manifest, exists/patched queries checked against the MSI Property table, `apps.json` is valid JSON with a description filled in. - [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 Google Earth Pro for Windows to the maintained app catalog. * Added maintained-apps install and uninstall support for Google Earth Pro (version 7.3.7.1155). * Included automated download integrity verification and detection logic for installed/updated versions. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
c61632305a |
Add Logitech Unifying Software as a Windows FMA (#50024)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** #50020 # What this does Adds **Logitech Unifying Software** as a Windows Fleet-maintained app. One of the 11 apps split out of #48501 that failed the FMA validator; #50016 shipped the 6 that passed. ## Why it was failing Install and detection were already fine on the SYSTEM-context Windows runner — osquery found `Logitech Unifying Software 2.52` at `C:\Program Files\Common Files\LogiShrd\Unifying`. **Uninstall** was the failure: ``` 20:40:55 INFO msg="Executing uninstall script for app..." 20:40:57 INFO msg="Found app: 'Logitech Unifying Software 2.52' ... Version: 2.52.33" 20:40:57 ERROR msg="App still present after uninstall (expected no match for version '2.52.33' in programs)" ``` Two seconds start to finish — the uninstaller hadn't actually done anything yet. This is standard NSIS behavior: the uninstaller copies itself to `%TEMP%` and relaunches, so the process the script starts exits almost immediately while the real work happens in a detached child. The fix passes NSIS's `_?=<dir>` switch, which runs the uninstaller in place instead of relaunching, making it synchronous. It has to be the last argument and unquoted, so the script builds a single argument string rather than an array (PowerShell would quote an element containing spaces). A bounded poll on the ARP key follows as a backstop, and the script fails explicitly if the entry is still there. ## Notes - **Versioned ARP name.** The registry `DisplayName` is `Logitech Unifying Software 2.52`, so the input uses `fuzzy_match_name` and the exists query is `name LIKE 'Logitech Unifying Software %'`. The uninstall script matches the same prefix rather than an exact string. - Publisher `Logitech` confirmed against the winget locale manifest. - Installs under `C:\Program Files\Common Files`, so the validator's "no changes detected in `C:\Program Files`" line is an expected warning, not a failure. - Ships a new catalog icon and website asset. # 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] FMA CI validator (install → detect → uninstall) **passes** on the SYSTEM-context Windows runner — [run 30384010810](https://github.com/fleetdm/fleet/actions/runs/30384010810) (`All checks passed`) - [x] Generated output verified locally: manifest SHA matches the winget manifest, exists/patched queries reviewed for name + publisher correctness, `apps.json` is valid JSON with a description filled in. - [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 Logitech Unifying Software to the Windows software catalog, including the version 2.52.33 download, checksum, and install-detection metadata. * Implemented silent installation and a robust, registry-aware uninstall flow (with process lock handling and timeout behavior). * Added a dedicated Logitech Unifying Software icon to the software page UI. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
cfbb5a59fa |
Add GNU Privacy Guard as a Windows FMA (#50025)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** #50020 # What this does Adds **GNU Privacy Guard** as a Windows Fleet-maintained app. One of the 11 apps split out of #48501 that failed the FMA validator; #50016 shipped the 6 that passed. ## Why it was failing The install itself worked — the validator logged `New application detected at: C:\Program Files\GnuPG`. The *script* never returned: ``` 20:18:36 INFO msg="Executing install script..." app="GNU Privacy Guard" 20:28:36 ERROR msg="Error executing install script: exit status 1" # exactly 10:00 later 20:28:36 INFO msg="New application detected at: C:\Program Files\GnuPG" ``` Ten minutes on the nose is the validator's `executeScript` timeout. The cause is a PowerShell detail rather than anything wrong with the installer: **`Start-Process -Wait` waits for the process *and all of its descendants***. GnuPG's installer starts `gpg-agent`, `dirmngr`, `keyboxd` and `scdaemon` and leaves them resident, so `-Wait` never returns. The same run left the installer `.exe` locked in the validator's temp dir, which is the other tell that a child process was still alive. The install script now follows the pattern already established by [`ollama_install.ps1`](ee/maintained-apps/inputs/winget/scripts/ollama_install.ps1): start with `-PassThru` (no `-Wait`), wait on the installer process alone with a 7-minute cap (below the caller's 10-minute script budget), poll for the Add/Remove Programs entry so a fast-returning installer can't be mistaken for a finished one, then stop the daemons. Stopping the daemons also fixes the uninstall, which would otherwise fail on files those processes hold open. The uninstall script stops them up front, uses NSIS's `_?=<dir>` switch so the uninstaller runs in place instead of relaunching itself detached from `%TEMP%`, and polls the ARP key to confirm removal. ## Notes - Clean ARP `DisplayName` (`GNU Privacy Guard`), so exact name matching — no `fuzzy_match_name` needed. Publisher `The GnuPG Project`. - Ships a new catalog icon and website asset. # 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] FMA CI validator (install → detect → uninstall) **passes** on the SYSTEM-context Windows runner — [run 30384069714](https://github.com/fleetdm/fleet/actions/runs/30384069714) (`All checks passed`) - [x] Generated output verified locally: manifest SHA matches the winget manifest, exists/patched queries reviewed for name + publisher correctness, `apps.json` is valid JSON with a description filled in. - [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 GNU Privacy Guard as a supported Windows application in the maintained apps catalog. * Added install/upgrade detection and uninstall support for Windows. * Added GNU Privacy Guard to the software catalog (Security category). * Added a dedicated GNU Privacy Guard icon to the software interface for proper name-based display. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
2fc41c7592 |
Add Azure Data Studio as a Windows FMA (#50027)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** #50020 # What this does Adds **Azure Data Studio** as a Windows Fleet-maintained app. One of the 11 apps split out of #48501 that failed the FMA validator; #50016 shipped the 6 that passed. ## Why it was failing The install itself worked — the validator logged `New application detected at: C:\Program Files\Azure Data Studio`. The *script* never returned: ``` 20:08:19 INFO msg="Executing install script..." app="Azure Data Studio" 20:18:19 ERROR msg="Error executing install script: exit status 1" # exactly 10:00 later 20:18:19 INFO msg="New application detected at: C:\Program Files\Azure Data Studio" ``` Ten minutes on the nose is the validator's `executeScript` timeout. Azure Data Studio is a Visual Studio Code fork and ships the same Inno Setup script — including the **`runcode` task, which launches the app when the install finishes**. Because `Start-Process -Wait` waits for the process *and all of its descendants*, the launched app kept the script blocked forever. The fix is the switch VS Code's own FMA already uses: `/MERGETASKS=!runcode` (see [`vscode_install.ps1`](ee/maintained-apps/inputs/winget/scripts/vscode_install.ps1) and [`vscodium_install.ps1`](ee/maintained-apps/inputs/winget/scripts/vscodium_install.ps1), both of which pass validation). The script also waits on the installer process alone rather than its descendants, polls for the Add/Remove Programs entry, and stops a stray `azuredatastudio` process as a backstop in case a future build ignores the task suppression. ## Notes - Machine-scope x64 installer, per the winget manifest — Azure Data Studio publishes both user and machine scope, and Fleet installs run as SYSTEM, so machine scope is required. - Clean ARP `DisplayName` (`Azure Data Studio`), so exact name matching. Publisher `Microsoft Corporation`. - Uninstall is unchanged: the Inno uninstaller doesn't leave anything resident, and `-Wait` waiting on descendants is the desired behavior there (Inno relaunches itself from `%TEMP%`). - Ships a new catalog icon and website asset. # 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] FMA CI validator (install → detect → uninstall) **passes** on the SYSTEM-context Windows runner — [run 30384162280](https://github.com/fleetdm/fleet/actions/runs/30384162280) (`All checks passed`) - [x] Generated output verified locally: manifest SHA matches the winget manifest, exists/patched queries reviewed for name + publisher correctness, `apps.json` is valid JSON with a description filled in. - [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 Azure Data Studio to the available Windows software catalog. * Added support for installing and uninstalling Azure Data Studio (version 1.52.0) via silent installer and uninstaller flows with completion detection. * Added an Azure Data Studio icon to the software interface for better visual identification. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
1e8b96e03d |
Remove Yubikey Manager as a macOS FMA (#50109)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** N/A — fixes the failing scheduled "Update Fleet-maintained apps" workflow The `yubico-yubikey-manager` cask was removed from homebrew-cask on 2026-07-28 ([Homebrew/homebrew-cask@7ffabaa](https://github.com/Homebrew/homebrew-cask/commit/7ffabaad8fcc657dc90343844ad76a50bb60b945)) after being disabled on 2025-07-27 `because: :discontinued, replacement_cask: "yubico-authenticator"` — Yubico discontinued `yubikey-manager-qt` (the 1.2.5 installer this FMA pinned) in favor of Yubico Authenticator. The brew API now returns 404 for the token, so the maintained-apps ingester panics: ``` {"level":"INFO","msg":"ingesting homebrew app","name":"Yubikey Manager"} panic: ingesting homebrew app: app not found in brew API ``` Freezing the app in #50054 did not resolve this: `fetchCask` runs before the `frozen` flag is applied, so the ingester still fetches the cask and fails on the 404. This is the follow-up that PR called out. Removes Yubikey Manager as a **macOS** Fleet-maintained app, following the same pattern as #50050 (Nocturnal), #46541 (Messenger), and #47420 (Dell Display Manager): - `ee/maintained-apps/inputs/homebrew/yubico-yubikey-manager.json` — Homebrew input - `ee/maintained-apps/outputs/yubico-yubikey-manager/darwin.json` — macOS output data - `ee/maintained-apps/outputs/apps.json` — the `yubico-yubikey-manager/darwin` entry - `website/config/routes.js` — the bare `/software-catalog/yubico-yubikey-manager` redirect pointed at `-darwin`, which would now 404; retargeted to `-windows` The **Windows** FMA is unaffected and continues to update, so these are deliberately kept: - `ee/maintained-apps/inputs/winget/yubico-yubikey-manager.json` and its install/uninstall scripts - `ee/maintained-apps/outputs/yubico-yubikey-manager/windows.json` - the `yubico-yubikey-manager/windows` entry in `apps.json` - `frontend/pages/SoftwarePage/components/icons/YubikeyManager.tsx` and its `"yubikey manager"` mapping in `index.ts` - `website/assets/images/app-icon-yubico-yubikey-manager-60x60@2x.png` Also drops "Requires Rosetta 2." from the Windows entry's description in `apps.json`. Rosetta is macOS-only; the sentence was copy-pasted from the macOS entry, and with macOS gone the Windows page is what `/software-catalog/yubico-yubikey-manager` now resolves to. Descriptions in `apps.json` are hand-maintained — `updateAppsListFile` in `cmd/maintained-apps/main.go` only appends entries whose slug it doesn't already find, so it won't overwrite the edit. # 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: - `go run ./cmd/maintained-apps -slug yubico-yubikey-manager/darwin` exits 0 with no panic and writes no files (before this change, the same run panicked on the brew 404). - `apps.json` still parses and holds 1377 apps; the only remaining `yubico-yubikey-manager` entry is `/windows`. - Grepped the repo for `yubico-yubikey-manager`: remaining hits are the winget input, its two script paths, the windows `apps.json` entry, and the retargeted website redirect. No automated tests added — this is a data-file removal with no new code paths. |
||
|
|
4b8a8435af |
Amend Docker Desktop patch policy SQL (#50041)
My workstation has Docker Desktop 4.84.0 (latest as of today) and was incorrectly failing the "macOS - Docker Desktop up to date" patch policy. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Improved Docker Desktop patch-status detection on macOS by excluding application paths containing `.back` anywhere in the path, avoiding incorrect patching of nested/backup bundles. - **Improvements** - Enhanced Docker Desktop install and uninstall cleanup to remove stale `Docker.app.back` artifacts and related staged in-progress update copies (including cleanup during upgrade timing). - **Tests** - Updated macOS Docker Desktop ingestion/patched check expectations to match the new `.back` path filtering behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Allen Houchins <allenhouchins@mac.com> |
||
|
|
95008e853d |
Freeze the macOS Yubikey Manager FMA (#50054)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** N/A Pins the macOS Fleet-maintained app for Yubikey Manager at its current output version, `1.2.5`, by setting `"frozen": true` on the Homebrew input. - `ee/maintained-apps/inputs/homebrew/yubico-yubikey-manager.json` — added `"frozen": true` The flag is read by the ingester into the manifest ([`homebrew/ingester.go`](https://github.com/fleetdm/fleet/blob/main/ee/maintained-apps/ingesters/homebrew/ingester.go)) and then consumed in two places: - [`cmd/maintained-apps/main.go`](https://github.com/fleetdm/fleet/blob/main/cmd/maintained-apps/main.go) skips overwriting `outputs/yubico-yubikey-manager/darwin.json` when the output file already exists, so the published version, installer URL, SHA256, and patch-policy query stop moving. - [`cmd/maintained-apps/validate/main.go`](https://github.com/fleetdm/fleet/blob/main/cmd/maintained-apps/validate/main.go) skips the app entirely during validation. `frozen` is tagged `json:"-"` on the manifest struct, so it does not appear in the output JSON — that file is intentionally left untouched by this PR. The Windows FMA (`inputs/winget/yubico-yubikey-manager.json`) is deliberately **not** frozen and continues to update. ## Note for reviewers While preparing this change I found that the `yubico-yubikey-manager` cask has been **removed from homebrew-cask**: ``` https://formulae.brew.sh/api/cask/yubico-yubikey-manager.json → 404 ``` The full cask list now contains only `pallotron-yubiswitch`, `yubico-authenticator`, and `yubihsm2-sdk`, and the token is not present in `inputs/homebrew/custom-tap/` either. This matches upstream: Yubico discontinued `yubikey-manager-qt` (the 1.2.5 installer this FMA pins) in favor of Yubico Authenticator. **Freezing does not resolve that 404.** The ingester fetches cask metadata *before* the frozen flag is applied, so the scheduled "Update Fleet-maintained apps" workflow is still expected to fail for this app with: ``` panic: ingesting homebrew app: app not found in brew API ``` Fully resolving that would mean removing the macOS FMA, the way #50050 did for Nocturnal (input, output, `apps.json` entry, frontend icon + mapping, website PNG). This PR is scoped to the freeze only, per the request; the removal can be a follow-up if that is the direction we want. # 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 — confirmed the edited input still parses as JSON, and traced the `frozen` flag through the ingester into both the output-write skip and the validation skip. No automated tests were added; this is a single data-file flag with no new code paths. --------- Co-authored-by: Kitzy <kitzy@kitzy.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> |
||
|
|
3ce3e238ed |
Add 6 Windows Fleet-maintained apps (#50016)
**Related issue:** N/A — Windows Fleet-maintained app (FMA) coverage for apps found deployed in a customer's ManageEngine SDP environment but missing from Fleet. ## What this does Adds **6** Windows Fleet-maintained apps — the subset of a larger batch that passes the FMA validator cleanly. Each has a winget-sourced input, a generated output manifest, and a catalog icon. Detection identity was verified against each app's real registry DisplayName; apps whose DisplayName carries a version suffix use fuzzy name matching, the rest match exactly. **MSI (clean, auto upgrade-code uninstall):** - **Git Extensions** — versioned ARP name (`Git Extensions 7.2.0.92`) → fuzzy match - **TightVNC**, **Yarn**, **SonicWall NetExtender** (WiX), **Zoom Outlook Plugin** — clean ARP names → exact match **EXE — NSIS (custom `/S` install + registry-lookup uninstall):** - **Spyder** — versioned ARP name (`Spyder 6`) → fuzzy match ## Notes - **Detection verification.** Every app's `unique_identifier` (registry DisplayName / osquery `programs.name`) and publisher were verified per the `new-fma` skill against winget `AppsAndFeaturesEntries`, MSI Property tables (`msiinfo`), and vendor installer scripts — not assumed. Git Extensions' MSI `ProductName` is `Git Extensions 7.2.0.92` and Spyder's ARP entry is `Spyder 6`, so both need `fuzzy_match_name`; the four exact-match apps were confirmed clean (e.g. TightVNC registers as `TightVNC`, not a versioned string). - **Validated on a real Windows host.** All six pass the FMA CI validator (install → detect → uninstall) on the SYSTEM-context Windows runner. - **Icons.** Git Extensions, SonicWall NetExtender, TightVNC, Yarn, and Zoom Outlook Plugin ship new catalog icons + website assets; Spyder reuses the existing `Spyder` icon. ## Testing - [x] FMA CI validator (install → detect → uninstall) on the SYSTEM-context Windows runner. - Generated outputs verified locally: all 6 produce valid manifests; MSI apps carry the correct UpgradeCode-based uninstall; exists/patched queries reviewed for name + publisher correctness; `go test ./ee/maintained-apps/...` passes. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added maintained Windows catalog entries for Git Extensions, SonicWall NetExtender, Spyder, TightVNC, Yarn, and Zoom Outlook Plugin, including silent install, version upgrade detection, and maintenance-ready uninstall flows. * Added new software icons for these apps and expanded icon matching so they display correctly in the catalog. * **Bug Fixes** * Improved Spyder Windows uninstall targeting and command/argument handling for more reliable removals. * **Documentation** * Refreshed Spyder supported version details to 6.1.5. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Allen Houchins <allenhouchins@mac.com> |
||
|
|
aea7c4068f |
Remove Nocturnal as a macOS FMA (#50050)
**Related issue:** N/A — fixes the failing scheduled "Update Fleet-maintained apps" workflow The `nocturnal` cask was removed from homebrew-cask on 2026-07-28 ([Homebrew/homebrew-cask@517db75](https://github.com/Homebrew/homebrew-cask/commit/517db75b78)) after being deprecated on 2024-07-27 and disabled on 2025-07-27, both `because: :unmaintained` (upstream repo's last push was in 2018). The brew API now returns 404 for it, so the maintained-apps ingester panics: ``` panic: ingesting homebrew app: app not found in brew API ``` This removes Nocturnal as a Fleet-maintained app, following the same pattern as #46541 (Messenger) and #47420 (Dell Display Manager): - `ee/maintained-apps/inputs/homebrew/nocturnal.json` — Homebrew input - `ee/maintained-apps/outputs/nocturnal/darwin.json` — macOS output data - `ee/maintained-apps/outputs/apps.json` — Nocturnal entry - `frontend/pages/SoftwarePage/components/icons/Nocturnal.tsx` and its import/mapping in `index.ts` - `website/assets/images/app-icon-nocturnal-60x60@2x.png` # 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 (verified `apps.json` still parses, no remaining `nocturnal` references, ESLint passes on the icons index) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Removed Apps** - Removed Nocturnal from the maintained application catalog. - Removed its installation and uninstallation support. - Removed the Nocturnal icon from software listings. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |