VYPR
Moderate severityNVD Advisory· Published Apr 5, 2024· Updated Aug 2, 2024

Invite ID available to team admins even without the "Add Members" permission

CVE-2024-29221

Description

Improper Access Control in Mattermost Server versions 9.5.x before 9.5.2, 9.4.x before 9.4.4, 9.3.x before 9.3.3, 8.1.x before 8.1.11 lacked proper access control in the /api/v4/users/me/teams endpoint allowing a team admin to get the invite ID of their team, thus allowing them to invite users, even if the "Add Members" permission was explicitly removed from team admins.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/mattermost/mattermost/server/v8Go
>= 8.1.0, < 8.1.118.1.11
github.com/mattermost/mattermost/server/v8Go
>= 9.5.0, < 9.5.29.5.2
github.com/mattermost/mattermost/server/v8Go
>= 9.4.0, < 9.4.49.4.4
github.com/mattermost/mattermost/server/v8Go
>= 9.3.0, < 9.3.39.3.3

Affected products

1

Patches

4
0dc03fbc6e3c

MM-56822 Update logic around permissions and sanitization (#26227) (#26344)

https://github.com/mattermost/mattermostMattermost BuildFeb 29, 2024via ghsa
2 files changed · +39 10
  • server/channels/api4/team_test.go+28 2 modified
    @@ -327,7 +327,19 @@ func TestGetTeamSanitization(t *testing.T) {
     		require.Empty(t, rteam.InviteId, "should have sanitized inviteid")
     	})
     
    -	t.Run("team admin", func(t *testing.T) {
    +	t.Run("team admin default removed", func(t *testing.T) {
    +		// the above test removes PermissionInviteUser from TeamUser,
    +		// which also removes it from TeamAdmin. By default, TeamAdmin
    +		// permission is inherited from TeamUser.
    +		rteam, _, err := th.Client.GetTeam(context.Background(), team.Id, "")
    +		require.NoError(t, err)
    +
    +		require.NotEmpty(t, rteam.Email, "should not have sanitized email")
    +		require.Empty(t, rteam.InviteId, "should have sanitized inviteid")
    +	})
    +
    +	t.Run("team admin permission re-added", func(t *testing.T) {
    +		th.AddPermissionToRole(model.PermissionInviteUser.Id, model.TeamAdminRoleId)
     		rteam, _, err := th.Client.GetTeam(context.Background(), team.Id, "")
     		require.NoError(t, err)
     
    @@ -1454,7 +1466,19 @@ func TestGetTeamByNameSanitization(t *testing.T) {
     		require.Empty(t, rteam.InviteId, "should have sanitized inviteid")
     	})
     
    -	t.Run("team admin/non-admin", func(t *testing.T) {
    +	t.Run("team admin/non-admin without invite permission", func(t *testing.T) {
    +		// the above test removes PermissionInviteUser from TeamUser,
    +		// which also removes it from TeamAdmin. By default, TeamAdmin
    +		// permission is inherited from TeamUser.
    +		rteam, _, err := th.Client.GetTeamByName(context.Background(), team.Name, "")
    +		require.NoError(t, err)
    +
    +		require.NotEmpty(t, rteam.Email, "should not have sanitized email")
    +		require.Empty(t, rteam.InviteId, "should have sanitized inviteid")
    +	})
    +
    +	t.Run("team admin/non-admin with invite permission", func(t *testing.T) {
    +		th.AddPermissionToRole(model.PermissionInviteUser.Id, model.TeamAdminRoleId)
     		rteam, _, err := th.Client.GetTeamByName(context.Background(), team.Name, "")
     		require.NoError(t, err)
     
    @@ -1863,6 +1887,8 @@ func TestGetTeamsForUserSanitization(t *testing.T) {
     
     		client := th.CreateClient()
     		th.RemovePermissionFromRole(model.PermissionInviteUser.Id, model.TeamUserRoleId)
    +		defer th.AddPermissionToRole(model.PermissionInviteUser.Id, model.TeamUserRoleId)
    +
     		th.LoginBasic2WithClient(client)
     
     		rteams, _, err := client.GetTeamsForUser(context.Background(), th.BasicUser2.Id, "")
    
  • server/channels/app/team.go+11 8 modified
    @@ -1930,19 +1930,22 @@ func (a *App) GetTeamIdFromQuery(query url.Values) (string, *model.AppError) {
     }
     
     func (a *App) SanitizeTeam(session model.Session, team *model.Team) *model.Team {
    -	if a.SessionHasPermissionToTeam(session, team.Id, model.PermissionManageTeam) {
    -		return team
    -	}
    +	manageTeamPermission := a.SessionHasPermissionToTeam(session, team.Id, model.PermissionManageTeam)
    +	inviteUserPermission := a.SessionHasPermissionToTeam(session, team.Id, model.PermissionInviteUser)
     
    -	if a.SessionHasPermissionToTeam(session, team.Id, model.PermissionInviteUser) {
    -		inviteId := team.InviteId
    -		team.Sanitize()
    -		team.InviteId = inviteId
    +	if manageTeamPermission && inviteUserPermission {
     		return team
     	}
    -
    +	email := team.Email
    +	inviteId := team.InviteId
     	team.Sanitize()
     
    +	if manageTeamPermission {
    +		team.Email = email
    +	}
    +	if inviteUserPermission {
    +		team.InviteId = inviteId
    +	}
     	return team
     }
     
    
a5784f34ba65

MM-56822 Update logic around permissions and sanitization (#26227) (#26343)

https://github.com/mattermost/mattermostMattermost BuildFeb 29, 2024via ghsa
2 files changed · +39 10
  • server/channels/api4/team_test.go+28 2 modified
    @@ -326,7 +326,19 @@ func TestGetTeamSanitization(t *testing.T) {
     		require.Empty(t, rteam.InviteId, "should have sanitized inviteid")
     	})
     
    -	t.Run("team admin", func(t *testing.T) {
    +	t.Run("team admin default removed", func(t *testing.T) {
    +		// the above test removes PermissionInviteUser from TeamUser,
    +		// which also removes it from TeamAdmin. By default, TeamAdmin
    +		// permission is inherited from TeamUser.
    +		rteam, _, err := th.Client.GetTeam(context.Background(), team.Id, "")
    +		require.NoError(t, err)
    +
    +		require.NotEmpty(t, rteam.Email, "should not have sanitized email")
    +		require.Empty(t, rteam.InviteId, "should have sanitized inviteid")
    +	})
    +
    +	t.Run("team admin permission re-added", func(t *testing.T) {
    +		th.AddPermissionToRole(model.PermissionInviteUser.Id, model.TeamAdminRoleId)
     		rteam, _, err := th.Client.GetTeam(context.Background(), team.Id, "")
     		require.NoError(t, err)
     
    @@ -1452,7 +1464,19 @@ func TestGetTeamByNameSanitization(t *testing.T) {
     		require.Empty(t, rteam.InviteId, "should have sanitized inviteid")
     	})
     
    -	t.Run("team admin/non-admin", func(t *testing.T) {
    +	t.Run("team admin/non-admin without invite permission", func(t *testing.T) {
    +		// the above test removes PermissionInviteUser from TeamUser,
    +		// which also removes it from TeamAdmin. By default, TeamAdmin
    +		// permission is inherited from TeamUser.
    +		rteam, _, err := th.Client.GetTeamByName(context.Background(), team.Name, "")
    +		require.NoError(t, err)
    +
    +		require.NotEmpty(t, rteam.Email, "should not have sanitized email")
    +		require.Empty(t, rteam.InviteId, "should have sanitized inviteid")
    +	})
    +
    +	t.Run("team admin/non-admin with invite permission", func(t *testing.T) {
    +		th.AddPermissionToRole(model.PermissionInviteUser.Id, model.TeamAdminRoleId)
     		rteam, _, err := th.Client.GetTeamByName(context.Background(), team.Name, "")
     		require.NoError(t, err)
     
    @@ -1861,6 +1885,8 @@ func TestGetTeamsForUserSanitization(t *testing.T) {
     
     		client := th.CreateClient()
     		th.RemovePermissionFromRole(model.PermissionInviteUser.Id, model.TeamUserRoleId)
    +		defer th.AddPermissionToRole(model.PermissionInviteUser.Id, model.TeamUserRoleId)
    +
     		th.LoginBasic2WithClient(client)
     
     		rteams, _, err := client.GetTeamsForUser(context.Background(), th.BasicUser2.Id, "")
    
  • server/channels/app/team.go+11 8 modified
    @@ -1928,19 +1928,22 @@ func (a *App) GetTeamIdFromQuery(query url.Values) (string, *model.AppError) {
     }
     
     func (a *App) SanitizeTeam(session model.Session, team *model.Team) *model.Team {
    -	if a.SessionHasPermissionToTeam(session, team.Id, model.PermissionManageTeam) {
    -		return team
    -	}
    +	manageTeamPermission := a.SessionHasPermissionToTeam(session, team.Id, model.PermissionManageTeam)
    +	inviteUserPermission := a.SessionHasPermissionToTeam(session, team.Id, model.PermissionInviteUser)
     
    -	if a.SessionHasPermissionToTeam(session, team.Id, model.PermissionInviteUser) {
    -		inviteId := team.InviteId
    -		team.Sanitize()
    -		team.InviteId = inviteId
    +	if manageTeamPermission && inviteUserPermission {
     		return team
     	}
    -
    +	email := team.Email
    +	inviteId := team.InviteId
     	team.Sanitize()
     
    +	if manageTeamPermission {
    +		team.Email = email
    +	}
    +	if inviteUserPermission {
    +		team.InviteId = inviteId
    +	}
     	return team
     }
     
    
5cce9fed7363

MM-56822 Update logic around permissions and sanitization (#26227) (#26342)

https://github.com/mattermost/mattermostMattermost BuildFeb 29, 2024via ghsa
2 files changed · +39 10
  • server/channels/api4/team_test.go+28 2 modified
    @@ -326,7 +326,19 @@ func TestGetTeamSanitization(t *testing.T) {
     		require.Empty(t, rteam.InviteId, "should have sanitized inviteid")
     	})
     
    -	t.Run("team admin", func(t *testing.T) {
    +	t.Run("team admin default removed", func(t *testing.T) {
    +		// the above test removes PermissionInviteUser from TeamUser,
    +		// which also removes it from TeamAdmin. By default, TeamAdmin
    +		// permission is inherited from TeamUser.
    +		rteam, _, err := th.Client.GetTeam(context.Background(), team.Id, "")
    +		require.NoError(t, err)
    +
    +		require.NotEmpty(t, rteam.Email, "should not have sanitized email")
    +		require.Empty(t, rteam.InviteId, "should have sanitized inviteid")
    +	})
    +
    +	t.Run("team admin permission re-added", func(t *testing.T) {
    +		th.AddPermissionToRole(model.PermissionInviteUser.Id, model.TeamAdminRoleId)
     		rteam, _, err := th.Client.GetTeam(context.Background(), team.Id, "")
     		require.NoError(t, err)
     
    @@ -1452,7 +1464,19 @@ func TestGetTeamByNameSanitization(t *testing.T) {
     		require.Empty(t, rteam.InviteId, "should have sanitized inviteid")
     	})
     
    -	t.Run("team admin/non-admin", func(t *testing.T) {
    +	t.Run("team admin/non-admin without invite permission", func(t *testing.T) {
    +		// the above test removes PermissionInviteUser from TeamUser,
    +		// which also removes it from TeamAdmin. By default, TeamAdmin
    +		// permission is inherited from TeamUser.
    +		rteam, _, err := th.Client.GetTeamByName(context.Background(), team.Name, "")
    +		require.NoError(t, err)
    +
    +		require.NotEmpty(t, rteam.Email, "should not have sanitized email")
    +		require.Empty(t, rteam.InviteId, "should have sanitized inviteid")
    +	})
    +
    +	t.Run("team admin/non-admin with invite permission", func(t *testing.T) {
    +		th.AddPermissionToRole(model.PermissionInviteUser.Id, model.TeamAdminRoleId)
     		rteam, _, err := th.Client.GetTeamByName(context.Background(), team.Name, "")
     		require.NoError(t, err)
     
    @@ -1861,6 +1885,8 @@ func TestGetTeamsForUserSanitization(t *testing.T) {
     
     		client := th.CreateClient()
     		th.RemovePermissionFromRole(model.PermissionInviteUser.Id, model.TeamUserRoleId)
    +		defer th.AddPermissionToRole(model.PermissionInviteUser.Id, model.TeamUserRoleId)
    +
     		th.LoginBasic2WithClient(client)
     
     		rteams, _, err := client.GetTeamsForUser(context.Background(), th.BasicUser2.Id, "")
    
  • server/channels/app/team.go+11 8 modified
    @@ -1928,19 +1928,22 @@ func (a *App) GetTeamIdFromQuery(query url.Values) (string, *model.AppError) {
     }
     
     func (a *App) SanitizeTeam(session model.Session, team *model.Team) *model.Team {
    -	if a.SessionHasPermissionToTeam(session, team.Id, model.PermissionManageTeam) {
    -		return team
    -	}
    +	manageTeamPermission := a.SessionHasPermissionToTeam(session, team.Id, model.PermissionManageTeam)
    +	inviteUserPermission := a.SessionHasPermissionToTeam(session, team.Id, model.PermissionInviteUser)
     
    -	if a.SessionHasPermissionToTeam(session, team.Id, model.PermissionInviteUser) {
    -		inviteId := team.InviteId
    -		team.Sanitize()
    -		team.InviteId = inviteId
    +	if manageTeamPermission && inviteUserPermission {
     		return team
     	}
    -
    +	email := team.Email
    +	inviteId := team.InviteId
     	team.Sanitize()
     
    +	if manageTeamPermission {
    +		team.Email = email
    +	}
    +	if inviteUserPermission {
    +		team.InviteId = inviteId
    +	}
     	return team
     }
     
    
dd3fe2991a70

MM-56822 Update logic around permissions and sanitization (#26227) (#26337)

https://github.com/mattermost/mattermostMattermost BuildFeb 29, 2024via ghsa
2 files changed · +39 10
  • server/channels/api4/team_test.go+28 2 modified
    @@ -326,7 +326,19 @@ func TestGetTeamSanitization(t *testing.T) {
     		require.Empty(t, rteam.InviteId, "should have sanitized inviteid")
     	})
     
    -	t.Run("team admin", func(t *testing.T) {
    +	t.Run("team admin default removed", func(t *testing.T) {
    +		// the above test removes PermissionInviteUser from TeamUser,
    +		// which also removes it from TeamAdmin. By default, TeamAdmin
    +		// permission is inherited from TeamUser.
    +		rteam, _, err := th.Client.GetTeam(context.Background(), team.Id, "")
    +		require.NoError(t, err)
    +
    +		require.NotEmpty(t, rteam.Email, "should not have sanitized email")
    +		require.Empty(t, rteam.InviteId, "should have sanitized inviteid")
    +	})
    +
    +	t.Run("team admin permission re-added", func(t *testing.T) {
    +		th.AddPermissionToRole(model.PermissionInviteUser.Id, model.TeamAdminRoleId)
     		rteam, _, err := th.Client.GetTeam(context.Background(), team.Id, "")
     		require.NoError(t, err)
     
    @@ -1452,7 +1464,19 @@ func TestGetTeamByNameSanitization(t *testing.T) {
     		require.Empty(t, rteam.InviteId, "should have sanitized inviteid")
     	})
     
    -	t.Run("team admin/non-admin", func(t *testing.T) {
    +	t.Run("team admin/non-admin without invite permission", func(t *testing.T) {
    +		// the above test removes PermissionInviteUser from TeamUser,
    +		// which also removes it from TeamAdmin. By default, TeamAdmin
    +		// permission is inherited from TeamUser.
    +		rteam, _, err := th.Client.GetTeamByName(context.Background(), team.Name, "")
    +		require.NoError(t, err)
    +
    +		require.NotEmpty(t, rteam.Email, "should not have sanitized email")
    +		require.Empty(t, rteam.InviteId, "should have sanitized inviteid")
    +	})
    +
    +	t.Run("team admin/non-admin with invite permission", func(t *testing.T) {
    +		th.AddPermissionToRole(model.PermissionInviteUser.Id, model.TeamAdminRoleId)
     		rteam, _, err := th.Client.GetTeamByName(context.Background(), team.Name, "")
     		require.NoError(t, err)
     
    @@ -1861,6 +1885,8 @@ func TestGetTeamsForUserSanitization(t *testing.T) {
     
     		client := th.CreateClient()
     		th.RemovePermissionFromRole(model.PermissionInviteUser.Id, model.TeamUserRoleId)
    +		defer th.AddPermissionToRole(model.PermissionInviteUser.Id, model.TeamUserRoleId)
    +
     		th.LoginBasic2WithClient(client)
     
     		rteams, _, err := client.GetTeamsForUser(context.Background(), th.BasicUser2.Id, "")
    
  • server/channels/app/team.go+11 8 modified
    @@ -1928,19 +1928,22 @@ func (a *App) GetTeamIdFromQuery(query url.Values) (string, *model.AppError) {
     }
     
     func (a *App) SanitizeTeam(session model.Session, team *model.Team) *model.Team {
    -	if a.SessionHasPermissionToTeam(session, team.Id, model.PermissionManageTeam) {
    -		return team
    -	}
    +	manageTeamPermission := a.SessionHasPermissionToTeam(session, team.Id, model.PermissionManageTeam)
    +	inviteUserPermission := a.SessionHasPermissionToTeam(session, team.Id, model.PermissionInviteUser)
     
    -	if a.SessionHasPermissionToTeam(session, team.Id, model.PermissionInviteUser) {
    -		inviteId := team.InviteId
    -		team.Sanitize()
    -		team.InviteId = inviteId
    +	if manageTeamPermission && inviteUserPermission {
     		return team
     	}
    -
    +	email := team.Email
    +	inviteId := team.InviteId
     	team.Sanitize()
     
    +	if manageTeamPermission {
    +		team.Email = email
    +	}
    +	if inviteUserPermission {
    +		team.InviteId = inviteId
    +	}
     	return team
     }
     
    

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

8

News mentions

0

No linked articles in our index yet.