Validate RefreshedToken differs from original invite token (#34864) (#35656)

Automatic Merge
Этот коммит содержится в:
Mattermost Build
2026-03-17 12:31:12 +01:00
коммит произвёл GitHub
родитель 305be32134
Коммит 8c4ed0b65b
2 изменённых файлов: 44 добавлений и 0 удалений

Просмотреть файл

@@ -71,6 +71,9 @@ func (rcs *Service) ReceiveInviteConfirmation(confirm model.RemoteClusterInvite)
// If the accepting cluster sent a RefreshedToken (its RemoteToken), set it as our Token
if confirm.Version >= 2 && confirm.RefreshedToken != "" {
if confirm.RefreshedToken == rc.Token {
return nil, fmt.Errorf("cannot accept invite confirmation for remote %s: RefreshedToken must be different from the original invite token", confirm.RemoteId)
}
rc.Token = confirm.RefreshedToken
} else {
// For older versions or if no RefreshedToken was provided, generate a new token

Просмотреть файл

@@ -258,6 +258,47 @@ func TestReceiveInviteConfirmation_TokenInvalidation(t *testing.T) {
remoteClusterStoreMock.AssertExpectations(t)
})
t.Run("Protocol v2+ with RefreshedToken equal to original token - rejected (MM-67098)", func(t *testing.T) {
// Security: RefreshedToken must be different from the original invite token.
// If the remote sends back the same token, they did not actually refresh; reject.
originalToken := model.NewId()
remoteId := model.NewId()
originalRC := &model.RemoteCluster{
RemoteId: remoteId,
Token: originalToken,
SiteURL: model.SiteURLPending + model.NewId(),
CreateAt: model.GetMillis(),
}
remoteClusterStoreMock := &mocks.RemoteClusterStore{}
remoteClusterStoreMock.On("Get", remoteId, false).Return(originalRC, nil)
// Update must NOT be called when RefreshedToken == rc.Token
storeMock := &mocks.Store{}
storeMock.On("RemoteCluster").Return(remoteClusterStoreMock)
mockServer := newMockServerWithStore(t, storeMock)
mockApp := newMockApp(t, nil)
service, err := NewRemoteClusterService(mockServer, mockApp)
require.NoError(t, err)
confirm := model.RemoteClusterInvite{
RemoteId: remoteId,
SiteURL: "http://example.com",
Token: model.NewId(),
RefreshedToken: originalToken, // Same as rc.Token - invalid, must be different
Version: 3,
}
rcUpdated, err := service.ReceiveInviteConfirmation(confirm)
require.Error(t, err)
assert.Nil(t, rcUpdated)
assert.Contains(t, err.Error(), "RefreshedToken must be different from the original invite token")
remoteClusterStoreMock.AssertNotCalled(t, "Update", mock.Anything)
})
}
// TestReceiveInviteConfirmation_EdgeCases tests various edge cases