CVE-2026-3637
Description
Mattermost versions 11.5.x <= 11.5.1, 10.11.x <= 10.11.13, 11.4.x <= 11.4.3 fail to check the create_post channel permission during post edit operations which allows an authenticated attacker with revoked posting privileges to modify their existing posts via direct API requests to the post update and patch endpoints.. Mattermost Advisory ID: MMSA-2026-00627
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Mattermost fails to check create_post permission during post edit, allowing authenticated users with revoked posting privileges to modify existing posts.
Vulnerability
Mattermost versions 11.5.x <= 11.5.1, 10.11.x <= 10.11.13, and 11.4.x <= 11.4.3 do not verify the create_post channel permission when processing post edit operations. This allows an authenticated attacker whose posting privileges have been revoked to still modify their existing posts via direct API requests to the post update and patch endpoints. [1]
Exploitation
An attacker needs to be authenticated and have had their posting privileges revoked. They can then send direct API requests to the post update or patch endpoints to modify their own previously created posts. No special network position or user interaction is required beyond authentication. [1]
Impact
Successful exploitation allows the attacker to modify their existing posts even after their posting privileges have been revoked. This could lead to unauthorized content changes, potentially affecting the integrity of conversations or allowing the attacker to alter evidence. The attacker does not gain elevated privileges beyond their existing authentication, but bypasses a permission check. [1]
Mitigation
Matterhas released security updates; the advisory MMSA-2026-00627 provides details. Users should consult the Mattermost security updates page for the latest fixed versions. As a workaround, administrators can restrict API access or monitor for unusual post edit activity. [1]
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
1- Range: <=11.5.1, <=10.11.13, <=11.4.3
Patches
1f2b3d1c6a945[MM-67809] Check create post permission when editing posts (#35558) (#35713)
2 files changed · +56 −0
server/channels/api4/post.go+12 −0 modified@@ -1046,6 +1046,12 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) { return } + // Users who can't create posts in a channel shouldn't be able to edit them either. + userCreatePostPermissionCheckWithContext(c, originalPost.ChannelId) + if c.Err != nil { + return + } + auditRec.AddEventPriorState(originalPost) auditRec.AddEventObjectType("post") @@ -1183,6 +1189,12 @@ func postPatchChecks(c *Context, auditRec *model.AuditRecord, message *string) b return false } + // Users who can't create posts in a channel shouldn't be able to edit them either. + userCreatePostPermissionCheckWithContext(c, originalPost.ChannelId) + if c.Err != nil { + return false + } + if *c.App.Config().ServiceSettings.PostEditTimeLimit != -1 && model.GetMillis() > originalPost.CreateAt+int64(*c.App.Config().ServiceSettings.PostEditTimeLimit*1000) && message != nil { c.Err = model.NewAppError("patchPost", "api.post.update_post.permissions_time_limit.app_error", map[string]any{"timeLimit": *c.App.Config().ServiceSettings.PostEditTimeLimit}, "", http.StatusBadRequest) return isMember
server/channels/api4/post_test.go+44 −0 modified@@ -1701,6 +1701,29 @@ func TestUpdatePost(t *testing.T) { assert.Contains(t, updatedPost.FileIds, fileId) }) + t.Run("should prevent editing when create_post permission is revoked", func(t *testing.T) { + th.LoginBasic(t) + + postToEdit, _, appErr := th.App.CreatePost(th.Context, &model.Post{ + UserId: th.BasicUser.Id, + ChannelId: channel.Id, + Message: "original message", + }, channel, model.CreatePostFlags{SetOnline: true}) + require.Nil(t, appErr) + + th.RemovePermissionFromRole(t, model.PermissionCreatePost.Id, model.ChannelUserRoleId) + defer th.AddPermissionToRole(t, model.PermissionCreatePost.Id, model.ChannelUserRoleId) + + updatePost := &model.Post{ + Id: postToEdit.Id, + ChannelId: channel.Id, + Message: "edited message", + } + _, resp, err := client.UpdatePost(context.Background(), postToEdit.Id, updatePost) + require.Error(t, err) + CheckForbiddenStatus(t, resp) + }) + t.Run("logged out", func(t *testing.T) { _, err := client.Logout(context.Background()) require.NoError(t, err) @@ -2085,6 +2108,27 @@ func TestPatchPost(t *testing.T) { require.NoError(t, err) }) + t.Run("should prevent patching when create_post permission is revoked", func(t *testing.T) { + th.LoginBasic(t) + + postToEdit, _, err := client.CreatePost(context.Background(), &model.Post{ + ChannelId: channel.Id, + Message: "original message", + }) + require.NoError(t, err) + + defaultPerms := th.SaveDefaultRolePermissions(t) + defer th.RestoreDefaultRolePermissions(t, defaultPerms) + th.RemovePermissionFromRole(t, model.PermissionCreatePost.Id, model.ChannelUserRoleId) + + patch := &model.PostPatch{ + Message: model.NewPointer("edited message"), + } + _, resp, err := client.PatchPost(context.Background(), postToEdit.Id, patch) + require.Error(t, err) + CheckForbiddenStatus(t, resp) + }) + t.Run("time limit expired", func(t *testing.T) { th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.PostEditTimeLimit = 1
Vulnerability mechanics
Root cause
"Missing authorization check — the post update and patch endpoints did not verify that the user still holds the `create_post` channel permission, allowing users with revoked posting privileges to edit their existing posts."
Attack vector
An authenticated attacker whose `create_post` permission has been revoked in a channel (e.g., due to a role change or channel moderation action) can still modify their existing posts in that channel. The attacker sends a direct API request to the post update endpoint (`PUT /api/v4/posts/{post_id}`) or the patch endpoint (`PATCH /api/v4/posts/{post_id}`) with the desired changes. The server previously only checked that the user owned the post and had general edit permissions, but did not re-verify the `create_post` channel permission [CWE-862]. No special network position is required beyond normal authenticated API access.
Affected code
The vulnerability exists in the `updatePost` function and the `postPatchChecks` helper in `server/channels/api4/post.go`. These endpoints handle PUT and PATCH requests for post editing but lacked a call to `userCreatePostPermissionCheckWithContext` to verify the `create_post` channel permission. The test file `server/channels/api4/post_test.go` was updated with regression tests for both `TestUpdatePost` and `TestPatchPost` [patch_id=918581].
What the fix does
The patch adds a call to `userCreatePostPermissionCheckWithContext(c, originalPost.ChannelId)` in both the `updatePost` function and the `postPatchChecks` helper function in `server/channels/api4/post.go` [patch_id=918581]. This ensures that before allowing any post edit, the server checks whether the user still has the `create_post` permission in the post's channel. If the permission is absent, the request is rejected with an error, preventing users with revoked posting privileges from editing their existing posts.
Preconditions
- authAttacker must be authenticated as a user who previously created posts in the target channel
- inputAttacker must know the post ID of an existing post they authored
- configThe user's create_post permission must have been revoked (e.g., via role change or channel moderation) while their existing posts remain in the channel
Generated on May 20, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
1- mattermost.com/security-updatesnvdVendor Advisory
News mentions
0No linked articles in our index yet.