VYPR
Low severityNVD Advisory· Published Apr 24, 2025· Updated Apr 24, 2025

Unauthorized Playbooks Post Deletion in Mattermost Playbooks Plugin

CVE-2025-41423

Description

Mattermost versions 10.4.x <= 10.4.2, 10.5.x <= 10.5.0, 9.11.x <= 9.11.10 fail to properly validate permissions for the API endpoint /plugins/playbooks/api/v0/signal/keywords/ignore-thread, allowing any user or attacker to delete posts containing actions created by the Playbooks bot, even without channel access or appropriate permissions.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/mattermost/mattermost-plugin-playbooksGo
>= 2.0.0
github.com/mattermost/mattermost-plugin-playbooksGo
< 1.41.01.41.0
github.com/mattermost/mattermost/server/v8Go
< 8.0.0-20250218121836-2b5275d871368.0.0-20250218121836-2b5275d87136
github.com/mattermost/mattermost/server/v8Go
>= 10.4.0
github.com/mattermost/mattermost/server/v8Go
>= 10.5.0
github.com/mattermost/mattermost/server/v8Go
>= 9.11.0

Affected products

1

Patches

2
2b5275d87136

chore: Update Playbooks plugin to v2.1.1 (#29996)

https://github.com/mattermost/mattermostChristopher SpellerFeb 18, 2025via ghsa
1 file changed · +1 1
  • server/Makefile+1 1 modified
    @@ -141,7 +141,7 @@ PLUGIN_PACKAGES += mattermost-plugin-gitlab-v1.9.1
     PLUGIN_PACKAGES += mattermost-plugin-jira-v4.2.0
     # We need to prepackage both versions of playbooks and install the correct one based on the server license. See MM-60025.
     PLUGIN_PACKAGES += mattermost-plugin-playbooks-v1.40.0
    -PLUGIN_PACKAGES += mattermost-plugin-playbooks-v2.0.1
    +PLUGIN_PACKAGES += mattermost-plugin-playbooks-v2.1.1
     PLUGIN_PACKAGES += mattermost-plugin-nps-v1.3.3
     PLUGIN_PACKAGES += mattermost-plugin-servicenow-v2.3.4
     PLUGIN_PACKAGES += mattermost-plugin-zoom-v1.8.0
    
f9f7064e4d9f

Fix channel actions modal (#1961)

https://github.com/mattermost/mattermost-plugin-playbooksChristopher SpellerJan 24, 2025via ghsa
3 files changed · +21 21
  • e2e-tests/tests/integration/playbooks/channels/general_actions_spec.js+0 17 modified
    @@ -386,23 +386,6 @@ describe('channels > general actions', {testIsolation: true}, () => {
             });
         });
     
    -    it('action settings are disabled for non-channel admin', () => {
    -        // # Login as non-channel admin
    -        cy.apiLogin(testUser);
    -
    -        // # Go to the test channel
    -        cy.visit(`/${testTeam.name}/channels/${testChannel.name}`);
    -
    -        // # Open Channel Header and the Channel Actions modal
    -        cy.get('#channelHeaderTitle').click();
    -        cy.findByText('Channel Actions').click();
    -
    -        // * Verify the toggles are disabled
    -        cy.findByRole('dialog', {name: /channel actions/i}).within(() => {
    -            cy.get('input').should('be.disabled');
    -        });
    -    });
    -
         it('action settings are reset to the default when switching to a channel with no actions configured', () => {
             // # Create an additional channel
             const name = 'New channel ' + Date.now();
    
  • server/api/actions.go+6 0 modified
    @@ -273,6 +273,12 @@ func (a *ActionsHandler) updateChannelAction(c *Context, w http.ResponseWriter,
     		return
     	}
     
    +	// Ensure that the action ID in both the URL and the body of the request are the same as well
    +	if newChannelAction.ID != vars["action_id"] {
    +		a.HandleErrorWithCode(w, c.logger, http.StatusBadRequest, "action ID in request body must match action ID in URL", nil)
    +		return
    +	}
    +
     	// Validate the new action type and payload
     	if err := a.ValidateChannelAction(c, w, &newChannelAction, userID); err != nil {
     		a.HandleErrorWithCode(w, c.logger, http.StatusBadRequest, "invalid action", err)
    
  • webapp/src/components/channel_actions_modal.tsx+15 4 modified
    @@ -7,9 +7,17 @@ import {useIntl} from 'react-intl';
     
     import {getCurrentChannelId} from 'mattermost-webapp/packages/mattermost-redux/src/selectors/entities/common';
     
    +import Permissions from 'mattermost-redux/constants/permissions';
    +
    +import {getCurrentTeamId} from 'mattermost-webapp/packages/mattermost-redux/src/selectors/entities/teams';
    +
    +import {getChannel} from 'mattermost-webapp/packages/mattermost-redux/src/selectors/entities/channels';
    +
    +import {GlobalState} from 'mattermost-webapp/packages/types/src/store';
    +
     import {fetchChannelActions, saveChannelAction} from 'src/client';
     import {hideChannelActionsModal} from 'src/actions';
    -import {isChannelActionsModalVisible, isCurrentUserAdmin, isCurrentUserChannelAdmin} from 'src/selectors';
    +import {isChannelActionsModalVisible} from 'src/selectors';
     import Action from 'src/components/actions_modal_action';
     import Trigger, {TriggerKeywords} from 'src/components/actions_modal_trigger';
     import {
    @@ -23,6 +31,7 @@ import {
     
     import ActionsModal, {ActionsContainer, TriggersContainer} from 'src/components/actions_modal';
     import {CategorizeChannelChildren, RunPlaybookChildren, WelcomeActionChildren} from 'src/components/actions_modal_action_children';
    +import {useHasChannelPermission} from 'src/hooks/permissions';
     
     interface ActionState<T extends PayloadType> {
         id: string | undefined,
    @@ -70,14 +79,16 @@ const ChannelActionsModal = () => {
         const dispatch = useDispatch();
         const show = useSelector(isChannelActionsModalVisible);
         const channelID = useSelector(getCurrentChannelId);
    -    const isChannelAdmin = useSelector(isCurrentUserChannelAdmin);
    -    const isSysAdmin = useSelector(isCurrentUserAdmin);
    +    const channel = useSelector((state: GlobalState) => getChannel(state, channelID));
    +    const teamID = useSelector(getCurrentTeamId);
    +    const publicChannelPermission = useHasChannelPermission(teamID, channelID, Permissions.MANAGE_PUBLIC_CHANNEL_PROPERTIES);
    +    const privateChannelPermission = useHasChannelPermission(teamID, channelID, Permissions.MANAGE_PRIVATE_CHANNEL_PROPERTIES);
     
         const [welcomeMsg, setWelcomeMsg, welcomeMsgInit, welcomeMsgReset, welcomeMsgOverwrite] = useActionState(welcomeMsgEmptyState);
         const [categorization, setCategorization, categorizationInit, categorizationReset, categorizationOverwrite] = useActionState(categorizationEmptyState);
         const [prompt, setPrompt, promptInit, promptReset, promptOverwrite] = useActionState(promptEmptyState);
     
    -    const editable = isChannelAdmin || isSysAdmin;
    +    const editable = channel?.type === 'O' ? publicChannelPermission : privateChannelPermission;
     
         useEffect(() => {
             const getActions = async (id: string) => {
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.