Information Disclosure in Common Teams API
Description
Mattermost versions 11.0.x <= 11.0.2, 10.12.x <= 10.12.1, 10.11.x <= 10.11.4, 10.5.x <= 10.5.12 fail to sanitize team email addresses to be visible only to Team Admins, which allows any authenticated user to view team email addresses via the GET /api/v4/channels/{channel_id}/common_teams endpoint
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/mattermost/mattermost/server/v8Go | < 8.0.0-20251015091448-abbf01b9db45 | 8.0.0-20251015091448-abbf01b9db45 |
github.com/mattermost/mattermost-serverGo | >= 11.0.0, < 11.0.3 | 11.0.3 |
github.com/mattermost/mattermost-serverGo | >= 10.12.0, < 10.12.2 | 10.12.2 |
github.com/mattermost/mattermost-serverGo | >= 10.11.0, < 10.11.5 | 10.11.5 |
github.com/mattermost/mattermost-serverGo | >= 10.5.0, < 10.5.13 | 10.5.13 |
Affected products
1- Range: 11.0.0
Patches
57ccb62db7958[MM-65684] Sanitize teams for /api/v4/channels/{channel_id}/common_teams endpoint (#34110) (#34180)
2 files changed · +47 −55
server/channels/api4/channel.go+1 −1 modified@@ -2427,7 +2427,7 @@ func getGroupMessageMembersCommonTeams(c *Context, w http.ResponseWriter, r *htt return } - if err := json.NewEncoder(w).Encode(teams); err != nil { + if err := json.NewEncoder(w).Encode(c.App.SanitizeTeams(*c.AppContext.Session(), teams)); err != nil { c.Logger.Warn("Error while writing response from getGroupMessageMembersCommonTeams", mlog.Err(err)) } }
server/channels/app/channel_test.go+46 −54 modified@@ -2863,69 +2863,61 @@ func TestIsCRTEnabledForUser(t *testing.T) { func TestGetGroupMessageMembersCommonTeams(t *testing.T) { mainHelper.Parallel(t) - th := SetupWithStoreMock(t) + th := Setup(t).InitBasic() defer th.TearDown() - mockStore := th.App.Srv().Store().(*mocks.Store) - - mockChannelStore := mocks.ChannelStore{} - mockStore.On("Channel").Return(&mockChannelStore) - mockChannelStore.On("Get", "gm_channel_id", true).Return(&model.Channel{Type: model.ChannelTypeGroup}, nil) - - mockTeamStore := mocks.TeamStore{} - mockStore.On("Team").Return(&mockTeamStore) - - th.App.Srv().Store().Team() - - mockTeamStore.On("GetCommonTeamIDsForMultipleUsers", []string{"user_id_1", "user_id_2"}).Return([]string{"team_id_1", "team_id_2", "team_id_3"}, nil).Times(1) - mockTeamStore.On("GetMany", []string{"team_id_1", "team_id_2", "team_id_3"}).Return( - []*model.Team{ - {DisplayName: "Team 1"}, - {DisplayName: "Team 2"}, - {DisplayName: "Team 3"}, - }, - nil, - ) + teamsToCreate := 2 + usersToCreate := 4 // at least 3 users to create a GM channel, last user is not in any team + teams := make([]string, 0, teamsToCreate) + for i := 0; i < cap(teams); i++ { + team := th.CreateTeam() + defer func(team *model.Team) { + appErr := th.App.PermanentDeleteTeam(th.Context, team) + require.Nil(t, appErr) + }(team) + teams = append(teams, team.Id) + } - mockUserStore := mocks.UserStore{} - mockStore.On("User").Return(&mockUserStore) - options := &model.UserGetOptions{ - PerPage: model.ChannelGroupMaxUsers, - Page: 0, - InChannelId: "gm_channel_id", - Inactive: false, - Active: true, + users := make([]string, 0, usersToCreate) + for i := 0; i < cap(users); i++ { + user := th.CreateUser() + defer func(user *model.User) { + appErr := th.App.PermanentDeleteUser(th.Context, user) + require.Nil(t, appErr) + }(user) + users = append(users, user.Id) } - mockUserStore.On("GetProfilesInChannel", options).Return([]*model.User{ - { - Id: "user_id_1", - }, - { - Id: "user_id_2", - }, - }, nil) - var err error - th.App.ch.srv.teamService, err = teams.New(teams.ServiceConfig{ - TeamStore: &mockTeamStore, - ChannelStore: &mockChannelStore, - GroupStore: &mocks.GroupStore{}, - Users: th.App.ch.srv.userService, - WebHub: th.App.ch.srv.platform, - ConfigFn: th.App.ch.srv.platform.Config, - LicenseFn: th.App.ch.srv.License, - }) - require.NoError(t, err) + for _, teamId := range teams { + // add first 3 users to each team, last user is not in any team + for i := range 3 { + _, _, appErr := th.App.AddUserToTeam(th.Context, teamId, users[i], "") + require.Nil(t, appErr) + } + } - commonTeams, appErr := th.App.GetGroupMessageMembersCommonTeams(th.Context, "gm_channel_id") + // create GM channel with first 3 users who share common teams + gmChannel, appErr := th.App.createGroupChannel(th.Context, users[:3], users[0]) require.Nil(t, appErr) - require.Equal(t, 3, len(commonTeams)) + require.NotNil(t, gmChannel) - // case of no common teams - mockTeamStore.On("GetCommonTeamIDsForMultipleUsers", []string{"user_id_1", "user_id_2"}).Return([]string{}, nil) - commonTeams, appErr = th.App.GetGroupMessageMembersCommonTeams(th.Context, "gm_channel_id") + // normally you can't create a GM channel with users that don't share any teams, but we do it here to test the edge case + // create GM channel with last 3 users, where last member is not in any team + otherGMChannel, appErr := th.App.createGroupChannel(th.Context, users[1:], users[0]) require.Nil(t, appErr) - require.Equal(t, 0, len(commonTeams)) + require.NotNil(t, otherGMChannel) + + t.Run("Get teams for GM channel", func(t *testing.T) { + commonTeams, appErr := th.App.GetGroupMessageMembersCommonTeams(th.Context, gmChannel.Id) + require.Nil(t, appErr) + require.Equal(t, 2, len(commonTeams)) + }) + + t.Run("No common teams", func(t *testing.T) { + commonTeams, appErr := th.App.GetGroupMessageMembersCommonTeams(th.Context, otherGMChannel.Id) + require.Nil(t, appErr) + require.Equal(t, 0, len(commonTeams)) + }) } func TestConvertGroupMessageToChannel(t *testing.T) {
5d8719042c18[MM-65684] Sanitize teams for /api/v4/channels/{channel_id}/common_teams endpoint (#34110) (#34181)
2 files changed · +47 −55
server/channels/api4/channel.go+1 −1 modified@@ -2461,7 +2461,7 @@ func getGroupMessageMembersCommonTeams(c *Context, w http.ResponseWriter, r *htt return } - if err := json.NewEncoder(w).Encode(teams); err != nil { + if err := json.NewEncoder(w).Encode(c.App.SanitizeTeams(*c.AppContext.Session(), teams)); err != nil { c.Logger.Warn("Error while writing response from getGroupMessageMembersCommonTeams", mlog.Err(err)) } }
server/channels/app/channel_test.go+46 −54 modified@@ -2863,69 +2863,61 @@ func TestIsCRTEnabledForUser(t *testing.T) { func TestGetGroupMessageMembersCommonTeams(t *testing.T) { mainHelper.Parallel(t) - th := SetupWithStoreMock(t) + th := Setup(t).InitBasic() defer th.TearDown() - mockStore := th.App.Srv().Store().(*mocks.Store) - - mockChannelStore := mocks.ChannelStore{} - mockStore.On("Channel").Return(&mockChannelStore) - mockChannelStore.On("Get", "gm_channel_id", true).Return(&model.Channel{Type: model.ChannelTypeGroup}, nil) - - mockTeamStore := mocks.TeamStore{} - mockStore.On("Team").Return(&mockTeamStore) - - th.App.Srv().Store().Team() - - mockTeamStore.On("GetCommonTeamIDsForMultipleUsers", []string{"user_id_1", "user_id_2"}).Return([]string{"team_id_1", "team_id_2", "team_id_3"}, nil).Times(1) - mockTeamStore.On("GetMany", []string{"team_id_1", "team_id_2", "team_id_3"}).Return( - []*model.Team{ - {DisplayName: "Team 1"}, - {DisplayName: "Team 2"}, - {DisplayName: "Team 3"}, - }, - nil, - ) + teamsToCreate := 2 + usersToCreate := 4 // at least 3 users to create a GM channel, last user is not in any team + teams := make([]string, 0, teamsToCreate) + for i := 0; i < cap(teams); i++ { + team := th.CreateTeam() + defer func(team *model.Team) { + appErr := th.App.PermanentDeleteTeam(th.Context, team) + require.Nil(t, appErr) + }(team) + teams = append(teams, team.Id) + } - mockUserStore := mocks.UserStore{} - mockStore.On("User").Return(&mockUserStore) - options := &model.UserGetOptions{ - PerPage: model.ChannelGroupMaxUsers, - Page: 0, - InChannelId: "gm_channel_id", - Inactive: false, - Active: true, + users := make([]string, 0, usersToCreate) + for i := 0; i < cap(users); i++ { + user := th.CreateUser() + defer func(user *model.User) { + appErr := th.App.PermanentDeleteUser(th.Context, user) + require.Nil(t, appErr) + }(user) + users = append(users, user.Id) } - mockUserStore.On("GetProfilesInChannel", options).Return([]*model.User{ - { - Id: "user_id_1", - }, - { - Id: "user_id_2", - }, - }, nil) - var err error - th.App.ch.srv.teamService, err = teams.New(teams.ServiceConfig{ - TeamStore: &mockTeamStore, - ChannelStore: &mockChannelStore, - GroupStore: &mocks.GroupStore{}, - Users: th.App.ch.srv.userService, - WebHub: th.App.ch.srv.platform, - ConfigFn: th.App.ch.srv.platform.Config, - LicenseFn: th.App.ch.srv.License, - }) - require.NoError(t, err) + for _, teamId := range teams { + // add first 3 users to each team, last user is not in any team + for i := range 3 { + _, _, appErr := th.App.AddUserToTeam(th.Context, teamId, users[i], "") + require.Nil(t, appErr) + } + } - commonTeams, appErr := th.App.GetGroupMessageMembersCommonTeams(th.Context, "gm_channel_id") + // create GM channel with first 3 users who share common teams + gmChannel, appErr := th.App.createGroupChannel(th.Context, users[:3], users[0]) require.Nil(t, appErr) - require.Equal(t, 3, len(commonTeams)) + require.NotNil(t, gmChannel) - // case of no common teams - mockTeamStore.On("GetCommonTeamIDsForMultipleUsers", []string{"user_id_1", "user_id_2"}).Return([]string{}, nil) - commonTeams, appErr = th.App.GetGroupMessageMembersCommonTeams(th.Context, "gm_channel_id") + // normally you can't create a GM channel with users that don't share any teams, but we do it here to test the edge case + // create GM channel with last 3 users, where last member is not in any team + otherGMChannel, appErr := th.App.createGroupChannel(th.Context, users[1:], users[0]) require.Nil(t, appErr) - require.Equal(t, 0, len(commonTeams)) + require.NotNil(t, otherGMChannel) + + t.Run("Get teams for GM channel", func(t *testing.T) { + commonTeams, appErr := th.App.GetGroupMessageMembersCommonTeams(th.Context, gmChannel.Id) + require.Nil(t, appErr) + require.Equal(t, 2, len(commonTeams)) + }) + + t.Run("No common teams", func(t *testing.T) { + commonTeams, appErr := th.App.GetGroupMessageMembersCommonTeams(th.Context, otherGMChannel.Id) + require.Nil(t, appErr) + require.Equal(t, 0, len(commonTeams)) + }) } func TestConvertGroupMessageToChannel(t *testing.T) {
9f54e5cdc3ae[MM-65684] Sanitize teams for /api/v4/channels/{channel_id}/common_teams endpoint (#34110) (#34182)
2 files changed · +47 −55
server/channels/api4/channel.go+1 −1 modified@@ -2467,7 +2467,7 @@ func getGroupMessageMembersCommonTeams(c *Context, w http.ResponseWriter, r *htt return } - if err := json.NewEncoder(w).Encode(teams); err != nil { + if err := json.NewEncoder(w).Encode(c.App.SanitizeTeams(*c.AppContext.Session(), teams)); err != nil { c.Logger.Warn("Error while writing response from getGroupMessageMembersCommonTeams", mlog.Err(err)) } }
server/channels/app/channel_test.go+46 −54 modified@@ -2863,69 +2863,61 @@ func TestIsCRTEnabledForUser(t *testing.T) { func TestGetGroupMessageMembersCommonTeams(t *testing.T) { mainHelper.Parallel(t) - th := SetupWithStoreMock(t) + th := Setup(t).InitBasic() defer th.TearDown() - mockStore := th.App.Srv().Store().(*mocks.Store) - - mockChannelStore := mocks.ChannelStore{} - mockStore.On("Channel").Return(&mockChannelStore) - mockChannelStore.On("Get", "gm_channel_id", true).Return(&model.Channel{Type: model.ChannelTypeGroup}, nil) - - mockTeamStore := mocks.TeamStore{} - mockStore.On("Team").Return(&mockTeamStore) - - th.App.Srv().Store().Team() - - mockTeamStore.On("GetCommonTeamIDsForMultipleUsers", []string{"user_id_1", "user_id_2"}).Return([]string{"team_id_1", "team_id_2", "team_id_3"}, nil).Times(1) - mockTeamStore.On("GetMany", []string{"team_id_1", "team_id_2", "team_id_3"}).Return( - []*model.Team{ - {DisplayName: "Team 1"}, - {DisplayName: "Team 2"}, - {DisplayName: "Team 3"}, - }, - nil, - ) + teamsToCreate := 2 + usersToCreate := 4 // at least 3 users to create a GM channel, last user is not in any team + teams := make([]string, 0, teamsToCreate) + for i := 0; i < cap(teams); i++ { + team := th.CreateTeam() + defer func(team *model.Team) { + appErr := th.App.PermanentDeleteTeam(th.Context, team) + require.Nil(t, appErr) + }(team) + teams = append(teams, team.Id) + } - mockUserStore := mocks.UserStore{} - mockStore.On("User").Return(&mockUserStore) - options := &model.UserGetOptions{ - PerPage: model.ChannelGroupMaxUsers, - Page: 0, - InChannelId: "gm_channel_id", - Inactive: false, - Active: true, + users := make([]string, 0, usersToCreate) + for i := 0; i < cap(users); i++ { + user := th.CreateUser() + defer func(user *model.User) { + appErr := th.App.PermanentDeleteUser(th.Context, user) + require.Nil(t, appErr) + }(user) + users = append(users, user.Id) } - mockUserStore.On("GetProfilesInChannel", options).Return([]*model.User{ - { - Id: "user_id_1", - }, - { - Id: "user_id_2", - }, - }, nil) - var err error - th.App.ch.srv.teamService, err = teams.New(teams.ServiceConfig{ - TeamStore: &mockTeamStore, - ChannelStore: &mockChannelStore, - GroupStore: &mocks.GroupStore{}, - Users: th.App.ch.srv.userService, - WebHub: th.App.ch.srv.platform, - ConfigFn: th.App.ch.srv.platform.Config, - LicenseFn: th.App.ch.srv.License, - }) - require.NoError(t, err) + for _, teamId := range teams { + // add first 3 users to each team, last user is not in any team + for i := range 3 { + _, _, appErr := th.App.AddUserToTeam(th.Context, teamId, users[i], "") + require.Nil(t, appErr) + } + } - commonTeams, appErr := th.App.GetGroupMessageMembersCommonTeams(th.Context, "gm_channel_id") + // create GM channel with first 3 users who share common teams + gmChannel, appErr := th.App.createGroupChannel(th.Context, users[:3], users[0]) require.Nil(t, appErr) - require.Equal(t, 3, len(commonTeams)) + require.NotNil(t, gmChannel) - // case of no common teams - mockTeamStore.On("GetCommonTeamIDsForMultipleUsers", []string{"user_id_1", "user_id_2"}).Return([]string{}, nil) - commonTeams, appErr = th.App.GetGroupMessageMembersCommonTeams(th.Context, "gm_channel_id") + // normally you can't create a GM channel with users that don't share any teams, but we do it here to test the edge case + // create GM channel with last 3 users, where last member is not in any team + otherGMChannel, appErr := th.App.createGroupChannel(th.Context, users[1:], users[0]) require.Nil(t, appErr) - require.Equal(t, 0, len(commonTeams)) + require.NotNil(t, otherGMChannel) + + t.Run("Get teams for GM channel", func(t *testing.T) { + commonTeams, appErr := th.App.GetGroupMessageMembersCommonTeams(th.Context, gmChannel.Id) + require.Nil(t, appErr) + require.Equal(t, 2, len(commonTeams)) + }) + + t.Run("No common teams", func(t *testing.T) { + commonTeams, appErr := th.App.GetGroupMessageMembersCommonTeams(th.Context, otherGMChannel.Id) + require.Nil(t, appErr) + require.Equal(t, 0, len(commonTeams)) + }) } func TestConvertGroupMessageToChannel(t *testing.T) {
649aee8fa918[MM-65684] Sanitize teams for /api/v4/channels/{channel_id}/common_teams endpoint (#34110) (#34183)
2 files changed · +47 −55
server/channels/api4/channel.go+1 −1 modified@@ -2432,7 +2432,7 @@ func getGroupMessageMembersCommonTeams(c *Context, w http.ResponseWriter, r *htt return } - if err := json.NewEncoder(w).Encode(teams); err != nil { + if err := json.NewEncoder(w).Encode(c.App.SanitizeTeams(*c.AppContext.Session(), teams)); err != nil { c.Logger.Warn("Error while writing response from getGroupMessageMembersCommonTeams", mlog.Err(err)) } }
server/channels/app/channel_test.go+46 −54 modified@@ -2743,69 +2743,61 @@ func TestIsCRTEnabledForUser(t *testing.T) { } func TestGetGroupMessageMembersCommonTeams(t *testing.T) { - th := SetupWithStoreMock(t) + th := Setup(t).InitBasic() defer th.TearDown() - mockStore := th.App.Srv().Store().(*mocks.Store) - - mockChannelStore := mocks.ChannelStore{} - mockStore.On("Channel").Return(&mockChannelStore) - mockChannelStore.On("Get", "gm_channel_id", true).Return(&model.Channel{Type: model.ChannelTypeGroup}, nil) - - mockTeamStore := mocks.TeamStore{} - mockStore.On("Team").Return(&mockTeamStore) - - th.App.Srv().Store().Team() - - mockTeamStore.On("GetCommonTeamIDsForMultipleUsers", []string{"user_id_1", "user_id_2"}).Return([]string{"team_id_1", "team_id_2", "team_id_3"}, nil).Times(1) - mockTeamStore.On("GetMany", []string{"team_id_1", "team_id_2", "team_id_3"}).Return( - []*model.Team{ - {DisplayName: "Team 1"}, - {DisplayName: "Team 2"}, - {DisplayName: "Team 3"}, - }, - nil, - ) + teamsToCreate := 2 + usersToCreate := 4 // at least 3 users to create a GM channel, last user is not in any team + teams := make([]string, 0, teamsToCreate) + for i := 0; i < cap(teams); i++ { + team := th.CreateTeam() + defer func(team *model.Team) { + appErr := th.App.PermanentDeleteTeam(th.Context, team) + require.Nil(t, appErr) + }(team) + teams = append(teams, team.Id) + } - mockUserStore := mocks.UserStore{} - mockStore.On("User").Return(&mockUserStore) - options := &model.UserGetOptions{ - PerPage: model.ChannelGroupMaxUsers, - Page: 0, - InChannelId: "gm_channel_id", - Inactive: false, - Active: true, + users := make([]string, 0, usersToCreate) + for i := 0; i < cap(users); i++ { + user := th.CreateUser() + defer func(user *model.User) { + appErr := th.App.PermanentDeleteUser(th.Context, user) + require.Nil(t, appErr) + }(user) + users = append(users, user.Id) } - mockUserStore.On("GetProfilesInChannel", options).Return([]*model.User{ - { - Id: "user_id_1", - }, - { - Id: "user_id_2", - }, - }, nil) - var err error - th.App.ch.srv.teamService, err = teams.New(teams.ServiceConfig{ - TeamStore: &mockTeamStore, - ChannelStore: &mockChannelStore, - GroupStore: &mocks.GroupStore{}, - Users: th.App.ch.srv.userService, - WebHub: th.App.ch.srv.platform, - ConfigFn: th.App.ch.srv.platform.Config, - LicenseFn: th.App.ch.srv.License, - }) - require.NoError(t, err) + for _, teamId := range teams { + // add first 3 users to each team, last user is not in any team + for i := range 3 { + _, _, appErr := th.App.AddUserToTeam(th.Context, teamId, users[i], "") + require.Nil(t, appErr) + } + } - commonTeams, appErr := th.App.GetGroupMessageMembersCommonTeams(th.Context, "gm_channel_id") + // create GM channel with first 3 users who share common teams + gmChannel, appErr := th.App.createGroupChannel(th.Context, users[:3]) require.Nil(t, appErr) - require.Equal(t, 3, len(commonTeams)) + require.NotNil(t, gmChannel) - // case of no common teams - mockTeamStore.On("GetCommonTeamIDsForMultipleUsers", []string{"user_id_1", "user_id_2"}).Return([]string{}, nil) - commonTeams, appErr = th.App.GetGroupMessageMembersCommonTeams(th.Context, "gm_channel_id") + // normally you can't create a GM channel with users that don't share any teams, but we do it here to test the edge case + // create GM channel with last 3 users, where last member is not in any team + otherGMChannel, appErr := th.App.createGroupChannel(th.Context, users[1:]) require.Nil(t, appErr) - require.Equal(t, 0, len(commonTeams)) + require.NotNil(t, otherGMChannel) + + t.Run("Get teams for GM channel", func(t *testing.T) { + commonTeams, appErr := th.App.GetGroupMessageMembersCommonTeams(th.Context, gmChannel.Id) + require.Nil(t, appErr) + require.Equal(t, 2, len(commonTeams)) + }) + + t.Run("No common teams", func(t *testing.T) { + commonTeams, appErr := th.App.GetGroupMessageMembersCommonTeams(th.Context, otherGMChannel.Id) + require.Nil(t, appErr) + require.Equal(t, 0, len(commonTeams)) + }) } func TestConvertGroupMessageToChannel(t *testing.T) {
abbf01b9db45[MM-65684] Sanitize teams for /api/v4/channels/{channel_id}/common_teams endpoint (#34110)
2 files changed · +47 −55
server/channels/api4/channel.go+1 −1 modified@@ -2462,7 +2462,7 @@ func getDirectOrGroupMessageMembersCommonTeams(c *Context, w http.ResponseWriter return } - if err := json.NewEncoder(w).Encode(teams); err != nil { + if err := json.NewEncoder(w).Encode(c.App.SanitizeTeams(*c.AppContext.Session(), teams)); err != nil { c.Logger.Warn("Error while writing response from getDirectOrGroupMessageMembersCommonTeams", mlog.Err(err)) } }
server/channels/app/channel_test.go+46 −54 modified@@ -2862,69 +2862,61 @@ func TestIsCRTEnabledForUser(t *testing.T) { func TestGetDirectOrGroupMessageMembersCommonTeams(t *testing.T) { mainHelper.Parallel(t) - th := SetupWithStoreMock(t) + th := Setup(t).InitBasic() defer th.TearDown() - mockStore := th.App.Srv().Store().(*mocks.Store) - - mockChannelStore := mocks.ChannelStore{} - mockStore.On("Channel").Return(&mockChannelStore) - mockChannelStore.On("Get", "gm_channel_id", true).Return(&model.Channel{Type: model.ChannelTypeGroup}, nil) - - mockTeamStore := mocks.TeamStore{} - mockStore.On("Team").Return(&mockTeamStore) - - th.App.Srv().Store().Team() - - mockTeamStore.On("GetCommonTeamIDsForMultipleUsers", []string{"user_id_1", "user_id_2"}).Return([]string{"team_id_1", "team_id_2", "team_id_3"}, nil).Times(1) - mockTeamStore.On("GetMany", []string{"team_id_1", "team_id_2", "team_id_3"}).Return( - []*model.Team{ - {DisplayName: "Team 1"}, - {DisplayName: "Team 2"}, - {DisplayName: "Team 3"}, - }, - nil, - ) + teamsToCreate := 2 + usersToCreate := 4 // at least 3 users to create a GM channel, last user is not in any team + teams := make([]string, 0, teamsToCreate) + for i := 0; i < cap(teams); i++ { + team := th.CreateTeam() + defer func(team *model.Team) { + appErr := th.App.PermanentDeleteTeam(th.Context, team) + require.Nil(t, appErr) + }(team) + teams = append(teams, team.Id) + } - mockUserStore := mocks.UserStore{} - mockStore.On("User").Return(&mockUserStore) - options := &model.UserGetOptions{ - PerPage: model.ChannelGroupMaxUsers, - Page: 0, - InChannelId: "gm_channel_id", - Inactive: false, - Active: true, + users := make([]string, 0, usersToCreate) + for i := 0; i < cap(users); i++ { + user := th.CreateUser() + defer func(user *model.User) { + appErr := th.App.PermanentDeleteUser(th.Context, user) + require.Nil(t, appErr) + }(user) + users = append(users, user.Id) } - mockUserStore.On("GetProfilesInChannel", options).Return([]*model.User{ - { - Id: "user_id_1", - }, - { - Id: "user_id_2", - }, - }, nil) - var err error - th.App.ch.srv.teamService, err = teams.New(teams.ServiceConfig{ - TeamStore: &mockTeamStore, - ChannelStore: &mockChannelStore, - GroupStore: &mocks.GroupStore{}, - Users: th.App.ch.srv.userService, - WebHub: th.App.ch.srv.platform, - ConfigFn: th.App.ch.srv.platform.Config, - LicenseFn: th.App.ch.srv.License, - }) - require.NoError(t, err) + for _, teamId := range teams { + // add first 3 users to each team, last user is not in any team + for i := range 3 { + _, _, appErr := th.App.AddUserToTeam(th.Context, teamId, users[i], "") + require.Nil(t, appErr) + } + } - commonTeams, appErr := th.App.GetDirectOrGroupMessageMembersCommonTeams(th.Context, "gm_channel_id") + // create GM channel with first 3 users who share common teams + gmChannel, appErr := th.App.createGroupChannel(th.Context, users[:3], users[0]) require.Nil(t, appErr) - require.Equal(t, 3, len(commonTeams)) + require.NotNil(t, gmChannel) - // case of no common teams - mockTeamStore.On("GetCommonTeamIDsForMultipleUsers", []string{"user_id_1", "user_id_2"}).Return([]string{}, nil) - commonTeams, appErr = th.App.GetDirectOrGroupMessageMembersCommonTeams(th.Context, "gm_channel_id") + // normally you can't create a GM channel with users that don't share any teams, but we do it here to test the edge case + // create GM channel with last 3 users, where last member is not in any team + otherGMChannel, appErr := th.App.createGroupChannel(th.Context, users[1:], users[0]) require.Nil(t, appErr) - require.Equal(t, 0, len(commonTeams)) + require.NotNil(t, otherGMChannel) + + t.Run("Get teams for GM channel", func(t *testing.T) { + commonTeams, appErr := th.App.GetDirectOrGroupMessageMembersCommonTeams(th.Context, gmChannel.Id) + require.Nil(t, appErr) + require.Equal(t, 2, len(commonTeams)) + }) + + t.Run("No common teams", func(t *testing.T) { + commonTeams, appErr := th.App.GetDirectOrGroupMessageMembersCommonTeams(th.Context, otherGMChannel.Id) + require.Nil(t, appErr) + require.Equal(t, 0, len(commonTeams)) + }) } func TestConvertGroupMessageToChannel(t *testing.T) {
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
9- github.com/advisories/GHSA-4g87-9x45-cx2hghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-12559ghsaADVISORY
- github.com/mattermost/mattermost/commit/5d8719042c1807da59ac8a821624eb01152d8495ghsaWEB
- github.com/mattermost/mattermost/commit/649aee8fa9184ca59bd66022a33b8f8918e413aaghsaWEB
- github.com/mattermost/mattermost/commit/7ccb62db7958abd6a4b21a06c5a4f5367a8f8b1fghsaWEB
- github.com/mattermost/mattermost/commit/9f54e5cdc3aef412945ff0e6a58338f7b549bddaghsaWEB
- github.com/mattermost/mattermost/commit/abbf01b9db45d1850eaf3701ea8362b910193ffdghsaWEB
- github.com/mattermost/mattermost/pull/34110ghsaWEB
- mattermost.com/security-updatesghsaWEB
News mentions
0No linked articles in our index yet.