VYPR
Moderate severityNVD Advisory· Published Dec 11, 2025· Updated Dec 11, 2025

Zitadel Discloses the Total Number of Instance Users

CVE-2025-67717

Description

ZITADEL is an open-source identity infrastructure tool. Versions 2.44.0 through 3.4.4 and 4.0.0-rc.1 through 4.7.1 disclose the total number of instance users to authenticated users, regardless of their specific permissions. While this does not leak individual user data or PII, disclosing the total user count via the totalResult field constitutes an information disclosure vulnerability that may be sensitive in certain contexts. This issue is fixed in versions 3.4.5 and 4.7.2.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/zitadel/zitadelGo
>= 4.0.0-rc.1, < 4.7.24.7.2
github.com/zitadel/zitadelGo
>= 2.44.0, < 3.4.53.4.5
github.com/zitadel/zitadelGo
< 1.80.0-v2.20.0.20251210121356-826039c6208f1.80.0-v2.20.0.20251210121356-826039c6208f

Affected products

1

Patches

1
826039c6208f

Merge commit from fork

https://github.com/zitadel/zitadelMarco A.Dec 10, 2025via ghsa
4 files changed · +44 1276
  • internal/api/grpc/user/v2beta/integration_test/query_test.go+40 104 modified
    @@ -4,7 +4,6 @@ package user_test
     
     import (
     	"context"
    -	"errors"
     	"slices"
     	"testing"
     	"time"
    @@ -15,7 +14,6 @@ import (
     	"google.golang.org/protobuf/types/known/timestamppb"
     
     	"github.com/zitadel/zitadel/internal/integration"
    -	"github.com/zitadel/zitadel/pkg/grpc/feature/v2"
     	"github.com/zitadel/zitadel/pkg/grpc/object/v2"
     	object_v2beta "github.com/zitadel/zitadel/pkg/grpc/object/v2beta"
     	"github.com/zitadel/zitadel/pkg/grpc/session/v2"
    @@ -30,55 +28,6 @@ func detailsV2ToV2beta(obj *object.Details) *object_v2beta.Details {
     	}
     }
     
    -var (
    -	permissionCheckV2SetFlagInital bool
    -	permissionCheckV2SetFlag       bool
    -)
    -
    -type permissionCheckV2SettingsStruct struct {
    -	TestNamePrependString string
    -	SetFlag               bool
    -}
    -
    -var permissionCheckV2Settings []permissionCheckV2SettingsStruct = []permissionCheckV2SettingsStruct{
    -	{
    -		SetFlag:               false,
    -		TestNamePrependString: "permission_check_v2 IS NOT SET" + " ",
    -	},
    -	{
    -		SetFlag:               true,
    -		TestNamePrependString: "permission_check_v2 IS SET" + " ",
    -	},
    -}
    -
    -func setPermissionCheckV2Flag(t *testing.T, setFlag bool) {
    -	if permissionCheckV2SetFlagInital && permissionCheckV2SetFlag == setFlag {
    -		return
    -	}
    -
    -	_, err := Instance.Client.FeatureV2.SetInstanceFeatures(IamCTX, &feature.SetInstanceFeaturesRequest{
    -		PermissionCheckV2: &setFlag,
    -	})
    -	require.NoError(t, err)
    -
    -	var flagSet bool
    -	for i := 0; !flagSet || i < 6; i++ {
    -		res, err := Instance.Client.FeatureV2.GetInstanceFeatures(IamCTX, &feature.GetInstanceFeaturesRequest{})
    -		require.NoError(t, err)
    -		if res.PermissionCheckV2.Enabled == setFlag {
    -			flagSet = true
    -			continue
    -		}
    -		time.Sleep(10 * time.Second)
    -	}
    -
    -	if !flagSet {
    -		require.NoError(t, errors.New("unable to set permission_check_v2 flag"))
    -	}
    -	permissionCheckV2SetFlagInital = true
    -	permissionCheckV2SetFlag = setFlag
    -}
    -
     func TestServer_GetUserByID(t *testing.T) {
     	orgResp := Instance.CreateOrganization(IamCTX, integration.OrganizationName(), integration.Email())
     	type args struct {
    @@ -431,11 +380,6 @@ func createUser(ctx context.Context, orgID string, passwordChangeRequired bool)
     }
     
     func TestServer_ListUsers(t *testing.T) {
    -	t.Cleanup(func() {
    -		_, err := Instance.Client.FeatureV2.ResetInstanceFeatures(IamCTX, &feature.ResetInstanceFeaturesRequest{})
    -		require.NoError(t, err)
    -	})
    -
     	orgResp := Instance.CreateOrganization(IamCTX, integration.OrganizationName(), integration.Email())
     	type args struct {
     		ctx context.Context
    @@ -1111,7 +1055,6 @@ func TestServer_ListUsers(t *testing.T) {
     				func(ctx context.Context, request *user_v2beta.ListUsersRequest) userAttrs {
     					orgRespForOrgTests := Instance.CreateOrganization(IamCTX, integration.OrganizationName(), integration.Email())
     					orgRespForOrgTests2 := Instance.CreateOrganization(IamCTX, integration.OrganizationName(), integration.Email())
    -					// info := createUser(ctx, orgRespForOrgTests.OrganizationId, false)
     					createUser(ctx, orgRespForOrgTests.OrganizationId, false)
     					request.Queries = []*user_v2beta.SearchQuery{}
     					request.Queries = append(request.Queries, OrganizationIdQuery(orgRespForOrgTests2.OrganizationId))
    @@ -1120,7 +1063,7 @@ func TestServer_ListUsers(t *testing.T) {
     			},
     			want: &user_v2beta.ListUsersResponse{
     				Details: &object_v2beta.ListDetails{
    -					TotalResult: 0,
    +					TotalResult: 1,
     					Timestamp:   timestamppb.Now(),
     				},
     				SortingColumn: 0,
    @@ -1131,58 +1074,51 @@ func TestServer_ListUsers(t *testing.T) {
     			},
     		},
     	}
    -	for _, f := range permissionCheckV2Settings {
    -		for _, tc := range tt {
    -			t.Run(f.TestNamePrependString+tc.name, func(t1 *testing.T) {
    -				setPermissionCheckV2Flag(t1, f.SetFlag)
    -				infos := tc.args.dep(IamCTX, tc.args.req)
    +	for _, tc := range tt {
    +		t.Run(tc.name, func(t1 *testing.T) {
    +			infos := tc.args.dep(IamCTX, tc.args.req)
     
    -				// retryDuration, tick := integration.WaitForAndTickWithMaxDuration(tt.args.ctx, 10*time.Minute)
    -				retryDuration, tick := integration.WaitForAndTickWithMaxDuration(tc.args.ctx, time.Minute)
    -				require.EventuallyWithT(t1, func(ttt *assert.CollectT) {
    -					got, err := Client.ListUsers(tc.args.ctx, tc.args.req)
    -					if tc.wantErr {
    -						require.Error(ttt, err)
    -						return
    -					}
    -					require.NoError(ttt, err)
    -
    -					// always only give back dependency infos which are required for the response
    -					require.Len(ttt, tc.want.Result, len(infos))
    -					// always first check length, otherwise its failed anyway
    -					if assert.Len(ttt, got.Result, len(tc.want.Result)) {
    -						// totalResult is unrelated to the tests here so gets carried over, can vary from the count of results due to permissions
    -						tc.want.Details.TotalResult = got.Details.TotalResult
    +			retryDuration, tick := integration.WaitForAndTickWithMaxDuration(tc.args.ctx, time.Minute)
    +			require.EventuallyWithT(t1, func(ttt *assert.CollectT) {
    +				got, err := Client.ListUsers(tc.args.ctx, tc.args.req)
    +				if tc.wantErr {
    +					require.Error(ttt, err)
    +					return
    +				}
    +				require.NoError(ttt, err)
     
    -						// fill in userid and username as it is generated
    -						for i := range infos {
    -							if tc.want.Result[i] == nil {
    -								continue
    -							}
    -							tc.want.Result[i].UserId = infos[i].UserID
    -							tc.want.Result[i].Username = infos[i].Username
    -							tc.want.Result[i].PreferredLoginName = infos[i].Username
    -							tc.want.Result[i].LoginNames = []string{infos[i].Username}
    -							if human := tc.want.Result[i].GetHuman(); human != nil {
    -								human.Email.Email = infos[i].Username
    -								human.Phone.Phone = infos[i].Phone
    -								if tc.want.Result[i].GetHuman().GetPasswordChanged() != nil {
    -									human.PasswordChanged = infos[i].Changed
    -								}
    -							}
    -							tc.want.Result[i].Details = detailsV2ToV2beta(infos[i].Details)
    +				// always only give back dependency infos which are required for the response
    +				require.Len(ttt, tc.want.Result, len(infos))
    +				// always first check length, otherwise its failed anyway
    +				if assert.Len(ttt, got.Result, len(tc.want.Result)) {
    +					// fill in userid and username as it is generated
    +					for i := range infos {
    +						if tc.want.Result[i] == nil {
    +							continue
     						}
    -						for i := range tc.want.Result {
    -							if tc.want.Result[i] == nil {
    -								continue
    +						tc.want.Result[i].UserId = infos[i].UserID
    +						tc.want.Result[i].Username = infos[i].Username
    +						tc.want.Result[i].PreferredLoginName = infos[i].Username
    +						tc.want.Result[i].LoginNames = []string{infos[i].Username}
    +						if human := tc.want.Result[i].GetHuman(); human != nil {
    +							human.Email.Email = infos[i].Username
    +							human.Phone.Phone = infos[i].Phone
    +							if tc.want.Result[i].GetHuman().GetPasswordChanged() != nil {
    +								human.PasswordChanged = infos[i].Changed
     							}
    -							assert.EqualExportedValues(ttt, got.Result[i], tc.want.Result[i])
     						}
    +						tc.want.Result[i].Details = detailsV2ToV2beta(infos[i].Details)
    +					}
    +					for i := range tc.want.Result {
    +						if tc.want.Result[i] == nil {
    +							continue
    +						}
    +						assert.EqualExportedValues(ttt, got.Result[i], tc.want.Result[i])
     					}
    -					integration.AssertListDetails(ttt, tc.want, got)
    -				}, retryDuration, tick, "timeout waiting for expected user result")
    -			})
    -		}
    +				}
    +				integration.AssertListDetails(ttt, tc.want, got)
    +			}, retryDuration, tick, "timeout waiting for expected user result")
    +		})
     	}
     }
     
    
  • internal/api/grpc/user/v2/integration_test/query_test.go+2 1035 modified
    @@ -5,7 +5,6 @@ package user_test
     import (
     	"context"
     	"encoding/base64"
    -	"fmt"
     	"slices"
     	"testing"
     	"time"
    @@ -384,952 +383,6 @@ func createUserWithUserName(ctx context.Context, instance *integration.Instance,
     }
     
     func TestServer_ListUsers(t *testing.T) {
    -	orgResp := Instance.CreateOrganization(IamCTX, integration.OrganizationName(), integration.Email())
    -	type args struct {
    -		ctx context.Context
    -		req *user.ListUsersRequest
    -		dep func(ctx context.Context, request *user.ListUsersRequest) userAttrs
    -	}
    -	tt := []struct {
    -		name    string
    -		args    args
    -		want    *user.ListUsersResponse
    -		wantErr bool
    -	}{
    -		{
    -			name: "list user by id, no permission machine user",
    -			args: args{
    -				UserCTX,
    -				&user.ListUsersRequest{},
    -				func(ctx context.Context, request *user.ListUsersRequest) userAttrs {
    -					info := createUser(ctx, Instance, orgResp.OrganizationId, false)
    -					request.Queries = append(request.Queries, InUserIDsQuery([]string{info.UserID}))
    -					return []userAttr{}
    -				},
    -			},
    -			want: &user.ListUsersResponse{
    -				Details: &object.ListDetails{
    -					TotalResult: 0,
    -					Timestamp:   timestamppb.Now(),
    -				},
    -				SortingColumn: 0,
    -				Result:        []*user.User{},
    -			},
    -		},
    -		{
    -			name: "list user by id, no permission human user",
    -			args: func() args {
    -				info := createUser(IamCTX, Instance, orgResp.OrganizationId, true)
    -				// create session to get token
    -				userID := info.UserID
    -				createResp, err := Instance.Client.SessionV2.CreateSession(IamCTX, &session.CreateSessionRequest{
    -					Checks: &session.Checks{
    -						User: &session.CheckUser{
    -							Search: &session.CheckUser_UserId{UserId: userID},
    -						},
    -						Password: &session.CheckPassword{
    -							Password: integration.UserPassword,
    -						},
    -					},
    -				})
    -				if err != nil {
    -					require.NoError(t, err)
    -				}
    -				// use token to get ctx
    -				HumanCTX := integration.WithAuthorizationToken(IamCTX, createResp.GetSessionToken())
    -				return args{
    -					HumanCTX,
    -					&user.ListUsersRequest{},
    -					func(ctx context.Context, request *user.ListUsersRequest) userAttrs {
    -						return []userAttr{info}
    -					},
    -				}
    -			}(),
    -			want: &user.ListUsersResponse{ // human user should return itself when calling ListUsers() even if it has no permissions
    -				Details: &object.ListDetails{
    -					TotalResult: 1,
    -					Timestamp:   timestamppb.Now(),
    -				},
    -				SortingColumn: 0,
    -				Result: []*user.User{
    -					{
    -						State: user.UserState_USER_STATE_ACTIVE,
    -						Type: &user.User_Human{
    -							Human: &user.HumanUser{
    -								Profile: &user.HumanProfile{
    -									GivenName:         "Mickey",
    -									FamilyName:        "Mouse",
    -									NickName:          gu.Ptr("Mickey"),
    -									DisplayName:       gu.Ptr("Mickey Mouse"),
    -									PreferredLanguage: gu.Ptr("nl"),
    -									Gender:            user.Gender_GENDER_MALE.Enum(),
    -								},
    -								Email: &user.HumanEmail{
    -									IsVerified: true,
    -								},
    -								Phone: &user.HumanPhone{
    -									IsVerified: true,
    -								},
    -								PasswordChangeRequired: true,
    -								PasswordChanged:        timestamppb.Now(),
    -							},
    -						},
    -					},
    -				},
    -			},
    -		},
    -		{
    -			name: "list user by id, ok",
    -			args: args{
    -				IamCTX,
    -				&user.ListUsersRequest{},
    -				func(ctx context.Context, request *user.ListUsersRequest) userAttrs {
    -					info := createUser(ctx, Instance, orgResp.OrganizationId, false)
    -					request.Queries = []*user.SearchQuery{}
    -					request.Queries = append(request.Queries, OrganizationIdQuery(orgResp.OrganizationId))
    -					request.Queries = append(request.Queries, InUserIDsQuery([]string{info.UserID}))
    -					return []userAttr{info}
    -				},
    -			},
    -			want: &user.ListUsersResponse{
    -				Details: &object.ListDetails{
    -					TotalResult: 1,
    -					Timestamp:   timestamppb.Now(),
    -				},
    -				SortingColumn: 0,
    -				Result: []*user.User{
    -					{
    -						State: user.UserState_USER_STATE_ACTIVE,
    -						Type: &user.User_Human{
    -							Human: &user.HumanUser{
    -								Profile: &user.HumanProfile{
    -									GivenName:         "Mickey",
    -									FamilyName:        "Mouse",
    -									NickName:          gu.Ptr("Mickey"),
    -									DisplayName:       gu.Ptr("Mickey Mouse"),
    -									PreferredLanguage: gu.Ptr("nl"),
    -									Gender:            user.Gender_GENDER_MALE.Enum(),
    -								},
    -								Email: &user.HumanEmail{
    -									IsVerified: true,
    -								},
    -								Phone: &user.HumanPhone{
    -									IsVerified: true,
    -								},
    -							},
    -						},
    -					},
    -				},
    -			},
    -		},
    -		{
    -			name: "list user by id, passwordChangeRequired, ok",
    -			args: args{
    -				IamCTX,
    -				&user.ListUsersRequest{},
    -				func(ctx context.Context, request *user.ListUsersRequest) userAttrs {
    -					info := createUser(ctx, Instance, orgResp.OrganizationId, true)
    -					request.Queries = []*user.SearchQuery{}
    -					request.Queries = append(request.Queries, OrganizationIdQuery(orgResp.OrganizationId))
    -					request.Queries = append(request.Queries, InUserIDsQuery([]string{info.UserID}))
    -					return []userAttr{info}
    -				},
    -			},
    -			want: &user.ListUsersResponse{
    -				Details: &object.ListDetails{
    -					TotalResult: 1,
    -					Timestamp:   timestamppb.Now(),
    -				},
    -				SortingColumn: 0,
    -				Result: []*user.User{
    -					{
    -						State: user.UserState_USER_STATE_ACTIVE,
    -						Type: &user.User_Human{
    -							Human: &user.HumanUser{
    -								Profile: &user.HumanProfile{
    -									GivenName:         "Mickey",
    -									FamilyName:        "Mouse",
    -									NickName:          gu.Ptr("Mickey"),
    -									DisplayName:       gu.Ptr("Mickey Mouse"),
    -									PreferredLanguage: gu.Ptr("nl"),
    -									Gender:            user.Gender_GENDER_MALE.Enum(),
    -								},
    -								Email: &user.HumanEmail{
    -									IsVerified: true,
    -								},
    -								Phone: &user.HumanPhone{
    -									IsVerified: true,
    -								},
    -								PasswordChangeRequired: true,
    -								PasswordChanged:        timestamppb.Now(),
    -							},
    -						},
    -					},
    -				},
    -			},
    -		},
    -		{
    -			name: "list user by id and meta key multiple, ok",
    -			args: args{
    -				IamCTX,
    -				&user.ListUsersRequest{},
    -				func(ctx context.Context, request *user.ListUsersRequest) userAttrs {
    -					infos := createUsers(ctx, Instance, orgResp.OrganizationId, 3, false)
    -					request.Queries = []*user.SearchQuery{}
    -					request.Queries = append(request.Queries, OrganizationIdQuery(orgResp.OrganizationId))
    -					request.Queries = append(request.Queries, InUserIDsQuery(infos.userIDs()))
    -
    -					Instance.SetUserMetadata(ctx, infos[0].UserID, "my meta", "my value 1")
    -					Instance.SetUserMetadata(ctx, infos[1].UserID, "my meta 2", "my value 3")
    -					Instance.SetUserMetadata(ctx, infos[2].UserID, "my meta", "my value 2")
    -
    -					request.Queries = append(request.Queries, MetadataKeyContainsQuery("my meta"))
    -					request.SortingColumn = user.UserFieldName_USER_FIELD_NAME_CREATION_DATE
    -					return infos
    -				},
    -			},
    -			want: &user.ListUsersResponse{
    -				Details: &object.ListDetails{
    -					TotalResult: 3,
    -					Timestamp:   timestamppb.Now(),
    -				},
    -				SortingColumn: user.UserFieldName_USER_FIELD_NAME_CREATION_DATE,
    -				Result: []*user.User{
    -					{
    -						State: user.UserState_USER_STATE_ACTIVE,
    -						Type: &user.User_Human{
    -							Human: &user.HumanUser{
    -								Profile: &user.HumanProfile{
    -									GivenName:         "Mickey",
    -									FamilyName:        "Mouse",
    -									NickName:          gu.Ptr("Mickey"),
    -									DisplayName:       gu.Ptr("Mickey Mouse"),
    -									PreferredLanguage: gu.Ptr("nl"),
    -									Gender:            user.Gender_GENDER_MALE.Enum(),
    -								},
    -								Email: &user.HumanEmail{
    -									IsVerified: true,
    -								},
    -								Phone: &user.HumanPhone{
    -									IsVerified: true,
    -								},
    -							},
    -						},
    -					},
    -					{
    -						State: user.UserState_USER_STATE_ACTIVE,
    -						Type: &user.User_Human{
    -							Human: &user.HumanUser{
    -								Profile: &user.HumanProfile{
    -									GivenName:         "Mickey",
    -									FamilyName:        "Mouse",
    -									NickName:          gu.Ptr("Mickey"),
    -									DisplayName:       gu.Ptr("Mickey Mouse"),
    -									PreferredLanguage: gu.Ptr("nl"),
    -									Gender:            user.Gender_GENDER_MALE.Enum(),
    -								},
    -								Email: &user.HumanEmail{
    -									IsVerified: true,
    -								},
    -								Phone: &user.HumanPhone{
    -									IsVerified: true,
    -								},
    -							},
    -						},
    -					},
    -					{
    -						State: user.UserState_USER_STATE_ACTIVE,
    -						Type: &user.User_Human{
    -							Human: &user.HumanUser{
    -								Profile: &user.HumanProfile{
    -									GivenName:         "Mickey",
    -									FamilyName:        "Mouse",
    -									NickName:          gu.Ptr("Mickey"),
    -									DisplayName:       gu.Ptr("Mickey Mouse"),
    -									PreferredLanguage: gu.Ptr("nl"),
    -									Gender:            user.Gender_GENDER_MALE.Enum(),
    -								},
    -								Email: &user.HumanEmail{
    -									IsVerified: true,
    -								},
    -								Phone: &user.HumanPhone{
    -									IsVerified: true,
    -								},
    -							},
    -						},
    -					},
    -				},
    -			},
    -		},
    -		{
    -			// https://github.com/zitadel/zitadel/issues/10825
    -			name: "list user with metadata by IDs with offset and limit, ok",
    -			args: args{
    -				IamCTX,
    -				&user.ListUsersRequest{},
    -				func(ctx context.Context, request *user.ListUsersRequest) userAttrs {
    -					infos := createUsers(ctx, Instance, orgResp.OrganizationId, 3, false)
    -					request.Queries = []*user.SearchQuery{}
    -					request.Queries = append(request.Queries, OrganizationIdQuery(orgResp.OrganizationId))
    -					request.Queries = append(request.Queries, InUserIDsQuery(infos.userIDs()))
    -
    -					// With the original bug, this would multiply the "TotalResult" by 2.
    -					for _, user := range infos {
    -						for i := 0; i < 2; i++ {
    -							Instance.SetUserMetadata(ctx, user.UserID, fmt.Sprintf("key-%d", i), fmt.Sprintf("value-%d", i))
    -						}
    -					}
    -					infos = infos[1:] // prevent panic in user ID setting below
    -
    -					request.SortingColumn = user.UserFieldName_USER_FIELD_NAME_CREATION_DATE
    -					request.Query = &object.ListQuery{
    -						Offset: 1,
    -						Limit:  2,
    -					}
    -					return infos
    -				},
    -			},
    -			want: &user.ListUsersResponse{
    -				Details: &object.ListDetails{
    -					TotalResult: 3,
    -					Timestamp:   timestamppb.Now(),
    -				},
    -				SortingColumn: user.UserFieldName_USER_FIELD_NAME_CREATION_DATE,
    -				Result: []*user.User{
    -					{
    -						State: user.UserState_USER_STATE_ACTIVE,
    -						Type: &user.User_Human{
    -							Human: &user.HumanUser{
    -								Profile: &user.HumanProfile{
    -									GivenName:         "Mickey",
    -									FamilyName:        "Mouse",
    -									NickName:          gu.Ptr("Mickey"),
    -									DisplayName:       gu.Ptr("Mickey Mouse"),
    -									PreferredLanguage: gu.Ptr("nl"),
    -									Gender:            user.Gender_GENDER_MALE.Enum(),
    -								},
    -								Email: &user.HumanEmail{
    -									IsVerified: true,
    -								},
    -								Phone: &user.HumanPhone{
    -									IsVerified: true,
    -								},
    -							},
    -						},
    -					},
    -					{
    -						State: user.UserState_USER_STATE_ACTIVE,
    -						Type: &user.User_Human{
    -							Human: &user.HumanUser{
    -								Profile: &user.HumanProfile{
    -									GivenName:         "Mickey",
    -									FamilyName:        "Mouse",
    -									NickName:          gu.Ptr("Mickey"),
    -									DisplayName:       gu.Ptr("Mickey Mouse"),
    -									PreferredLanguage: gu.Ptr("nl"),
    -									Gender:            user.Gender_GENDER_MALE.Enum(),
    -								},
    -								Email: &user.HumanEmail{
    -									IsVerified: true,
    -								},
    -								Phone: &user.HumanPhone{
    -									IsVerified: true,
    -								},
    -							},
    -						},
    -					},
    -				},
    -			},
    -		},
    -		{
    -			name: "list user by username, ok",
    -			args: args{
    -				IamCTX,
    -				&user.ListUsersRequest{},
    -				func(ctx context.Context, request *user.ListUsersRequest) userAttrs {
    -					info := createUser(ctx, Instance, orgResp.OrganizationId, false)
    -					request.Queries = []*user.SearchQuery{}
    -					request.Queries = append(request.Queries, OrganizationIdQuery(orgResp.OrganizationId))
    -					request.Queries = append(request.Queries, UsernameQuery(info.Username))
    -
    -					request.SortingColumn = user.UserFieldName_USER_FIELD_NAME_CREATION_DATE
    -					return []userAttr{info}
    -				},
    -			},
    -			want: &user.ListUsersResponse{
    -				Details: &object.ListDetails{
    -					TotalResult: 1,
    -					Timestamp:   timestamppb.Now(),
    -				},
    -				SortingColumn: user.UserFieldName_USER_FIELD_NAME_CREATION_DATE,
    -				Result: []*user.User{
    -					{
    -						State: user.UserState_USER_STATE_ACTIVE,
    -						Type: &user.User_Human{
    -							Human: &user.HumanUser{
    -								Profile: &user.HumanProfile{
    -									GivenName:         "Mickey",
    -									FamilyName:        "Mouse",
    -									NickName:          gu.Ptr("Mickey"),
    -									DisplayName:       gu.Ptr("Mickey Mouse"),
    -									PreferredLanguage: gu.Ptr("nl"),
    -									Gender:            user.Gender_GENDER_MALE.Enum(),
    -								},
    -								Email: &user.HumanEmail{
    -									IsVerified: true,
    -								},
    -								Phone: &user.HumanPhone{
    -									IsVerified: true,
    -								},
    -							},
    -						},
    -					},
    -				},
    -			},
    -		},
    -		{
    -			name: "list user in emails, ok",
    -			args: args{
    -				IamCTX,
    -				&user.ListUsersRequest{},
    -				func(ctx context.Context, request *user.ListUsersRequest) userAttrs {
    -					info := createUser(ctx, Instance, orgResp.OrganizationId, false)
    -					request.Queries = []*user.SearchQuery{}
    -					request.Queries = append(request.Queries, OrganizationIdQuery(orgResp.OrganizationId))
    -					request.Queries = append(request.Queries, InUserEmailsQuery([]string{info.Username}))
    -					request.SortingColumn = user.UserFieldName_USER_FIELD_NAME_CREATION_DATE
    -					return []userAttr{info}
    -				},
    -			},
    -			want: &user.ListUsersResponse{
    -				Details: &object.ListDetails{
    -					TotalResult: 1,
    -					Timestamp:   timestamppb.Now(),
    -				},
    -				SortingColumn: user.UserFieldName_USER_FIELD_NAME_CREATION_DATE,
    -				Result: []*user.User{
    -					{
    -						State: user.UserState_USER_STATE_ACTIVE,
    -						Type: &user.User_Human{
    -							Human: &user.HumanUser{
    -								Profile: &user.HumanProfile{
    -									GivenName:         "Mickey",
    -									FamilyName:        "Mouse",
    -									NickName:          gu.Ptr("Mickey"),
    -									DisplayName:       gu.Ptr("Mickey Mouse"),
    -									PreferredLanguage: gu.Ptr("nl"),
    -									Gender:            user.Gender_GENDER_MALE.Enum(),
    -								},
    -								Email: &user.HumanEmail{
    -									IsVerified: true,
    -								},
    -								Phone: &user.HumanPhone{
    -									IsVerified: true,
    -								},
    -							},
    -						},
    -					},
    -				},
    -			},
    -		},
    -		{
    -			name: "list user by emails and meta value multiple, ok",
    -			args: args{
    -				IamCTX,
    -				&user.ListUsersRequest{},
    -				func(ctx context.Context, request *user.ListUsersRequest) userAttrs {
    -					infos := createUsers(ctx, Instance, orgResp.OrganizationId, 3, false)
    -					request.Queries = []*user.SearchQuery{}
    -					request.Queries = append(request.Queries, OrganizationIdQuery(orgResp.OrganizationId))
    -					request.Queries = append(request.Queries, InUserEmailsQuery(infos.emails()))
    -
    -					Instance.SetUserMetadata(ctx, infos[0].UserID, "my meta 1", "my value")
    -					Instance.SetUserMetadata(ctx, infos[0].UserID, "my meta 2", "my value")
    -					Instance.SetUserMetadata(ctx, infos[1].UserID, "my meta 2", "my value")
    -					Instance.SetUserMetadata(ctx, infos[2].UserID, "my meta", "my value")
    -
    -					request.Queries = append(request.Queries, MetadataValueQuery("my value"))
    -					request.SortingColumn = user.UserFieldName_USER_FIELD_NAME_CREATION_DATE
    -
    -					return infos
    -				},
    -			},
    -			want: &user.ListUsersResponse{
    -				Details: &object.ListDetails{
    -					TotalResult: 3,
    -					Timestamp:   timestamppb.Now(),
    -				},
    -				SortingColumn: user.UserFieldName_USER_FIELD_NAME_CREATION_DATE,
    -				Result: []*user.User{
    -					{
    -						State: user.UserState_USER_STATE_ACTIVE,
    -						Type: &user.User_Human{
    -							Human: &user.HumanUser{
    -								Profile: &user.HumanProfile{
    -									GivenName:         "Mickey",
    -									FamilyName:        "Mouse",
    -									NickName:          gu.Ptr("Mickey"),
    -									DisplayName:       gu.Ptr("Mickey Mouse"),
    -									PreferredLanguage: gu.Ptr("nl"),
    -									Gender:            user.Gender_GENDER_MALE.Enum(),
    -								},
    -								Email: &user.HumanEmail{
    -									IsVerified: true,
    -								},
    -								Phone: &user.HumanPhone{
    -									IsVerified: true,
    -								},
    -							},
    -						},
    -					}, {
    -						State: user.UserState_USER_STATE_ACTIVE,
    -						Type: &user.User_Human{
    -							Human: &user.HumanUser{
    -								Profile: &user.HumanProfile{
    -									GivenName:         "Mickey",
    -									FamilyName:        "Mouse",
    -									NickName:          gu.Ptr("Mickey"),
    -									DisplayName:       gu.Ptr("Mickey Mouse"),
    -									PreferredLanguage: gu.Ptr("nl"),
    -									Gender:            user.Gender_GENDER_MALE.Enum(),
    -								},
    -								Email: &user.HumanEmail{
    -									IsVerified: true,
    -								},
    -								Phone: &user.HumanPhone{
    -									IsVerified: true,
    -								},
    -							},
    -						},
    -					}, {
    -						State: user.UserState_USER_STATE_ACTIVE,
    -						Type: &user.User_Human{
    -							Human: &user.HumanUser{
    -								Profile: &user.HumanProfile{
    -									GivenName:         "Mickey",
    -									FamilyName:        "Mouse",
    -									NickName:          gu.Ptr("Mickey"),
    -									DisplayName:       gu.Ptr("Mickey Mouse"),
    -									PreferredLanguage: gu.Ptr("nl"),
    -									Gender:            user.Gender_GENDER_MALE.Enum(),
    -								},
    -								Email: &user.HumanEmail{
    -									IsVerified: true,
    -								},
    -								Phone: &user.HumanPhone{
    -									IsVerified: true,
    -								},
    -							},
    -						},
    -					},
    -				},
    -			},
    -		},
    -		{
    -			// https://github.com/zitadel/zitadel/issues/10825
    -			name: "list user with metadata by emails with offset and limit, ok",
    -			args: args{
    -				IamCTX,
    -				&user.ListUsersRequest{},
    -				func(ctx context.Context, request *user.ListUsersRequest) userAttrs {
    -					infos := createUsers(ctx, Instance, orgResp.OrganizationId, 3, false)
    -					request.Queries = []*user.SearchQuery{}
    -					request.Queries = append(request.Queries, OrganizationIdQuery(orgResp.OrganizationId))
    -					request.Queries = append(request.Queries, InUserEmailsQuery(infos.emails()))
    -
    -					// With the original bug, this would multiply the "TotalResult" by 2.
    -					for _, user := range infos {
    -						for i := 0; i < 2; i++ {
    -							Instance.SetUserMetadata(ctx, user.UserID, fmt.Sprintf("key-%d", i), fmt.Sprintf("value-%d", i))
    -						}
    -					}
    -					infos = infos[1:] // prevent panic in user ID setting below
    -
    -					request.SortingColumn = user.UserFieldName_USER_FIELD_NAME_CREATION_DATE
    -					request.Query = &object.ListQuery{
    -						Offset: 1,
    -						Limit:  2,
    -					}
    -					return infos
    -				},
    -			},
    -			want: &user.ListUsersResponse{
    -				Details: &object.ListDetails{
    -					TotalResult: 3,
    -					Timestamp:   timestamppb.Now(),
    -				},
    -				SortingColumn: user.UserFieldName_USER_FIELD_NAME_CREATION_DATE,
    -				Result: []*user.User{
    -					{
    -						State: user.UserState_USER_STATE_ACTIVE,
    -						Type: &user.User_Human{
    -							Human: &user.HumanUser{
    -								Profile: &user.HumanProfile{
    -									GivenName:         "Mickey",
    -									FamilyName:        "Mouse",
    -									NickName:          gu.Ptr("Mickey"),
    -									DisplayName:       gu.Ptr("Mickey Mouse"),
    -									PreferredLanguage: gu.Ptr("nl"),
    -									Gender:            user.Gender_GENDER_MALE.Enum(),
    -								},
    -								Email: &user.HumanEmail{
    -									IsVerified: true,
    -								},
    -								Phone: &user.HumanPhone{
    -									IsVerified: true,
    -								},
    -							},
    -						},
    -					}, {
    -						State: user.UserState_USER_STATE_ACTIVE,
    -						Type: &user.User_Human{
    -							Human: &user.HumanUser{
    -								Profile: &user.HumanProfile{
    -									GivenName:         "Mickey",
    -									FamilyName:        "Mouse",
    -									NickName:          gu.Ptr("Mickey"),
    -									DisplayName:       gu.Ptr("Mickey Mouse"),
    -									PreferredLanguage: gu.Ptr("nl"),
    -									Gender:            user.Gender_GENDER_MALE.Enum(),
    -								},
    -								Email: &user.HumanEmail{
    -									IsVerified: true,
    -								},
    -								Phone: &user.HumanPhone{
    -									IsVerified: true,
    -								},
    -							},
    -						},
    -					},
    -				},
    -			},
    -		},
    -		{
    -			name: "list user in emails no found, ok",
    -			args: args{
    -				IamCTX,
    -				&user.ListUsersRequest{
    -					Queries: []*user.SearchQuery{
    -						OrganizationIdQuery(orgResp.OrganizationId),
    -						InUserEmailsQuery([]string{"notfound"}),
    -					},
    -				},
    -				func(ctx context.Context, request *user.ListUsersRequest) userAttrs {
    -					return []userAttr{}
    -				},
    -			},
    -			want: &user.ListUsersResponse{
    -				Details: &object.ListDetails{
    -					TotalResult: 0,
    -					Timestamp:   timestamppb.Now(),
    -				},
    -				SortingColumn: 0,
    -				Result:        []*user.User{},
    -			},
    -		},
    -		{
    -			name: "list user phone, ok",
    -			args: args{
    -				IamCTX,
    -				&user.ListUsersRequest{},
    -				func(ctx context.Context, request *user.ListUsersRequest) userAttrs {
    -					info := createUser(ctx, Instance, orgResp.OrganizationId, false)
    -					request.Queries = []*user.SearchQuery{}
    -					request.Queries = append(request.Queries, OrganizationIdQuery(orgResp.OrganizationId))
    -					request.Queries = append(request.Queries, PhoneQuery(info.Phone))
    -					return []userAttr{info}
    -				},
    -			},
    -			want: &user.ListUsersResponse{
    -				Details: &object.ListDetails{
    -					TotalResult: 1,
    -					Timestamp:   timestamppb.Now(),
    -				},
    -				SortingColumn: 0,
    -				Result: []*user.User{
    -					{
    -						State: user.UserState_USER_STATE_ACTIVE,
    -						Type: &user.User_Human{
    -							Human: &user.HumanUser{
    -								Profile: &user.HumanProfile{
    -									GivenName:         "Mickey",
    -									FamilyName:        "Mouse",
    -									NickName:          gu.Ptr("Mickey"),
    -									DisplayName:       gu.Ptr("Mickey Mouse"),
    -									PreferredLanguage: gu.Ptr("nl"),
    -									Gender:            user.Gender_GENDER_MALE.Enum(),
    -								},
    -								Email: &user.HumanEmail{
    -									IsVerified: true,
    -								},
    -								Phone: &user.HumanPhone{
    -									IsVerified: true,
    -								},
    -							},
    -						},
    -					},
    -				},
    -			},
    -		},
    -		{
    -			name: "list user in emails no found, ok",
    -			args: args{
    -				IamCTX,
    -				&user.ListUsersRequest{
    -					Queries: []*user.SearchQuery{
    -						OrganizationIdQuery(orgResp.OrganizationId),
    -						InUserEmailsQuery([]string{"notfound"}),
    -					},
    -				},
    -				func(ctx context.Context, request *user.ListUsersRequest) userAttrs {
    -					return []userAttr{}
    -				},
    -			},
    -			want: &user.ListUsersResponse{
    -				Details: &object.ListDetails{
    -					TotalResult: 0,
    -					Timestamp:   timestamppb.Now(),
    -				},
    -				SortingColumn: 0,
    -				Result:        []*user.User{},
    -			},
    -		},
    -		{
    -			name: "list user resourceowner multiple, ok",
    -			args: args{
    -				IamCTX,
    -				&user.ListUsersRequest{},
    -				func(ctx context.Context, request *user.ListUsersRequest) userAttrs {
    -					orgResp := Instance.CreateOrganization(ctx, integration.OrganizationName(), integration.Email())
    -
    -					infos := createUsers(ctx, Instance, orgResp.OrganizationId, 3, false)
    -					request.Queries = []*user.SearchQuery{}
    -					request.Queries = append(request.Queries, OrganizationIdQuery(orgResp.OrganizationId))
    -					request.Queries = append(request.Queries, InUserEmailsQuery(infos.emails()))
    -					request.SortingColumn = user.UserFieldName_USER_FIELD_NAME_CREATION_DATE
    -					return infos
    -				},
    -			},
    -			want: &user.ListUsersResponse{
    -				Details: &object.ListDetails{
    -					TotalResult: 3,
    -					Timestamp:   timestamppb.Now(),
    -				},
    -				SortingColumn: user.UserFieldName_USER_FIELD_NAME_CREATION_DATE,
    -				Result: []*user.User{
    -					{
    -						State: user.UserState_USER_STATE_ACTIVE,
    -						Type: &user.User_Human{
    -							Human: &user.HumanUser{
    -								Profile: &user.HumanProfile{
    -									GivenName:         "Mickey",
    -									FamilyName:        "Mouse",
    -									NickName:          gu.Ptr("Mickey"),
    -									DisplayName:       gu.Ptr("Mickey Mouse"),
    -									PreferredLanguage: gu.Ptr("nl"),
    -									Gender:            user.Gender_GENDER_MALE.Enum(),
    -								},
    -								Email: &user.HumanEmail{
    -									IsVerified: true,
    -								},
    -								Phone: &user.HumanPhone{
    -									IsVerified: true,
    -								},
    -							},
    -						},
    -					}, {
    -						State: user.UserState_USER_STATE_ACTIVE,
    -						Type: &user.User_Human{
    -							Human: &user.HumanUser{
    -								Profile: &user.HumanProfile{
    -									GivenName:         "Mickey",
    -									FamilyName:        "Mouse",
    -									NickName:          gu.Ptr("Mickey"),
    -									DisplayName:       gu.Ptr("Mickey Mouse"),
    -									PreferredLanguage: gu.Ptr("nl"),
    -									Gender:            user.Gender_GENDER_MALE.Enum(),
    -								},
    -								Email: &user.HumanEmail{
    -									IsVerified: true,
    -								},
    -								Phone: &user.HumanPhone{
    -									IsVerified: true,
    -								},
    -							},
    -						},
    -					}, {
    -						State: user.UserState_USER_STATE_ACTIVE,
    -						Type: &user.User_Human{
    -							Human: &user.HumanUser{
    -								Profile: &user.HumanProfile{
    -									GivenName:         "Mickey",
    -									FamilyName:        "Mouse",
    -									NickName:          gu.Ptr("Mickey"),
    -									DisplayName:       gu.Ptr("Mickey Mouse"),
    -									PreferredLanguage: gu.Ptr("nl"),
    -									Gender:            user.Gender_GENDER_MALE.Enum(),
    -								},
    -								Email: &user.HumanEmail{
    -									IsVerified: true,
    -								},
    -								Phone: &user.HumanPhone{
    -									IsVerified: true,
    -								},
    -							},
    -						},
    -					},
    -				},
    -			},
    -		},
    -		{
    -			name: "list user with org query",
    -			args: args{
    -				IamCTX,
    -				&user.ListUsersRequest{},
    -				func(ctx context.Context, request *user.ListUsersRequest) userAttrs {
    -					orgRespForOrgTests := Instance.CreateOrganization(IamCTX, integration.OrganizationName(), integration.Email())
    -					info := createUser(ctx, Instance, orgRespForOrgTests.OrganizationId, false)
    -					request.Queries = []*user.SearchQuery{}
    -					request.Queries = append(request.Queries, OrganizationIdQuery(orgRespForOrgTests.OrganizationId))
    -					request.SortingColumn = user.UserFieldName_USER_FIELD_NAME_CREATION_DATE
    -					return []userAttr{info, {}}
    -				},
    -			},
    -			want: &user.ListUsersResponse{
    -				Details: &object.ListDetails{
    -					TotalResult: 2,
    -					Timestamp:   timestamppb.Now(),
    -				},
    -				SortingColumn: user.UserFieldName_USER_FIELD_NAME_CREATION_DATE,
    -				Result: []*user.User{
    -					{
    -						State: user.UserState_USER_STATE_ACTIVE,
    -						Type: &user.User_Human{
    -							Human: &user.HumanUser{
    -								Profile: &user.HumanProfile{
    -									GivenName:         "Mickey",
    -									FamilyName:        "Mouse",
    -									NickName:          gu.Ptr("Mickey"),
    -									DisplayName:       gu.Ptr("Mickey Mouse"),
    -									PreferredLanguage: gu.Ptr("nl"),
    -									Gender:            user.Gender_GENDER_MALE.Enum(),
    -								},
    -								Email: &user.HumanEmail{
    -									IsVerified: true,
    -								},
    -								Phone: &user.HumanPhone{
    -									IsVerified: true,
    -								},
    -							},
    -						},
    -					},
    -					// this is the admin of the org craated in Instance.CreateOrganization()
    -					nil,
    -				},
    -			},
    -		},
    -		{
    -			name: "list user with wrong org query",
    -			args: args{
    -				IamCTX,
    -				&user.ListUsersRequest{},
    -				func(ctx context.Context, request *user.ListUsersRequest) userAttrs {
    -					orgRespForOrgTests := Instance.CreateOrganization(IamCTX, integration.OrganizationName(), integration.Email())
    -					orgRespForOrgTests2 := Instance.CreateOrganization(IamCTX, integration.OrganizationName(), integration.Email())
    -					createUser(ctx, Instance, orgRespForOrgTests.OrganizationId, false)
    -					request.Queries = []*user.SearchQuery{}
    -					request.Queries = append(request.Queries, OrganizationIdQuery(orgRespForOrgTests2.OrganizationId))
    -					return []userAttr{{}}
    -				},
    -			},
    -			want: &user.ListUsersResponse{
    -				Details: &object.ListDetails{
    -					TotalResult: 0,
    -					Timestamp:   timestamppb.Now(),
    -				},
    -				SortingColumn: 0,
    -				Result: []*user.User{
    -					// this is the admin of the org craated in Instance.CreateOrganization()
    -					nil,
    -				},
    -			},
    -		},
    -		{
    -			name: "when no users matching meta key should return empty list",
    -			args: args{
    -				IamCTX,
    -				&user.ListUsersRequest{},
    -				func(ctx context.Context, request *user.ListUsersRequest) userAttrs {
    -					createUser(ctx, Instance, orgResp.OrganizationId, false)
    -					request.Queries = []*user.SearchQuery{}
    -					request.Queries = append(request.Queries, OrganizationIdQuery(orgResp.OrganizationId))
    -					request.Queries = append(request.Queries, MetadataKeyContainsQuery("some non-existent meta"))
    -
    -					request.SortingColumn = user.UserFieldName_USER_FIELD_NAME_CREATION_DATE
    -					return []userAttr{}
    -				},
    -			},
    -			want: &user.ListUsersResponse{
    -				Details: &object.ListDetails{
    -					TotalResult: 0,
    -					Timestamp:   timestamppb.Now(),
    -				},
    -				SortingColumn: user.UserFieldName_USER_FIELD_NAME_CREATION_DATE,
    -				Result:        []*user.User{},
    -			},
    -		},
    -	}
    -	for _, tc := range tt {
    -		t.Run(tc.name, func(t1 *testing.T) {
    -			infos := tc.args.dep(IamCTX, tc.args.req)
    -
    -			retryDuration, tick := integration.WaitForAndTickWithMaxDuration(tc.args.ctx, time.Minute)
    -			require.EventuallyWithT(t1, func(ttt *assert.CollectT) {
    -				got, err := Client.ListUsers(tc.args.ctx, tc.args.req)
    -				if tc.wantErr {
    -					require.Error(ttt, err)
    -					return
    -				}
    -				require.NoError(ttt, err)
    -
    -				// always only give back dependency infos which are required for the response
    -				require.Len(ttt, tc.want.Result, len(infos))
    -				if assert.Len(ttt, got.Result, len(tc.want.Result)) {
    -					tc.want.Details.TotalResult = got.Details.TotalResult
    -
    -					// fill in userid and username as it is generated
    -					for i := range infos {
    -						if tc.want.Result[i] == nil {
    -							continue
    -						}
    -						tc.want.Result[i].UserId = infos[i].UserID
    -						tc.want.Result[i].Username = infos[i].Username
    -						tc.want.Result[i].PreferredLoginName = infos[i].Username
    -						tc.want.Result[i].LoginNames = []string{infos[i].Username}
    -						if human := tc.want.Result[i].GetHuman(); human != nil {
    -							human.Email.Email = infos[i].Username
    -							human.Phone.Phone = infos[i].Phone
    -							if tc.want.Result[i].GetHuman().GetPasswordChanged() != nil {
    -								human.PasswordChanged = infos[i].Changed
    -							}
    -						}
    -						tc.want.Result[i].Details = infos[i].Details
    -					}
    -					for i := range tc.want.Result {
    -						if tc.want.Result[i] == nil {
    -							continue
    -						}
    -						assert.EqualExportedValues(ttt, got.Result[i], tc.want.Result[i])
    -					}
    -				}
    -				integration.AssertListDetails(ttt, tc.want, got)
    -			}, retryDuration, tick, "timeout waiting for expected user result")
    -		})
    -	}
    -}
    -
    -func TestServer_ListUsers_PermissionsV2(t *testing.T) {
    -	ensureFeaturePermissionV2Enabled(t, InstancePermissionV2)
     	iamOwnerCtx := InstancePermissionV2.WithAuthorizationToken(OrgCTX, integration.UserTypeIAMOwner)
     
     	orgResp := InstancePermissionV2.CreateOrganization(iamOwnerCtx, integration.OrganizationName(), integration.Email())
    @@ -2033,12 +1086,12 @@ func TestServer_ListUsers_PermissionsV2(t *testing.T) {
     			},
     			want: &user.ListUsersResponse{
     				Details: &object.ListDetails{
    -					TotalResult: 0,
    +					TotalResult: 1,
     					Timestamp:   timestamppb.Now(),
     				},
     				SortingColumn: 0,
     				Result: []*user.User{
    -					// this is the admin of the org craated in InstancePermissionV2.CreateOrganization()
    +					// this is the admin of the org created in InstancePermissionV2.CreateOrganization()
     					nil,
     				},
     			},
    @@ -2084,8 +1137,6 @@ func TestServer_ListUsers_PermissionsV2(t *testing.T) {
     				// always only give back dependency infos which are required for the response
     				require.Len(ttt, tc.want.Result, len(infos))
     				if assert.Len(ttt, got.Result, len(tc.want.Result)) {
    -					tc.want.Details.TotalResult = got.Details.TotalResult
    -
     					// fill in userid and username as it is generated
     					for i := range infos {
     						if tc.want.Result[i] == nil {
    @@ -2118,90 +1169,6 @@ func TestServer_ListUsers_PermissionsV2(t *testing.T) {
     }
     
     func TestServer_SystemUsers_ListUsers(t *testing.T) {
    -
    -	org1 := Instance.CreateOrganization(IamCTX, integration.OrganizationName(), integration.Email())
    -	org2 := Instance.CreateOrganization(IamCTX, integration.OrganizationName(), "org2@zitadel.com")
    -	org3 := Instance.CreateOrganization(IamCTX, integration.OrganizationName(), integration.Email())
    -	_ = createUserWithUserName(IamCTX, Instance, "Test_SystemUsers_ListUser1@zitadel.com", org1.OrganizationId, false)
    -	_ = createUserWithUserName(IamCTX, Instance, "Test_SystemUsers_ListUser2@zitadel.com", org2.OrganizationId, false)
    -	_ = createUserWithUserName(IamCTX, Instance, "Test_SystemUsers_ListUser3@zitadel.com", org3.OrganizationId, false)
    -
    -	tests := []struct {
    -		name                       string
    -		ctx                        context.Context
    -		req                        *user.ListUsersRequest
    -		expectedFoundUsernames     []string
    -		checkNumberOfUsersReturned bool
    -	}{
    -		{
    -			name: "list users with neccessary permissions",
    -			ctx:  SystemCTX,
    -			req:  &user.ListUsersRequest{},
    -			// the number of users returned will vary from test run to test run,
    -			// so just check the system user gets back users from different orgs whcih it is not a memeber of
    -			checkNumberOfUsersReturned: false,
    -			expectedFoundUsernames:     []string{"Test_SystemUsers_ListUser1@zitadel.com", "Test_SystemUsers_ListUser2@zitadel.com", "Test_SystemUsers_ListUser3@zitadel.com"},
    -		},
    -		{
    -			name: "list users without neccessary permissions",
    -			ctx:  SystemUserWithNoPermissionsCTX,
    -			req:  &user.ListUsersRequest{},
    -			// check no users returned
    -			checkNumberOfUsersReturned: true,
    -		},
    -		{
    -			name: "list users with neccessary permissions specifying org",
    -			req: &user.ListUsersRequest{
    -				Queries: []*user.SearchQuery{OrganizationIdQuery(org2.OrganizationId)},
    -			},
    -			ctx:                        SystemCTX,
    -			expectedFoundUsernames:     []string{"Test_SystemUsers_ListUser2@zitadel.com", "org2@zitadel.com"},
    -			checkNumberOfUsersReturned: true,
    -		},
    -		{
    -			name: "list users without neccessary permissions specifying org",
    -			req: &user.ListUsersRequest{
    -				Queries: []*user.SearchQuery{OrganizationIdQuery(org2.OrganizationId)},
    -			},
    -			ctx: SystemUserWithNoPermissionsCTX,
    -			// check no users returned
    -			checkNumberOfUsersReturned: true,
    -		},
    -	}
    -
    -	for _, tt := range tests {
    -		t.Run(tt.name, func(t *testing.T) {
    -
    -			retryDuration, tick := integration.WaitForAndTickWithMaxDuration(tt.ctx, 1*time.Minute)
    -			require.EventuallyWithT(t, func(ttt *assert.CollectT) {
    -				got, err := Client.ListUsers(tt.ctx, tt.req)
    -				require.NoError(ttt, err)
    -
    -				if tt.checkNumberOfUsersReturned {
    -					require.Equal(t, len(tt.expectedFoundUsernames), len(got.Result))
    -				}
    -
    -				if tt.expectedFoundUsernames != nil {
    -					for _, user := range got.Result {
    -						for i, username := range tt.expectedFoundUsernames {
    -							if username == user.Username {
    -								tt.expectedFoundUsernames = tt.expectedFoundUsernames[i+1:]
    -								break
    -							}
    -						}
    -						if len(tt.expectedFoundUsernames) == 0 {
    -							return
    -						}
    -					}
    -					require.FailNow(t, "unable to find all users with specified usernames")
    -				}
    -			}, retryDuration, tick, "timeout waiting for expected user result")
    -		})
    -	}
    -}
    -
    -func TestServer_SystemUsers_ListUsers_PermissionsV2(t *testing.T) {
    -	ensureFeaturePermissionV2Enabled(t, InstancePermissionV2)
     	iamOwnerCtx := InstancePermissionV2.WithAuthorizationToken(OrgCTX, integration.UserTypeIAMOwner)
     
     	org1 := InstancePermissionV2.CreateOrganization(iamOwnerCtx, integration.OrganizationName(), integration.Email())
    
  • internal/query/user.go+2 13 modified
    @@ -5,7 +5,6 @@ import (
     	"database/sql"
     	_ "embed"
     	"errors"
    -	"slices"
     	"strings"
     	"time"
     
    @@ -124,14 +123,6 @@ type NotifyUser struct {
     	PasswordSet        bool
     }
     
    -func usersCheckPermission(ctx context.Context, users *Users, permissionCheck domain.PermissionCheck) {
    -	users.Users = slices.DeleteFunc(users.Users,
    -		func(user *User) bool {
    -			return userCheckPermission(ctx, user.ResourceOwner, user.ID, permissionCheck) != nil
    -		},
    -	)
    -}
    -
     func userPermissionCheckV2(ctx context.Context, query sq.SelectBuilder, enabled bool, filters []SearchQuery) sq.SelectBuilder {
     	return userPermissionCheckV2WithCustomColumns(ctx, query, enabled, filters, UserResourceOwnerCol, UserIDCol)
     }
    @@ -619,14 +610,12 @@ func (q *Queries) CountUsers(ctx context.Context, queries *UserSearchQueries) (c
     }
     
     func (q *Queries) SearchUsers(ctx context.Context, queries *UserSearchQueries, permissionCheck domain.PermissionCheck) (*Users, error) {
    -	permissionCheckV2 := PermissionV2(ctx, permissionCheck)
    +	permissionCheckV2 := permissionCheck != nil
     	users, err := q.searchUsers(ctx, queries, permissionCheckV2)
     	if err != nil {
     		return nil, err
     	}
    -	if permissionCheck != nil && !authz.GetFeatures(ctx).PermissionCheckV2 {
    -		usersCheckPermission(ctx, users, permissionCheck)
    -	}
    +
     	return users, nil
     }
     
    
  • internal/query/user_test.go+0 124 modified
    @@ -11,7 +11,6 @@ import (
     
     	sq "github.com/Masterminds/squirrel"
     	"github.com/stretchr/testify/assert"
    -	"github.com/stretchr/testify/require"
     	"golang.org/x/text/language"
     
     	"github.com/zitadel/zitadel/internal/api/authz"
    @@ -20,129 +19,6 @@ import (
     	"github.com/zitadel/zitadel/internal/zerrors"
     )
     
    -func TestUser_usersCheckPermission(t *testing.T) {
    -	type want struct {
    -		users []*User
    -	}
    -	tests := []struct {
    -		name        string
    -		want        want
    -		users       *Users
    -		permissions []string
    -	}{
    -		{
    -			"permissions for all users",
    -			want{
    -				users: []*User{
    -					{ID: "first"}, {ID: "second"}, {ID: "third"},
    -				},
    -			},
    -			&Users{
    -				Users: []*User{
    -					{ID: "first"}, {ID: "second"}, {ID: "third"},
    -				},
    -			},
    -			[]string{"first", "second", "third"},
    -		},
    -		{
    -			"permissions for one user, first",
    -			want{
    -				users: []*User{
    -					{ID: "first"},
    -				},
    -			},
    -			&Users{
    -				Users: []*User{
    -					{ID: "first"}, {ID: "second"}, {ID: "third"},
    -				},
    -			},
    -			[]string{"first"},
    -		},
    -		{
    -			"permissions for one user, second",
    -			want{
    -				users: []*User{
    -					{ID: "second"},
    -				},
    -			},
    -			&Users{
    -				Users: []*User{
    -					{ID: "first"}, {ID: "second"}, {ID: "third"},
    -				},
    -			},
    -			[]string{"second"},
    -		},
    -		{
    -			"permissions for one user, third",
    -			want{
    -				users: []*User{
    -					{ID: "third"},
    -				},
    -			},
    -			&Users{
    -				Users: []*User{
    -					{ID: "first"}, {ID: "second"}, {ID: "third"},
    -				},
    -			},
    -			[]string{"third"},
    -		},
    -		{
    -			"permissions for two users, first",
    -			want{
    -				users: []*User{
    -					{ID: "first"}, {ID: "third"},
    -				},
    -			},
    -			&Users{
    -				Users: []*User{
    -					{ID: "first"}, {ID: "second"}, {ID: "third"},
    -				},
    -			},
    -			[]string{"first", "third"},
    -		},
    -		{
    -			"permissions for two users, second",
    -			want{
    -				users: []*User{
    -					{ID: "second"}, {ID: "third"},
    -				},
    -			},
    -			&Users{
    -				Users: []*User{
    -					{ID: "first"}, {ID: "second"}, {ID: "third"},
    -				},
    -			},
    -			[]string{"second", "third"},
    -		},
    -		{
    -			"no permissions",
    -			want{
    -				users: []*User{},
    -			},
    -			&Users{
    -				Users: []*User{
    -					{ID: "first"}, {ID: "second"}, {ID: "third"},
    -				},
    -			},
    -			[]string{},
    -		},
    -	}
    -	for _, tt := range tests {
    -		t.Run(tt.name, func(t *testing.T) {
    -			checkPermission := func(ctx context.Context, permission, orgID, resourceID string) (err error) {
    -				for _, perm := range tt.permissions {
    -					if resourceID == perm {
    -						return nil
    -					}
    -				}
    -				return errors.New("failed")
    -			}
    -			usersCheckPermission(context.Background(), tt.users, checkPermission)
    -			require.Equal(t, tt.want.users, tt.users.Users)
    -		})
    -	}
    -}
    -
     func TestUser_userCheckPermission(t *testing.T) {
     	type args struct {
     		ctxData       string
    

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

4

News mentions

0

No linked articles in our index yet.