Automatic Merge
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
21a86506f9
Коммит
51f2e2fdd5
@@ -795,6 +795,8 @@ func (a *App) UpdatePost(c request.CTX, receivedUpdatedPost *model.Post, updateP
|
||||
// Always use incoming metadata when provided, otherwise retain existing
|
||||
if receivedUpdatedPost.Metadata != nil {
|
||||
newPost.Metadata = receivedUpdatedPost.Metadata.Copy()
|
||||
// MM-67055: Strip embeds - always server-generated. Preserves Priority/Acks for Shared Channels sync.
|
||||
newPost.Metadata.Embeds = nil
|
||||
} else {
|
||||
// Restore the post metadata that was stripped by the plugin. Set it to
|
||||
// the last known good.
|
||||
|
||||
@@ -1791,6 +1791,60 @@ func TestUpdatePost(t *testing.T) {
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("should strip client-supplied embeds", func(t *testing.T) {
|
||||
// MM-67055: Verify that client-supplied metadata.embeds are stripped.
|
||||
// This prevents WebSocket message spoofing via permalink embeds.
|
||||
//
|
||||
// Note: Priority and Acknowledgements are stored in separate database tables,
|
||||
// not in post metadata. Shared Channels handles them separately via
|
||||
// syncRemotePriorityMetadata and syncRemoteAcknowledgementsMetadata after
|
||||
// calling UpdatePost. See sync_recv.go::upsertSyncPost
|
||||
mainHelper.Parallel(t)
|
||||
th := Setup(t).InitBasic()
|
||||
|
||||
th.AddUserToChannel(th.BasicUser, th.BasicChannel)
|
||||
th.Context.Session().UserId = th.BasicUser.Id
|
||||
|
||||
// Create a basic post
|
||||
post := &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
Message: "original message",
|
||||
UserId: th.BasicUser.Id,
|
||||
}
|
||||
createdPost, _, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{})
|
||||
require.Nil(t, err)
|
||||
|
||||
// Try to update with spoofed embeds (the attack vector)
|
||||
updatePost := &model.Post{
|
||||
Id: createdPost.Id,
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
Message: "updated message",
|
||||
UserId: th.BasicUser.Id,
|
||||
Metadata: &model.PostMetadata{
|
||||
Embeds: []*model.PostEmbed{
|
||||
{
|
||||
Type: model.PostEmbedPermalink,
|
||||
Data: &model.PreviewPost{
|
||||
PostID: "spoofed-post-id",
|
||||
Post: &model.Post{
|
||||
Id: "spoofed-post-id",
|
||||
UserId: th.BasicUser2.Id,
|
||||
Message: "Spoofed message from another user!",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
updatedPost, _, err := th.App.UpdatePost(th.Context, updatePost, nil)
|
||||
require.Nil(t, err)
|
||||
require.NotNil(t, updatedPost.Metadata)
|
||||
|
||||
// Verify embeds were stripped
|
||||
assert.Empty(t, updatedPost.Metadata.Embeds, "spoofed embeds should be stripped")
|
||||
})
|
||||
}
|
||||
|
||||
func TestSearchPostsForUser(t *testing.T) {
|
||||
|
||||
Ссылка в новой задаче
Block a user