From b746b7e55066535fd5f0f29d6c8ee4e089d87fb2 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:01:58 +0000 Subject: [PATCH 01/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- website/assets/js/pages/try-fleet/sandbox-teleporter.page.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/assets/js/pages/try-fleet/sandbox-teleporter.page.js b/website/assets/js/pages/try-fleet/sandbox-teleporter.page.js index 964af18ca6c..391ad652428 100644 --- a/website/assets/js/pages/try-fleet/sandbox-teleporter.page.js +++ b/website/assets/js/pages/try-fleet/sandbox-teleporter.page.js @@ -20,7 +20,7 @@ parasails.registerPage('sandbox-teleporter', { window.history.replaceState({}, '', '/'); // Binding an event handler to 'onpageshow', if a user navigates to a locally cached version of this page (e.g., A Safari user clicking the back button from their Fleet Sandbox), they will be taken to the fleetdm.com homepage. - window.onpageshow = function(event) { + window.onpageshow = (event) => { if(event.persisted) { this.goto('/'); } From ae86306734eee17e31bb06ef35dd3ea914ea8f8c Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:00 +0000 Subject: [PATCH 02/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../AppleMdmPage/components/content/ApplePushCertSetup.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleMdmPage/components/content/ApplePushCertSetup.tsx b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleMdmPage/components/content/ApplePushCertSetup.tsx index 8d52f0238f3..0c0c6e851aa 100644 --- a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleMdmPage/components/content/ApplePushCertSetup.tsx +++ b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleMdmPage/components/content/ApplePushCertSetup.tsx @@ -29,6 +29,7 @@ const ApplePushCertSetup = ({ try { await mdmAppleApi.uploadApplePushCertificate(files[0]); renderFlash("success", "MDM turned on successfully."); + setIsUploading(false); onSetupSuccess(); } catch (e) { const msg = getErrorReason(e); From d7f93a9a8ea6f4ec06fadebc0eeb4ace890416e8 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:01 +0000 Subject: [PATCH 03/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- server/mdm/nanodep/proxy/proxy.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/mdm/nanodep/proxy/proxy.go b/server/mdm/nanodep/proxy/proxy.go index 1e55289658a..a70145f8898 100644 --- a/server/mdm/nanodep/proxy/proxy.go +++ b/server/mdm/nanodep/proxy/proxy.go @@ -79,6 +79,8 @@ func newDirector(store client.ConfigRetriever, logger log.Logger) func(*http.Req config, err := store.RetrieveConfig(req.Context(), name) if err != nil { logger.Info("msg", "retrieve config", "err", err) + // do not cache a broken URL derived from a failed config lookup + return } url, err = url.Parse(config.BaseURL) if err != nil { From 7071dbaac6d2ce19b3e0aab5b9dfb0a4625b2d40 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:02 +0000 Subject: [PATCH 04/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- tools/github-manage/pkg/ghapi/projects.go | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/tools/github-manage/pkg/ghapi/projects.go b/tools/github-manage/pkg/ghapi/projects.go index 3b2a6cd56a0..ed43c0441ef 100644 --- a/tools/github-manage/pkg/ghapi/projects.go +++ b/tools/github-manage/pkg/ghapi/projects.go @@ -58,6 +58,16 @@ func getAliasKeys() []string { return keys } +// escapeGraphQLString escapes backslashes and double quotes so a value can be +// safely embedded inside a double-quoted GraphQL string literal. +func escapeGraphQLString(s string) string { + s = strings.ReplaceAll(s, `\`, `\\`) + s = strings.ReplaceAll(s, `"`, `\"`) + s = strings.ReplaceAll(s, "\n", `\n`) + s = strings.ReplaceAll(s, "\r", `\r`) + return s +} + // ParseJSONtoProjectItems converts JSON data to a slice of ProjectItem structs. func ParseJSONtoProjectItems(jsonData []byte, limit int) ([]ProjectItem, int, error) { var items ProjectItemsResponse @@ -257,7 +267,7 @@ func SetProjectItemFieldValue(itemID string, projectID int, fieldName, value str // For number fields (like Estimate) - try different possible type names if field.Type == "NUMBER" || field.Type == "ProjectV2Field" || strings.Contains(strings.ToLower(field.Type), "number") { command := fmt.Sprintf(`gh api graphql -f query='mutation { updateProjectV2ItemFieldValue(input: { projectId: "%s", itemId: "%s", fieldId: "%s", value: { number: %s } }) { projectV2Item { id } } }'`, - projectNodeID, itemID, field.ID, value) + escapeGraphQLString(projectNodeID), escapeGraphQLString(itemID), escapeGraphQLString(field.ID), escapeGraphQLString(value)) _, err := RunCommandAndReturnOutput(command) if err != nil { @@ -288,7 +298,7 @@ func SetProjectItemFieldValue(itemID string, projectID int, fieldName, value str } command := fmt.Sprintf(`gh api graphql -f query='mutation { updateProjectV2ItemFieldValue(input: { projectId: "%s", itemId: "%s", fieldId: "%s", value: { singleSelectOptionId: "%s" } }) { projectV2Item { id } } }'`, - projectNodeID, itemID, field.ID, optionID) + escapeGraphQLString(projectNodeID), escapeGraphQLString(itemID), escapeGraphQLString(field.ID), escapeGraphQLString(optionID)) _, err = RunCommandAndReturnOutput(command) if err != nil { @@ -313,7 +323,7 @@ func SetProjectItemFieldValue(itemID string, projectID int, fieldName, value str // Use GraphQL mutation with the actual current iteration ID command := fmt.Sprintf(`gh api graphql -f query='mutation { updateProjectV2ItemFieldValue(input: { projectId: "%s", itemId: "%s", fieldId: "%s", value: { iterationId: "%s" } }) { projectV2Item { id } } }'`, - projectNodeID, itemID, field.ID, currentIterationID) + escapeGraphQLString(projectNodeID), escapeGraphQLString(itemID), escapeGraphQLString(field.ID), escapeGraphQLString(currentIterationID)) out, err := RunCommandAndReturnOutput(command) if err != nil { @@ -332,7 +342,7 @@ func SetProjectItemFieldValue(itemID string, projectID int, fieldName, value str // For text fields if field.Type == "TEXT" || strings.Contains(strings.ToLower(field.Type), "text") { command := fmt.Sprintf(`gh api graphql -f query='mutation { updateProjectV2ItemFieldValue(input: { projectId: "%s", itemId: "%s", fieldId: "%s", value: { text: "%s" } }) { projectV2Item { id } } }'`, - projectNodeID, itemID, field.ID, value) + escapeGraphQLString(projectNodeID), escapeGraphQLString(itemID), escapeGraphQLString(field.ID), escapeGraphQLString(value)) _, err := RunCommandAndReturnOutput(command) if err != nil { @@ -344,7 +354,7 @@ func SetProjectItemFieldValue(itemID string, projectID int, fieldName, value str // If we can't determine the type, try to infer from field name or context if strings.EqualFold(fieldName, "Estimate") || strings.Contains(strings.ToLower(fieldName), "estimate") { command := fmt.Sprintf(`gh api graphql -f query='mutation { updateProjectV2ItemFieldValue(input: { projectId: "%s", itemId: "%s", fieldId: "%s", value: { number: %s } }) { projectV2Item { id } } }'`, - projectNodeID, itemID, field.ID, value) + escapeGraphQLString(projectNodeID), escapeGraphQLString(itemID), escapeGraphQLString(field.ID), escapeGraphQLString(value)) _, err := RunCommandAndReturnOutput(command) if err != nil { From 8e51aecf43f0346c147601ed5034dda245d98317 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:03 +0000 Subject: [PATCH 05/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../inputs/homebrew/scripts/microsoft_word_uninstall.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ee/maintained-apps/inputs/homebrew/scripts/microsoft_word_uninstall.sh b/ee/maintained-apps/inputs/homebrew/scripts/microsoft_word_uninstall.sh index f42f0bf7cb5..fdac953d268 100644 --- a/ee/maintained-apps/inputs/homebrew/scripts/microsoft_word_uninstall.sh +++ b/ee/maintained-apps/inputs/homebrew/scripts/microsoft_word_uninstall.sh @@ -134,7 +134,7 @@ remove_receipt_files() { fi echo "sudo pkgutil --only-files --files \"$PKGID\" | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" | tr '\\\\n' '\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf" - sudo pkgutil --only-files --files "$PKGID" | sed "s|^|/${INSTALL_LOCATION}/|" | tr '\n' '\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf + sudo pkgutil --only-files --files "$PKGID" | sed "s|^|${FULL_INSTALL_LOCATION}/|" | tr '\n' '\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf echo "sudo pkgutil --only-dirs --files \"$PKGID\" | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" | grep '\\.app$' | tr '\\\\n' '\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf" sudo pkgutil --only-dirs --files "$PKGID" | sed "s|^|${FULL_INSTALL_LOCATION}/|" | grep '\.app$' | tr '\n' '\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf @@ -188,3 +188,4 @@ trash $LOGGED_IN_USER '~/Library/Application Support/CrashReporter/Microsoft Wor trash $LOGGED_IN_USER '~/Library/Containers/com.microsoft.Word' trash $LOGGED_IN_USER '~/Library/Preferences/com.microsoft.Word.plist' trash $LOGGED_IN_USER '~/Library/Saved Application State/com.microsoft.Word.savedState' + From 2ae334aaa437d4ed3029b3c6d541b219dfaee1ba Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:05 +0000 Subject: [PATCH 06/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- ee/server/service/scep/sceptest/sceptest.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ee/server/service/scep/sceptest/sceptest.go b/ee/server/service/scep/sceptest/sceptest.go index 938e14f4482..3012c076bf1 100644 --- a/ee/server/service/scep/sceptest/sceptest.go +++ b/ee/server/service/scep/sceptest/sceptest.go @@ -11,7 +11,6 @@ import ( "crypto/x509" _ "embed" "encoding/binary" - "fmt" "log/slog" "net/http" "net/http/httptest" @@ -151,7 +150,7 @@ func NewTestDynamicChallengeServer(t *testing.T) *httptest.Server { dynamicChallengeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) - fmt.Println(r.URL.Path) + t.Logf("dynamic challenge request: %s", r.URL.Path) if _, err := w.Write([]byte("dynamic challenge")); err != nil { t.Errorf("write dynamic challenge response: %v", err) } From bf5d2f261db356d92c4413d5aff2fac34984535e Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:06 +0000 Subject: [PATCH 07/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- frontend/components/InfoBanner/InfoBanner.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frontend/components/InfoBanner/InfoBanner.tsx b/frontend/components/InfoBanner/InfoBanner.tsx index eea024a374b..69a67d03296 100644 --- a/frontend/components/InfoBanner/InfoBanner.tsx +++ b/frontend/components/InfoBanner/InfoBanner.tsx @@ -20,7 +20,8 @@ export interface IInfoBannerProps { cta?: JSX.Element; /** closable and link are mutually exclusive */ closable?: boolean; - icon?: IconNames; // TODO: This is unused but several banners have icons within children that can be refactored to use this for consistent styling + /** Renders an icon at the start of the banner message */ + icon?: IconNames; } const InfoBanner = ({ @@ -46,6 +47,9 @@ const InfoBanner = ({ const content = ( <> + {icon && ( + + )}
{children}
{(cta || closable) && ( From 65f637e569bbbe7d9f60ff4f4807cd356bc59db6 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:07 +0000 Subject: [PATCH 08/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../components/MDM/AppleBMTermsMessage/AppleBMTermsMessage.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/components/MDM/AppleBMTermsMessage/AppleBMTermsMessage.tsx b/frontend/components/MDM/AppleBMTermsMessage/AppleBMTermsMessage.tsx index e8d380e36f8..afbd0153588 100644 --- a/frontend/components/MDM/AppleBMTermsMessage/AppleBMTermsMessage.tsx +++ b/frontend/components/MDM/AppleBMTermsMessage/AppleBMTermsMessage.tsx @@ -13,7 +13,7 @@ const AppleBMTermsMessage = () => { cta={ { }; export default AppleBMTermsMessage; + From 16e56a387f8bcbd4888cf0d74d1f16400d32381f Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:08 +0000 Subject: [PATCH 09/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../components/AddEntraTenantModal/AddEntraTenantModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/components/AddEntraTenantModal/AddEntraTenantModal.tsx b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/components/AddEntraTenantModal/AddEntraTenantModal.tsx index 5932b44e34b..0dfa119cb6a 100644 --- a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/components/AddEntraTenantModal/AddEntraTenantModal.tsx +++ b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/components/AddEntraTenantModal/AddEntraTenantModal.tsx @@ -46,7 +46,7 @@ const AddEntraTenantModal = ({ onExit }: IAddEntraTenantModalProps) => { }; const onAddTenant = async () => { - const { tenantId } = formData; + const tenantId = formData.tenantId?.trim().toLowerCase(); const validation = validateFormData({ tenantId }); From 8e504f36ffebd749520e3a7154700b1ab01d6fa6 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:09 +0000 Subject: [PATCH 10/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../components/CommandDetailsModal/CommandDetailsModal.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/pages/hosts/components/CommandDetailsModal/CommandDetailsModal.tsx b/frontend/pages/hosts/components/CommandDetailsModal/CommandDetailsModal.tsx index f3f536283f8..6283a746287 100644 --- a/frontend/pages/hosts/components/CommandDetailsModal/CommandDetailsModal.tsx +++ b/frontend/pages/hosts/components/CommandDetailsModal/CommandDetailsModal.tsx @@ -220,8 +220,8 @@ const CommandResultsModal = ({ return { results: resp.results.map?.((r) => ({ ...r, - payload: atob(r.payload), - result: atob(r.result), + payload: r.payload ? atob(r.payload) : r.payload, + result: r.result ? atob(r.result) : r.result, })), }; }, @@ -246,3 +246,4 @@ const CommandResultsModal = ({ }; export default CommandResultsModal; + From a1e2b262217a86282d44ba5723b74de6cc8ffd6f Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:11 +0000 Subject: [PATCH 11/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../components/AddProfileModal/AddProfileModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/pages/ManageControlsPage/OSSettings/cards/ConfigurationProfiles/components/ProfileUploader/components/AddProfileModal/AddProfileModal.tsx b/frontend/pages/ManageControlsPage/OSSettings/cards/ConfigurationProfiles/components/ProfileUploader/components/AddProfileModal/AddProfileModal.tsx index df6e4bcdbad..69bc6c100d0 100644 --- a/frontend/pages/ManageControlsPage/OSSettings/cards/ConfigurationProfiles/components/ProfileUploader/components/AddProfileModal/AddProfileModal.tsx +++ b/frontend/pages/ManageControlsPage/OSSettings/cards/ConfigurationProfiles/components/ProfileUploader/components/AddProfileModal/AddProfileModal.tsx @@ -182,11 +182,11 @@ const AddProfileModal = ({ }); renderFlash("success", "Successfully uploaded."); onUpload(); + onDone(); } catch (e) { renderFlash("error", getErrorMessage(e as AxiosResponse)); } finally { setIsLoading(false); - onDone(); } }; From 58732c5ff131aca65142a2d0d9b95779e00381bd Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:12 +0000 Subject: [PATCH 12/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../components/BootstrapPackageUploader/helpers.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/pages/ManageControlsPage/SetupExperience/cards/BootstrapPackage/components/BootstrapPackageUploader/helpers.tsx b/frontend/pages/ManageControlsPage/SetupExperience/cards/BootstrapPackage/components/BootstrapPackageUploader/helpers.tsx index de70313206c..56e2dbe79fb 100644 --- a/frontend/pages/ManageControlsPage/SetupExperience/cards/BootstrapPackage/components/BootstrapPackageUploader/helpers.tsx +++ b/frontend/pages/ManageControlsPage/SetupExperience/cards/BootstrapPackage/components/BootstrapPackageUploader/helpers.tsx @@ -36,7 +36,7 @@ export const UPLOAD_ERROR_MESSAGES = { }; export const getErrorMessage = (err: AxiosResponse) => { - const apiReason = err.data.errors[0].reason; + const apiReason = err?.data?.errors?.[0]?.reason ?? ""; const error = Object.values(UPLOAD_ERROR_MESSAGES).find((errType) => errType.condition(apiReason) @@ -48,3 +48,4 @@ export const getErrorMessage = (err: AxiosResponse) => { return error.message; }; + From dd5be6f81c7ef7a318f195720fe8eb5208c6ee95 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:13 +0000 Subject: [PATCH 13/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../FleetMaintainedAppDetailsPage/helpers.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/frontend/pages/SoftwarePage/SoftwareAddPage/SoftwareFleetMaintained/FleetMaintainedAppDetailsPage/helpers.tsx b/frontend/pages/SoftwarePage/SoftwareAddPage/SoftwareFleetMaintained/FleetMaintainedAppDetailsPage/helpers.tsx index 61295d1020b..1c10dbdcc61 100644 --- a/frontend/pages/SoftwarePage/SoftwareAddPage/SoftwareFleetMaintained/FleetMaintainedAppDetailsPage/helpers.tsx +++ b/frontend/pages/SoftwarePage/SoftwareAddPage/SoftwareFleetMaintained/FleetMaintainedAppDetailsPage/helpers.tsx @@ -53,6 +53,12 @@ export const getFleetAppPolicyQuery = (name: string) => { return getFleetAppData(name)?.automatic_policy_query; }; +// NOTE: This logic is duplicated (with minor variations) in +// SoftwareCustomPackage/helpers.tsx and SoftwareAddPage/helpers.tsx. If you +// change the timeout detection, the "already available" handling, or the +// secret-variable handling here, please make the equivalent change in those +// sibling files as well. TODO: extract a shared base implementation with +// pluggable extra-branch callbacks so this only needs to be maintained once. export const getErrorMessage = (err: unknown) => { const isTimeout = isAxiosError(err) && From 898dfdf9d8fd6db1dab6002c4f20364bdc2040df Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:14 +0000 Subject: [PATCH 14/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../pages/SoftwarePage/SoftwareInventory/SoftwareInventory.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/pages/SoftwarePage/SoftwareInventory/SoftwareInventory.tsx b/frontend/pages/SoftwarePage/SoftwareInventory/SoftwareInventory.tsx index 8e2949e608b..d2f5c254c75 100644 --- a/frontend/pages/SoftwarePage/SoftwareInventory/SoftwareInventory.tsx +++ b/frontend/pages/SoftwarePage/SoftwareInventory/SoftwareInventory.tsx @@ -31,6 +31,7 @@ const QUERY_OPTIONS = { interface ISoftwareInventoryProps { router: InjectedRouter; + location: { pathname: string }; isSoftwareEnabled: boolean; query: string; perPage: number; @@ -44,6 +45,7 @@ interface ISoftwareInventoryProps { const SoftwareInventory = ({ router, + location, isSoftwareEnabled, query, perPage, From c4f2dddc421baa0324983df8cb5357aa7a5c704b Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:16 +0000 Subject: [PATCH 15/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../SoftwareInventoryTable/SoftwareInventoryTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/pages/SoftwarePage/SoftwareInventory/SoftwareInventoryTable/SoftwareInventoryTable.tsx b/frontend/pages/SoftwarePage/SoftwareInventory/SoftwareInventoryTable/SoftwareInventoryTable.tsx index 1156aaba7f4..e4d6d442b99 100644 --- a/frontend/pages/SoftwarePage/SoftwareInventory/SoftwareInventoryTable/SoftwareInventoryTable.tsx +++ b/frontend/pages/SoftwarePage/SoftwareInventory/SoftwareInventoryTable/SoftwareInventoryTable.tsx @@ -156,7 +156,7 @@ const SoftwareTable = ({ let generateTableConfig: ITableConfigGenerator; if (data === undefined) { - tableData; + tableData = undefined; generateTableConfig = () => []; } else if (isSoftwareTitles(data)) { tableData = data.software_titles; From e35417b8e8f14b2d91ffbe95877fa5a974010812 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:17 +0000 Subject: [PATCH 16/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- orbit/cmd/orbit/shell.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/orbit/cmd/orbit/shell.go b/orbit/cmd/orbit/shell.go index 6fa3ac3aee4..d5b5f43a790 100644 --- a/orbit/cmd/orbit/shell.go +++ b/orbit/cmd/orbit/shell.go @@ -155,7 +155,7 @@ var shellCommand = &cli.Command{ // thrift extensions? pipeName := filepath.Join(c.String("root-dir"), "orbit-osquery.em") if runtime.GOOS == "windows" { - pipeName = `\\\\.\\pipe\\orbit-osquery-extension` + pipeName = `\\.\pipe\orbit-osquery-extension` } registerExtensionRunner( &g, From a26583ff1dbbc644af51c6a491f671f41e356b2e Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:18 +0000 Subject: [PATCH 17/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../tables/20240829170023_CreateVPPTokenTeamsJoinTable.go | 1 - 1 file changed, 1 deletion(-) diff --git a/server/datastore/mysql/migrations/tables/20240829170023_CreateVPPTokenTeamsJoinTable.go b/server/datastore/mysql/migrations/tables/20240829170023_CreateVPPTokenTeamsJoinTable.go index 747e2eea7ed..885f0c0845d 100644 --- a/server/datastore/mysql/migrations/tables/20240829170023_CreateVPPTokenTeamsJoinTable.go +++ b/server/datastore/mysql/migrations/tables/20240829170023_CreateVPPTokenTeamsJoinTable.go @@ -10,7 +10,6 @@ func init() { } func Up_20240829170023(tx *sql.Tx) error { - // Idempotent migration. // Idempotent migration. _, err := tx.Exec(` CREATE TABLE IF NOT EXISTS vpp_token_teams ( From 6f8d8607a3de88e453a071f62e9992bc09641044 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:19 +0000 Subject: [PATCH 18/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../tables/20250731151000_EnforceFileVaultAtLogin_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/datastore/mysql/migrations/tables/20250731151000_EnforceFileVaultAtLogin_test.go b/server/datastore/mysql/migrations/tables/20250731151000_EnforceFileVaultAtLogin_test.go index c14e3983539..05c284d2a9c 100644 --- a/server/datastore/mysql/migrations/tables/20250731151000_EnforceFileVaultAtLogin_test.go +++ b/server/datastore/mysql/migrations/tables/20250731151000_EnforceFileVaultAtLogin_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" ) -func TestUp_20250731151000(t *testing.T) { +func TestUp_20250723111413(t *testing.T) { db := applyUpToPrev(t) stmt := ` From 83bc615271922b6cdf2166688f87046a7e6ef390 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:20 +0000 Subject: [PATCH 19/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../20250904091745_AddCertificateAuthoritiesTable_test.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/server/datastore/mysql/migrations/tables/20250904091745_AddCertificateAuthoritiesTable_test.go b/server/datastore/mysql/migrations/tables/20250904091745_AddCertificateAuthoritiesTable_test.go index 0699797d7a6..27c402b0cc6 100644 --- a/server/datastore/mysql/migrations/tables/20250904091745_AddCertificateAuthoritiesTable_test.go +++ b/server/datastore/mysql/migrations/tables/20250904091745_AddCertificateAuthoritiesTable_test.go @@ -135,16 +135,12 @@ func TestUp_20250904091745(t *testing.T) { `INSERT INTO app_config_json(json_value) VALUES(?) ON DUPLICATE KEY UPDATE json_value = VALUES(json_value)`, jsonBytes, ) - if err != nil { - require.NoError(t, err, "failed to insert app_config_json") - } + require.NoError(t, err, "failed to insert app_config_json") _, err = db.Exec( `UPDATE app_config_json SET json_value = JSON_SET(json_value, '$.integrations', CAST(? AS JSON))`, integrationJSONBytes, ) - if err != nil { - require.NoError(t, err, "failed to insert integrations_json into app_config_json") - } + require.NoError(t, err, "failed to insert integrations_json into app_config_json") // Apply current migration. applyNext(t, db) From fb06890b9cf6055eb5ec7105d9e88259e4eeb478 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:21 +0000 Subject: [PATCH 20/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- server/vulnerabilities/nvd/cve.go | 38 ++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/server/vulnerabilities/nvd/cve.go b/server/vulnerabilities/nvd/cve.go index f2005718b24..cdd3f54cd81 100644 --- a/server/vulnerabilities/nvd/cve.go +++ b/server/vulnerabilities/nvd/cve.go @@ -230,6 +230,19 @@ func TranslateCPEToCVE( return nil, nil } + // Detect corrupted/empty CVE feed files up front by validating the feed shape/size + // directly, rather than inferring corruption from zero downstream vulnerability matches + // (which can legitimately happen on well-patched fleets). A feed file is considered + // invalid if it is empty (zero bytes) on disk. + feedFilesInvalid := false + for _, file := range files { + info, statErr := os.Stat(file) + if statErr != nil || info.Size() == 0 { + feedFilesInvalid = true + break + } + } + // get all the software CPEs from the database CPEs, err := ds.ListSoftwareCPEs(ctx) if err != nil { @@ -276,9 +289,10 @@ func TranslateCPEToCVE( // NVD feed file. softwareVulns := make(map[string]fleet.SoftwareVulnerability) osVulns := make(map[string]fleet.OSVulnerability) + totalCVEsSeen := 0 for _, file := range files { - foundSoftwareVulns, foundOSVulns, err := checkCVEs( + foundSoftwareVulns, foundOSVulns, cveCount, err := checkCVEs( ctx, logger, interfaceParsed, @@ -288,6 +302,7 @@ func TranslateCPEToCVE( if err != nil { return nil, err } + totalCVEsSeen += cveCount for _, e := range foundSoftwareVulns { softwareVulns[e.Key()] = e @@ -322,11 +337,12 @@ func TranslateCPEToCVE( osInsertErr = true } - // Detect corrupted/empty CVE feeds. If we had CPE/OS inputs to match against but produced - // zero results across every feed file, the feed is almost certainly empty or corrupted - // (e.g., a failed/corrupted artifact from GitHub) — skip the deletes so we don't wipe - // legitimate existing software_cve rows that will be re-matched on the next good sync. - feedProducedNoData := len(allSoftwareVulns) == 0 && len(allOSVulns) == 0 + // Detect corrupted/empty CVE feeds by validating the feed shape/size directly (empty feed + // files on disk, or zero CVE entries parsed across all feed files) instead of inferring + // corruption from zero downstream vulnerability matches. Legitimate feeds can produce zero + // new vulnerability matches (e.g., on small or well-patched fleets), and that alone should + // not prevent stale-vulnerability cleanup. + feedProducedNoData := feedFilesInvalid || totalCVEsSeen == 0 // Delete any stale vulnerabilities. A vulnerability is stale iff the last time it was // updated was more than `2 * periodicity` ago. This assumes that the whole vulnerability @@ -345,8 +361,8 @@ func TranslateCPEToCVE( } } if feedProducedNoData { - logger.ErrorContext(ctx, "NVD scan produced no matches with non-empty input; skipping deletes to preserve existing software_cve rows (feed may be corrupted)", - "software_cpes", len(parsed), "os_cpes", len(cpes), "feed_files", len(files)) + logger.ErrorContext(ctx, "NVD feed appears empty or corrupted; skipping deletes to preserve existing software_cve rows", + "software_cpes", len(parsed), "os_cpes", len(cpes), "feed_files", len(files), "cve_count", totalCVEsSeen) } return newVulns, nil @@ -419,10 +435,10 @@ func checkCVEs( cpeItems []itemWithNVDMeta, jsonFile string, knownNVDBugRules CPEMatchingRules, -) ([]fleet.SoftwareVulnerability, []fleet.OSVulnerability, error) { +) ([]fleet.SoftwareVulnerability, []fleet.OSVulnerability, int, error) { dict, err := cvefeed.LoadJSONDictionary(jsonFile) if err != nil { - return nil, nil, err + return nil, nil, 0, err } // Group dictionary by vendor using a map. @@ -564,7 +580,7 @@ func checkCVEs( logger.DebugContext(ctx, "cpes pushed") wg.Wait() - return foundSoftwareVulns, foundOSVulns, nil + return foundSoftwareVulns, foundOSVulns, len(dict), nil } var pythonVersionWithUpdate = regexp.MustCompile(`(alpha|beta|rc)(\d+)`) From 4e4b4cac78326083fcf16a5465c070f4b36eccdc Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:22 +0000 Subject: [PATCH 21/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- tools/github-manage/cmd/gm/issues_with_historical_label.go | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/github-manage/cmd/gm/issues_with_historical_label.go b/tools/github-manage/cmd/gm/issues_with_historical_label.go index 84c2a1397c0..f6d6ff00cca 100644 --- a/tools/github-manage/cmd/gm/issues_with_historical_label.go +++ b/tools/github-manage/cmd/gm/issues_with_historical_label.go @@ -46,6 +46,7 @@ var issuesWithHistoricalLabelCmd = &cobra.Command{ issues, err := ghapi.GetIssuesCreatedSinceWithLabel(repo, since, label, verbose, concurrency, olderThan) if err != nil { fmt.Fprintf(os.Stderr, "Error fetching issues: %v\n", err) + return } if len(issues) == 0 { From 43753f0319feb5f9d495dea06a3c67c1a12478b6 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:23 +0000 Subject: [PATCH 22/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- tools/github-manage/pkg/ghapi/cache.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/github-manage/pkg/ghapi/cache.go b/tools/github-manage/pkg/ghapi/cache.go index 6b11c1f8918..e16ffef42fc 100644 --- a/tools/github-manage/pkg/ghapi/cache.go +++ b/tools/github-manage/pkg/ghapi/cache.go @@ -17,6 +17,7 @@ var ( // MapProjectFieldNameToField caches project field metadata by project ID MapProjectFieldNameToField = map[int]map[string]ProjectField{} + projectFieldsMutex sync.RWMutex ) // generateProjectItemCacheKey creates a unique key for project item cache. @@ -42,6 +43,8 @@ func ClearProjectItemIDCache() { // ClearProjectFieldsCache clears the project fields cache. func ClearProjectFieldsCache() { + projectFieldsMutex.Lock() + defer projectFieldsMutex.Unlock() MapProjectFieldNameToField = make(map[int]map[string]ProjectField) } @@ -62,7 +65,9 @@ func GetCacheStats() map[string]interface{} { projectItemIDCount := len(projectItemIDCache) projectItemIDMutex.RUnlock() + projectFieldsMutex.RLock() fieldCacheCount := len(MapProjectFieldNameToField) + projectFieldsMutex.RUnlock() return map[string]interface{}{ "project_node_ids": projectNodeIDCount, @@ -79,3 +84,4 @@ func InvalidateProjectItemID(issueNumber, projectID int) { defer projectItemIDMutex.Unlock() delete(projectItemIDCache, cacheKey) } + From c7590c982d05939fae2e3d7dce4b5df84dba18ec Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:25 +0000 Subject: [PATCH 23/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../main/java/com/fleetdm/agent/ApiClient.kt | 56 ++++++++++--------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/android/app/src/main/java/com/fleetdm/agent/ApiClient.kt b/android/app/src/main/java/com/fleetdm/agent/ApiClient.kt index 8f62148f41a..6248ed3ac5b 100644 --- a/android/app/src/main/java/com/fleetdm/agent/ApiClient.kt +++ b/android/app/src/main/java/com/fleetdm/agent/ApiClient.kt @@ -257,15 +257,17 @@ object ApiClient : CertificateApiClient { val result = block() if (result.isFailure && result.exceptionOrNull() is UnauthorizedException) { Log.d(TAG, "Received 401, clearing node key and retrying with re-enrollment") - clearApiKey() + enrollmentMutex.withLock { + clearApiKey() + } return block() } return result } - suspend fun enroll(): Result { + suspend fun enroll(): Result = enrollmentMutex.withLock { val credentials = getEnrollmentCredentials() - credentials ?: return Result.failure(Exception("Credentials not set")) + credentials ?: return@withLock Result.failure(Exception("Credentials not set")) val resp = makeRequest( endpoint = "/api/fleet/orbit/enroll", method = "POST", @@ -286,7 +288,7 @@ object ApiClient : CertificateApiClient { Log.d(TAG, "Enrollment failed: ${exception.message}") } - return resp + resp } suspend fun getOrbitConfig(): Result = withReenrollOnUnauthorized { @@ -405,30 +407,29 @@ object ApiClient : CertificateApiClient { } private suspend fun getNodeKeyOrEnroll(): Result { - enrollmentMutex.withLock { - // Check again inside lock in case another coroutine just enrolled - val existingKey = getApiKey() - if (existingKey != null) { - return Result.success(existingKey) - } - - // Node key is missing, attempt auto-enrollment - Log.d(TAG, "Orbit node key missing, attempting auto-enrollment") - - // Re-enroll - val enrollResult = enroll() - - return enrollResult.fold( - onSuccess = { response -> - Log.d(TAG, "Auto-enrollment successful") - Result.success(response.orbitNodeKey) - }, - onFailure = { error -> - FleetLog.e(TAG, "Auto-enrollment failed: ${error.message}") - Result.failure(error) - }, - ) + // Check outside the lock to avoid unnecessary contention when a key already exists. + val existingKey = getApiKey() + if (existingKey != null) { + return Result.success(existingKey) } + + // Node key is missing, attempt auto-enrollment + Log.d(TAG, "Orbit node key missing, attempting auto-enrollment") + + // enroll() acquires enrollmentMutex internally to guard the enroll/store sequence + // against concurrent re-enrollment attempts. + val enrollResult = enroll() + + return enrollResult.fold( + onSuccess = { response -> + Log.d(TAG, "Auto-enrollment successful") + Result.success(response.orbitNodeKey) + }, + onFailure = { error -> + FleetLog.e(TAG, "Auto-enrollment failed: ${error.message}") + Result.failure(error) + }, + ) } private data class EnrollmentCredentials( @@ -633,3 +634,4 @@ data class GetCertificateTemplateResponse( */ fun GetCertificateTemplateResponse.buildScepUrl(serverUrl: String, hostUUID: String): String = "$serverUrl/mdm/scep/proxy/$hostUUID,g$id,$certificateAuthorityType,${fleetChallenge ?: ""}" + From 2bae0f6c7214e1b517adab01ebe82ab128653095 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:27 +0000 Subject: [PATCH 24/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- android/settings.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts index 7e677746ee9..a7c431b8678 100644 --- a/android/settings.gradle.kts +++ b/android/settings.gradle.kts @@ -19,6 +19,6 @@ dependencyResolutionManagement { } } -rootProject.name = "My Application" +rootProject.name = "fleetmdm" include(":app") - \ No newline at end of file + From 47ed23efee18514f821ac7e159102b6725b2acb3 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:28 +0000 Subject: [PATCH 25/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- cmd/osquery-perf/osquery_perf/stats.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cmd/osquery-perf/osquery_perf/stats.go b/cmd/osquery-perf/osquery_perf/stats.go index 05c3157c87a..26beb35c6a4 100644 --- a/cmd/osquery-perf/osquery_perf/stats.go +++ b/cmd/osquery-perf/osquery_perf/stats.go @@ -273,10 +273,15 @@ func (s *Stats) Log() { s.l.Lock() defer s.l.Unlock() + var errorRate float64 + if s.osqueryEnrollments > 0 { + errorRate = float64(s.errors) / float64(s.osqueryEnrollments) + } + log.Printf( "uptime: %s, error rate: %.2f, osquery enrolls: %d, orbit enrolls: %d, mdm enrolls: %d, distributed/reads: %d, distributed/writes: %d, config requests: %d, result log requests: %d, mdm sessions initiated: %d, mdm on-demand syncs: %d, mdm commands received: %d, config errors: %d, distributed/read errors: %d, distributed/write errors: %d, log result errors: %d, orbit errors: %d, desktop errors: %d, mdm errors: %d, mdm scep requests: %d, mdm scep success: %d, mdm scep errors: %d, ddm tokens success: %d, ddm tokens errors: %d, ddm declaration items success: %d, ddm declaration items errors: %d, ddm activation success: %d, ddm activation errors: %d, ddm configuration success: %d, ddm configuration errors: %d, ddm status success: %d, ddm status errors: %d, buffered logs: %d, script execs (errs): %d (%d), software installs (errs): %d (%d)", time.Since(s.StartTime).Round(time.Second), - float64(s.errors)/float64(s.osqueryEnrollments), + errorRate, s.osqueryEnrollments, s.orbitEnrollments, s.mdmEnrollments, From 5cc6b0f5502d7b0146a98907a8cc6b93af0f99af Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:29 +0000 Subject: [PATCH 26/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- ee/fleetd-chrome/src/tables/os_version.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ee/fleetd-chrome/src/tables/os_version.ts b/ee/fleetd-chrome/src/tables/os_version.ts index f63b0935605..38d7858383f 100644 --- a/ee/fleetd-chrome/src/tables/os_version.ts +++ b/ee/fleetd-chrome/src/tables/os_version.ts @@ -59,6 +59,9 @@ export default class TableOSVersion extends Table { console.warn( `Chrome version ${version} does not have expected 4 segments` ); + for (const column of ["major", "minor", "build", "patch"]) { + warningsArray.push({ column, error_message: "unexpected version format" }); + } } else { [major, minor, build, patch] = splits; } From 57aea790132b9b17f0e71dc09a62e57b7fb85d78 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:30 +0000 Subject: [PATCH 27/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../ingesters/homebrew/external_refs/version_shortener.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ee/maintained-apps/ingesters/homebrew/external_refs/version_shortener.go b/ee/maintained-apps/ingesters/homebrew/external_refs/version_shortener.go index eaf2b8433a5..975a1a45a58 100644 --- a/ee/maintained-apps/ingesters/homebrew/external_refs/version_shortener.go +++ b/ee/maintained-apps/ingesters/homebrew/external_refs/version_shortener.go @@ -15,7 +15,7 @@ import ( func makeVersionShortener(keepSegments int) func(*maintained_apps.FMAManifestApp) (*maintained_apps.FMAManifestApp, error) { return func(app *maintained_apps.FMAManifestApp) (*maintained_apps.FMAManifestApp, error) { if app.Version == "" { - return app, fmt.Errorf("empty version for app %s", app.Slug) + return app, errors.New(fmt.Sprintf("empty version for app %s", app.Slug)) } parts := strings.Split(app.Version, ".") if len(parts) <= keepSegments { @@ -46,7 +46,7 @@ var ( // the host version always greater, breaking patch policy detection. func SublimeVersionTransformer(app *maintained_apps.FMAManifestApp) (*maintained_apps.FMAManifestApp, error) { if app.Version == "" { - return app, fmt.Errorf("empty version for Sublime app %s", app.Slug) + return app, errors.New(fmt.Sprintf("empty version for Sublime app %s", app.Slug)) } if strings.HasPrefix(app.Version, "Build ") { return app, nil From 6b858a9643959bea224dea8c452d2f01ff127851 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:31 +0000 Subject: [PATCH 28/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../inputs/homebrew/scripts/gpg-suite-uninstall.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ee/maintained-apps/inputs/homebrew/scripts/gpg-suite-uninstall.sh b/ee/maintained-apps/inputs/homebrew/scripts/gpg-suite-uninstall.sh index e5b6c0a7fea..377d76579c1 100644 --- a/ee/maintained-apps/inputs/homebrew/scripts/gpg-suite-uninstall.sh +++ b/ee/maintained-apps/inputs/homebrew/scripts/gpg-suite-uninstall.sh @@ -134,7 +134,7 @@ remove_receipt_files() { fi echo "sudo pkgutil --only-files --files \"$PKGID\" | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" | tr '\\\\n' '\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf" - sudo pkgutil --only-files --files "$PKGID" | sed "s|^|/${INSTALL_LOCATION}/|" | tr '\n' '\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf + sudo pkgutil --only-files --files "$PKGID" | sed "s|^|${FULL_INSTALL_LOCATION}/|" | tr '\n' '\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf echo "sudo pkgutil --only-dirs --files \"$PKGID\" | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" | grep '\\.app$' | tr '\\\\n' '\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf" sudo pkgutil --only-dirs --files "$PKGID" | sed "s|^|${FULL_INSTALL_LOCATION}/|" | grep '\.app$' | tr '\n' '\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf @@ -237,3 +237,4 @@ trash $LOGGED_IN_USER '~/Library/PreferencePanes/GPGPreferences.prefPane' trash $LOGGED_IN_USER '~/Library/Preferences/org.gpgtools.*' trash $LOGGED_IN_USER '~/Library/Services/GPGServices.service' + From ba26d9de34be5358638fa373ff7a21b969f26563 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:32 +0000 Subject: [PATCH 29/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- ee/server/service/hostidentity/config.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ee/server/service/hostidentity/config.go b/ee/server/service/hostidentity/config.go index cac57d12281..e4a07125af6 100644 --- a/ee/server/service/hostidentity/config.go +++ b/ee/server/service/hostidentity/config.go @@ -9,13 +9,13 @@ import ( "github.com/fleetdm/fleet/v4/server/mdm/scep/depot" ) -func initAssets(ds fleet.Datastore) error { +func initAssets(ctx context.Context, ds fleet.Datastore) error { // Check if we have existing certs and keys expectedAssets := []fleet.MDMAssetName{ fleet.MDMAssetHostIdentityCACert, fleet.MDMAssetHostIdentityCAKey, } - savedAssets, err := ds.GetAllMDMConfigAssetsByName(context.Background(), expectedAssets, nil) + savedAssets, err := ds.GetAllMDMConfigAssetsByName(ctx, expectedAssets, nil) if err != nil { // allow not found errors as it means we're generating the assets for the first time. if !fleet.IsNotFound(err) { @@ -49,9 +49,10 @@ func initAssets(ds fleet.Datastore) error { }) } - if err := ds.InsertMDMConfigAssets(context.Background(), assets, nil); err != nil { + if err := ds.InsertMDMConfigAssets(ctx, assets, nil); err != nil { return fmt.Errorf("inserting host identity SCEP assets: %w", err) } } return nil } + From 5c58cd08b7feb30f81a490400eaa802d5ba4dbd7 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:33 +0000 Subject: [PATCH 30/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- frontend/components/ActivityItem/ActivityItem.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/frontend/components/ActivityItem/ActivityItem.tsx b/frontend/components/ActivityItem/ActivityItem.tsx index bd1ada7694e..42fb33eeadc 100644 --- a/frontend/components/ActivityItem/ActivityItem.tsx +++ b/frontend/components/ActivityItem/ActivityItem.tsx @@ -91,11 +91,9 @@ const ActivityItem = ({ ? addGravatarUrlToResource({ email: actor_email }) : { gravatar_url: undefined }; - // wrapped just in case the date string does not parse correctly - let activityCreatedAt: Date; - try { - activityCreatedAt = new Date(activity.created_at); - } catch (e) { + // fall back to the current date if the date string does not parse correctly + let activityCreatedAt = new Date(activity.created_at); + if (isNaN(activityCreatedAt.getTime())) { activityCreatedAt = new Date(); } @@ -139,3 +137,4 @@ const ActivityItem = ({ }; export default ActivityItem; + From 37ac2635706b15c6aec1adf1e8c6712f1d566ec2 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:34 +0000 Subject: [PATCH 31/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../components/HostPicker.tests.tsx | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/frontend/components/CommandPalette/components/HostPicker.tests.tsx b/frontend/components/CommandPalette/components/HostPicker.tests.tsx index 4d129009fe9..2f82a937cd9 100644 --- a/frontend/components/CommandPalette/components/HostPicker.tests.tsx +++ b/frontend/components/CommandPalette/components/HostPicker.tests.tsx @@ -105,16 +105,15 @@ describe("HostPicker", () => { team_name: "Engineering", }); - // The shared QueryClient persists React Query's cache across tests - // in this file. Earlier tests register an empty result under - // queryKey ["commandPaletteHosts", ""], so subsequent renders with - // the same search would read that cached emptiness and never hit - // the mock. Each column test uses a unique search string to get a - // fresh queryFn invocation. The mock ignores the query value, so - // the same `hosts` is returned regardless. - it("renders a status dot next to the host name (no text)", async () => { + // Each test in this file renders with its own fresh QueryClient (see + // createCustomRenderer), so there is no cross-test cache to worry + // about here. The mock ignores the query value, so the same `hosts` + // is returned regardless of the search string used. + beforeEach(() => { mockedHosts.loadHosts.mockResolvedValue(hosts); + }); + it("renders a status dot next to the host name (no text)", async () => { const { findByText, container } = renderPicker( ); @@ -131,8 +130,6 @@ describe("HostPicker", () => { }); it("renders the host's team in the right-aligned column when showTeamColumn", async () => { - mockedHosts.loadHosts.mockResolvedValue(hosts); - const { findByText } = renderPicker( ); @@ -140,8 +137,6 @@ describe("HostPicker", () => { }); it("suppresses the team column by default (Free / Primo / single-fleet)", async () => { - mockedHosts.loadHosts.mockResolvedValue(hosts); - const { findByText, queryByText } = renderPicker( ); @@ -151,8 +146,6 @@ describe("HostPicker", () => { }); it("highlights the matched substring of the host name", async () => { - mockedHosts.loadHosts.mockResolvedValue(hosts); - const { findByText, container } = renderPicker( ); From 633a744c1d3cef4db8345a997b7b15ed4b66f011 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:35 +0000 Subject: [PATCH 32/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../CommandPalette/components/PolicyPicker.tests.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frontend/components/CommandPalette/components/PolicyPicker.tests.tsx b/frontend/components/CommandPalette/components/PolicyPicker.tests.tsx index 7fadd277cce..5dddee33614 100644 --- a/frontend/components/CommandPalette/components/PolicyPicker.tests.tsx +++ b/frontend/components/CommandPalette/components/PolicyPicker.tests.tsx @@ -158,9 +158,10 @@ describe("PolicyPicker", () => { }); describe("Patch badge", () => { - // Unique search values per test sidestep React Query cache pollution - // from earlier empty-state tests, which registered an empty result - // under queryKey ["commandPalettePolicies", ..., ""]. + // Each test uses its own QueryClient (via renderPickerInCommand -> + // createCustomRenderer) so results from earlier tests registered under + // queryKey ["commandPalettePolicies", ...] cannot leak into these + // assertions. it("renders the Patch badge when policy.type === 'patch'", async () => { mockedGlobal.loadAllNew.mockResolvedValue({ policies: [ From 27f6b3c668e05f7e7fab6ee39ed3598ccbfdeb2b Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:36 +0000 Subject: [PATCH 33/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- frontend/components/List/List.tests.tsx | 28 +++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/frontend/components/List/List.tests.tsx b/frontend/components/List/List.tests.tsx index afe65046d48..1d6c292ea0b 100644 --- a/frontend/components/List/List.tests.tsx +++ b/frontend/components/List/List.tests.tsx @@ -90,7 +90,7 @@ describe("List", () => { { customId: "beta", name: "Beta" }, ]; - const { container } = render( + const { container, rerender } = render( data={data} idKey="customId" @@ -107,7 +107,31 @@ describe("List", () => { li.textContent?.includes("Beta") ); - expect(alphaLi?.getAttribute("key")).toBeNull(); // React doesn't expose "key" to the DOM + expect(alphaLi).toBeInTheDocument(); expect(betaLi).toBeInTheDocument(); + + // Reordering data by customId should reuse the same DOM nodes when idKey + // is honored, since React matches elements by their key rather than + // position. This verifies idKey drives the keying, not array index. + const reorderedData: ICustomItem[] = [data[1], data[0]]; + + rerender( + + data={reorderedData} + idKey="customId" + renderItemRow={(item) => {item.name}} + /> + ); + + const reorderedListItems = container.querySelectorAll("li.list__row"); + const reorderedAlphaLi = Array.from(reorderedListItems).find((li) => + li.textContent?.includes("Alpha") + ); + const reorderedBetaLi = Array.from(reorderedListItems).find((li) => + li.textContent?.includes("Beta") + ); + + expect(reorderedAlphaLi).toBe(alphaLi); + expect(reorderedBetaLi).toBe(betaLi); }); }); From ca609192223be6259d41034ecee3d81dd8882aad Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:37 +0000 Subject: [PATCH 34/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../QuerySidePanel/EventedTableTag/EventedTableTag.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/components/side_panels/QuerySidePanel/EventedTableTag/EventedTableTag.tsx b/frontend/components/side_panels/QuerySidePanel/EventedTableTag/EventedTableTag.tsx index a4b89f366e0..1f78ad8129d 100644 --- a/frontend/components/side_panels/QuerySidePanel/EventedTableTag/EventedTableTag.tsx +++ b/frontend/components/side_panels/QuerySidePanel/EventedTableTag/EventedTableTag.tsx @@ -19,7 +19,8 @@ const EventedTableTag = ({ selectedTableName }: IEventedTableTagProps) => { EVENTED TABLE @@ -28,3 +29,4 @@ const EventedTableTag = ({ selectedTableName }: IEventedTableTagProps) => { }; export default EventedTableTag; + From 1636a5e936416dafdff1da7168dde85802f966ca Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:38 +0000 Subject: [PATCH 35/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- frontend/components/TableContainer/utilities/config_utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/components/TableContainer/utilities/config_utils.ts b/frontend/components/TableContainer/utilities/config_utils.ts index fed909c7247..a93b6ca2378 100644 --- a/frontend/components/TableContainer/utilities/config_utils.ts +++ b/frontend/components/TableContainer/utilities/config_utils.ts @@ -24,7 +24,7 @@ export const getConditionalSelectHeaderCheckboxProps = ({ ); const indeterminate = !allSelectableRowsSelected && - headerProps.rows.some((row) => row.isSelected); + headerProps.rows.filter(checkIfRowIsSelectable).some((row) => row.isSelected); const onChange = () => { if (checkIfAllSelectableRowsSelected(headerProps.rows)) { From 6e423b546e5312112aba37be56ffb0c02601c28c Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:40 +0000 Subject: [PATCH 36/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../components/TableContainer/utilities/TableContainerUtils.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/components/TableContainer/utilities/TableContainerUtils.ts b/frontend/components/TableContainer/utilities/TableContainerUtils.ts index 2e75ad63577..226749a639c 100644 --- a/frontend/components/TableContainer/utilities/TableContainerUtils.ts +++ b/frontend/components/TableContainer/utilities/TableContainerUtils.ts @@ -28,4 +28,3 @@ export const generateResultsCountText = ( return `${resultsCount.toLocaleString()} ${name}`; }; -export default { generateResultsCountText }; From 30148e4e6f264fe7cc28329a9aebdd1e0a828247 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:41 +0000 Subject: [PATCH 37/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../components/DigicertForm/helpers.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/DigicertForm/helpers.ts b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/DigicertForm/helpers.ts index 06832888875..cfeaa70413a 100644 --- a/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/DigicertForm/helpers.ts +++ b/frontend/pages/admin/IntegrationsPage/cards/CertificateAuthorities/components/DigicertForm/helpers.ts @@ -4,7 +4,14 @@ import valid_url from "components/forms/validators/valid_url"; import { IDigicertFormData } from "./DigicertForm"; -// TODO: create a validator abstraction for this and the other form validation files +// NOTE: This module intentionally keeps its own generic validation scaffolding +// (IValidation, IFormValidations, generateFormValidations, getErrorMessage, +// validateFormData) inline rather than importing a shared abstraction, because +// no such shared validator utility currently exists in this codebase. A follow-up +// should extract this scaffolding (duplicated across CustomESTForm, DigicertForm, +// and likely NDESForm/CustomSCEPForm/HydrantForm/SmallstepForm) into a single +// generic, reusable form-validation utility to avoid divergent bug fixes across +// CA form variants. export interface IDigicertFormValidation { isValid: boolean; From ddd7b68c67d310c53c325477950729d4f5e00562 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:42 +0000 Subject: [PATCH 38/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../IntegrationForm/IntegrationForm.tsx | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/frontend/pages/admin/IntegrationsPage/cards/Integrations/components/IntegrationForm/IntegrationForm.tsx b/frontend/pages/admin/IntegrationsPage/cards/Integrations/components/IntegrationForm/IntegrationForm.tsx index 28616cf8201..8651197c989 100644 --- a/frontend/pages/admin/IntegrationsPage/cards/Integrations/components/IntegrationForm/IntegrationForm.tsx +++ b/frontend/pages/admin/IntegrationsPage/cards/Integrations/components/IntegrationForm/IntegrationForm.tsx @@ -107,12 +107,17 @@ const IntegrationForm = ({ integrationEditing.username ) { // Edit existing jira integration using array replacement - jiraIntegrationSubmitData.splice(integrationEditing.originalIndex, 1, { - url, - username: username || "", - api_token: apiToken, - project_key: projectKey || "", - }); + jiraIntegrationSubmitData = jiraIntegrationSubmitData.map( + (integration, index) => + index === integrationEditing.originalIndex + ? { + url, + username: username || "", + api_token: apiToken, + project_key: projectKey || "", + } + : integration + ); } else { // Create new jira integration at end of array jiraIntegrationSubmitData = [ @@ -134,12 +139,17 @@ const IntegrationForm = ({ integrationEditing.email ) { // Edit existing zendesk integration using array replacement - zendeskIntegrationSubmitData.splice(integrationEditing.originalIndex, 1, { - url, - email: email || "", - api_token: apiToken, - group_id: Number(groupId) || 0, - }); + zendeskIntegrationSubmitData = zendeskIntegrationSubmitData.map( + (integration, index) => + index === integrationEditing.originalIndex + ? { + url, + email: email || "", + api_token: apiToken, + group_id: Number(groupId) || 0, + } + : integration + ); } else { // Create new zendesk integration at end of array zendeskIntegrationSubmitData = [ From adeb5b08e1c926f435155648786e822fb6fd9218 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:02:43 +0000 Subject: [PATCH 39/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../VppPage/components/DeleteVppModal/DeleteVppModal.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/VppPage/components/DeleteVppModal/DeleteVppModal.tsx b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/VppPage/components/DeleteVppModal/DeleteVppModal.tsx index bb0228ede3b..be072fab4cc 100644 --- a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/VppPage/components/DeleteVppModal/DeleteVppModal.tsx +++ b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/VppPage/components/DeleteVppModal/DeleteVppModal.tsx @@ -35,9 +35,9 @@ const DeleteVppModal = ({ } catch (e) { // TODO: Check API sends back correct error messages renderFlash("error", "Couldn’t delete. Please try again."); - onCancel(); + setIsDeleting(false); } - }, [onCancel, onDeletedToken, renderFlash, tokenId]); + }, [onDeletedToken, renderFlash, tokenId]); return ( Date: Mon, 7 Sep 2026 08:02:44 +0000 Subject: [PATCH 40/40] fix(adhoc-sweep-fixes): 40 review findings across 40 files --- .../MdmSettings/VppPage/components/RenewVppModal/helpers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/VppPage/components/RenewVppModal/helpers.ts b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/VppPage/components/RenewVppModal/helpers.ts index f7557518992..f40e76182cf 100644 --- a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/VppPage/components/RenewVppModal/helpers.ts +++ b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/VppPage/components/RenewVppModal/helpers.ts @@ -5,11 +5,11 @@ const DEFAULT_ERROR_MESSAGE = "Couldn’t renew. Please try again."; // eslint-disable-next-line import/prefer-default-export export const getErrorMessage = (err: unknown) => { const invalidTokenReason = getErrorReason(err, { - reasonIncludes: "invalid", + reasonIncludes: "Invalid token", }); if (invalidTokenReason) { - return "Invalid token. Please provide a valid token from Apple Business."; + return `Invalid token. ${invalidTokenReason}`; } return DEFAULT_ERROR_MESSAGE;