From d5cea5c1ae85bbffc49c2c4e9af6d0c884888a7a Mon Sep 17 00:00:00 2001 From: RachelElysia <71795832+RachelElysia@users.noreply.github.com> Date: Mon, 26 Jan 2026 14:45:15 -0500 Subject: [PATCH] Fleet UI: Do not allow clicking on run script if globally disabled (#38787) --- .../cards/Advanced/Advanced.tsx | 2 +- .../HostActionsDropdown.tests.tsx | 58 ++++++++++++++++++- .../HostActionsDropdown.tsx | 1 + .../HostActionsDropdown/helpers.tsx | 21 ++++++- .../modals/RunScriptModal/RunScriptModal.tsx | 2 + .../RunScriptModal/ScriptsTableConfig.tsx | 2 +- 6 files changed, 79 insertions(+), 7 deletions(-) diff --git a/frontend/pages/admin/OrgSettingsPage/cards/Advanced/Advanced.tsx b/frontend/pages/admin/OrgSettingsPage/cards/Advanced/Advanced.tsx index d8eacbba4a..abc98c7e95 100644 --- a/frontend/pages/admin/OrgSettingsPage/cards/Advanced/Advanced.tsx +++ b/frontend/pages/admin/OrgSettingsPage/cards/Advanced/Advanced.tsx @@ -446,7 +446,7 @@ const Advanced = ({ ) } - helpText="Features that run scripts under-the-hood (e.g. software install, lock/wipe) will still be available." + helpText="Features that run scripts under-the-hood (e.g. software install, lock/wipe, payload-free packages) will still be available." > Disable script execution features diff --git a/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tests.tsx b/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tests.tsx index 8c447c4150..a6c044d3f9 100644 --- a/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tests.tsx +++ b/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tests.tsx @@ -1158,6 +1158,11 @@ describe("Host Actions Dropdown", () => { app: { isGlobalAdmin: true, currentUser: createMockUser(), + config: { + server_settings: { + scripts_disabled: false, // scriptsGloballyDisabled = false + }, + }, }, }, }); @@ -1176,16 +1181,20 @@ describe("Host Actions Dropdown", () => { ); await user.click(screen.getByText("Actions")); - expect(screen.getByText("Run script")).toBeInTheDocument(); }); - it("renders the Run script action as enabled when `scripts_enabled` is `null`", async () => { + it("renders the Run script action as enabled when scripts_enabled is null", async () => { const render = createCustomRenderer({ context: { app: { isGlobalAdmin: true, currentUser: createMockUser(), + config: { + server_settings: { + scripts_disabled: false, + }, + }, }, }, }); @@ -1232,6 +1241,11 @@ describe("Host Actions Dropdown", () => { app: { isGlobalAdmin: true, currentUser: createMockUser(), + config: { + server_settings: { + scripts_disabled: false, + }, + }, }, }, }); @@ -1256,13 +1270,51 @@ describe("Host Actions Dropdown", () => { ?.parentElement ).toHaveClass("actions-dropdown-select__option--is-disabled"); + await waitFor(() => user.hover(screen.getByText("Run script"))); + expect( + screen.getByText(/fleetd agent with --enable-scripts/i) + ).toBeInTheDocument(); + }); + + it("renders the Run script action as disabled when scripts are disabled globally", async () => { + const render = createCustomRenderer({ + context: { + app: { + isGlobalAdmin: true, + currentUser: createMockUser(), + config: { + server_settings: { + scripts_disabled: true, // scriptsGloballyDisabled = true + }, + }, + }, + }, + }); + + const { user } = render( + + ); + + await user.click(screen.getByText("Actions")); + await waitFor(() => { waitFor(() => { user.hover(screen.getByText("Run script")); }); expect( - screen.getByText(/fleetd agent with --enable-scripts/i) + screen.getByText( + /Running scripts is disabled in organization settings./i + ) ).toBeInTheDocument(); }); }); diff --git a/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tsx b/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tsx index 54ad92f2b3..76150a4f7f 100644 --- a/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tsx +++ b/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tsx @@ -74,6 +74,7 @@ const HostActionsDropdown = ({ doesStoreEncryptionKey: doesStoreEncryptionKey ?? false, hostMdmDeviceStatus, hostScriptsEnabled, + scriptsGloballyDisabled: globalConfig?.server_settings.scripts_disabled, isPrimoMode: globalConfig?.partnerships?.enable_primo ?? false, hostMdmEnrollmentStatus, }); diff --git a/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/helpers.tsx b/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/helpers.tsx index a9a4c5a5ee..e4c7db7b93 100644 --- a/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/helpers.tsx +++ b/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/helpers.tsx @@ -89,6 +89,7 @@ interface IHostActionConfigOptions { doesStoreEncryptionKey: boolean; hostMdmDeviceStatus: HostMdmDeviceStatusUIState; hostScriptsEnabled: boolean | null; + scriptsGloballyDisabled: boolean | undefined; isPrimoMode: boolean; hostMdmEnrollmentStatus: MdmEnrollmentStatus | null; } @@ -283,6 +284,8 @@ const canRunScript = ({ isTeamAdmin, isTeamMaintainer, }: IHostActionConfigOptions) => { + // Scripts globally disabled, shown as disabled by modifyOptions + return ( (isGlobalAdmin || isGlobalMaintainer || isTeamAdmin || isTeamMaintainer) && isScriptSupportedPlatform(hostPlatform) @@ -339,8 +342,13 @@ const removeUnavailableOptions = ( // Available tooltips for disabled options export const getDropdownOptionTooltipContent = ( value: string | number, - isHostOnline?: boolean + isHostOnline?: boolean, + scriptsGloballyDisabled?: boolean ) => { + if (value === "runScript" && scriptsGloballyDisabled) { + return <>Running scripts is disabled in organization settings.; + } + const tooltipAction: Record = { runScript: "run scripts on", wipe: "wipe", @@ -384,6 +392,7 @@ const modifyOptions = ( hostMdmDeviceStatus, hostScriptsEnabled, hostPlatform, + scriptsGloballyDisabled, }: IHostActionConfigOptions ) => { const disableOptions = (optionsToDisable: IDropdownOption[]) => { @@ -391,7 +400,8 @@ const modifyOptions = ( option.disabled = true; option.tooltipContent = getDropdownOptionTooltipContent( option.value, - isHostOnline + isHostOnline, + scriptsGloballyDisabled ); }); }; @@ -424,6 +434,13 @@ const modifyOptions = ( ); } + // Disable run script feature if scripts are globally disabled + if (scriptsGloballyDisabled) { + optionsToDisable = optionsToDisable.concat( + options.filter((option) => option.value === "runScript") + ); + } + // null intentionally excluded from this condition: // scripts_enabled === null means this agent is not an orbit agent, or this agent is version // <=1.23.0 which is not collecting the scripts enabled info diff --git a/frontend/pages/hosts/details/HostDetailsPage/modals/RunScriptModal/RunScriptModal.tsx b/frontend/pages/hosts/details/HostDetailsPage/modals/RunScriptModal/RunScriptModal.tsx index dd9604f12b..fa7943de60 100644 --- a/frontend/pages/hosts/details/HostDetailsPage/modals/RunScriptModal/RunScriptModal.tsx +++ b/frontend/pages/hosts/details/HostDetailsPage/modals/RunScriptModal/RunScriptModal.tsx @@ -84,6 +84,8 @@ const RunScriptModal = ({ generateTableColumnConfigs( currentUser, hostTeamId, + // 4.81+ users won't reach this modal if scripts are disabled + // Intentionally left disabled actions in as a safeguard !!config?.server_settings?.scripts_disabled, onClickViewScript, onSelectAction diff --git a/frontend/pages/hosts/details/HostDetailsPage/modals/RunScriptModal/ScriptsTableConfig.tsx b/frontend/pages/hosts/details/HostDetailsPage/modals/RunScriptModal/ScriptsTableConfig.tsx index a20099746a..58187b3d5a 100644 --- a/frontend/pages/hosts/details/HostDetailsPage/modals/RunScriptModal/ScriptsTableConfig.tsx +++ b/frontend/pages/hosts/details/HostDetailsPage/modals/RunScriptModal/ScriptsTableConfig.tsx @@ -134,7 +134,7 @@ export const generateTableColumnConfigs = ( - Running scripts is disabled in organization settings + Running scripts is disabled in organization settings. } >