MM-67049: Fix unauthorized access to public channels in private teams (#34886)

* do not return channels from teams a user is not a member of

* add explicit tests (clearer than adding it above)

* linting

* explicitly test incudeDeleted true and false--it was implicit before
This commit is contained in:
Christopher Poile
2026-01-13 18:21:06 +00:00
committed by GitHub
parent 8e4cadbc88
commit a18b80ba4c
2 changed files with 23 additions and 4 deletions
@@ -3082,11 +3082,12 @@ func (s SqlChannelStore) Autocomplete(rctx request.CTX, userID, term string, inc
OrderBy("c.DisplayName").
Limit(model.ChannelSearchDefaultLimit)
// Always filter out soft-deleted team memberships - users removed from
// a team should not see channels from that team regardless of includeDeleted
query = query.Where(sq.Eq{"tm.DeleteAt": 0})
if !includeDeleted {
query = query.Where(sq.And{
sq.Eq{"c.DeleteAt": 0},
sq.Eq{"tm.DeleteAt": 0},
})
query = query.Where(sq.Eq{"c.DeleteAt": 0})
}
if isGuest {
@@ -6401,6 +6401,24 @@ func testAutocomplete(t *testing.T, rctx request.CTX, ss store.Store, s SqlStore
})
}
// MM-67049: Verify that users removed from a team cannot see channels from that
// team, regardless of includeDeleted. The includeDeleted parameter should only
// affect channel deletion status, not team membership.
t.Run("MM-67049: removed team member cannot see channels regardless of includeDeleted", func(t *testing.T) {
// Sanity check: o5 is in leftTeamID and matches search term
require.Equal(t, leftTeamID, o5.TeamId)
require.Contains(t, o5.DisplayName, "ChannelA")
// m1.UserId was removed from leftTeamID (tm5.DeleteAt was set above in the test setup)
for _, includeDeleted := range []bool{false, true} {
channels, err2 := ss.Channel().Autocomplete(rctx, m1.UserId, "ChannelA", includeDeleted, false)
require.NoError(t, err2)
for _, ch := range channels {
require.NotEqual(t, o5.Id, ch.Id, "includeDeleted=%v: channel from left team should not be returned", includeDeleted)
}
}
})
t.Run("Limit", func(t *testing.T) {
for i := range model.ChannelSearchDefaultLimit + 10 {
_, err = ss.Channel().Save(rctx, &model.Channel{