fix(api): permission checks for some management API endpoints

# Which Problems Are Solved

Some endpoints in the management API verified the user's permission but did not honor the organization the permission was granted in the internal process. This led to cross-tenant information disclosure.
The following endpoints were affected:

* `GetProjectByID`
* `GetGrantedProjectByID`
* `GetProjectGrantByID`
* `GetAppByID`
* `ListApps`
* `ListHumanAuthFactors`
* `ListHumanPasswordless`

# How the Problems Are Solved

Correctly treat the requested context (organization) where the permission was granted and use that to query the resource.

# Additional Changes

None

# Additional Context

- requires backport to v4.x and v3.x

(cherry picked from commit ab51fd9563)
(cherry picked from commit da227a458a)

# Conflicts:
#	internal/query/app.go
This commit is contained in:
Livio Spring committed 2026-03-11 08:45:13 +01:00
1 parent 61baf06b01
commit e891eb84af
6 files changed
+34 -3

No files matched your search

+7
View File
@@ -11,6 +11,7 @@ import (
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/query"
"github.com/zitadel/zitadel/internal/repository/project"
"github.com/zitadel/zitadel/internal/zerrors"
mgmt_pb "github.com/zitadel/zitadel/pkg/grpc/management"
)
@@ -19,6 +20,9 @@ func (s *Server) GetProjectByID(ctx context.Context, req *mgmt_pb.GetProjectByID
if err != nil {
return nil, err
}
if project.ResourceOwner != authz.GetCtxData(ctx).OrgID {
return nil, zerrors.ThrowNotFound(nil, "MANAG-SFf2a", "Errors.Project.NotFound")
}
return &mgmt_pb.GetProjectByIDResponse{
Project: project_grpc.ProjectViewToPb(project),
}, nil
@@ -29,6 +33,9 @@ func (s *Server) GetGrantedProjectByID(ctx context.Context, req *mgmt_pb.GetGran
if err != nil {
return nil, err
}
if !(grant.ResourceOwner == authz.GetCtxData(ctx).OrgID || grant.GrantedOrgID == authz.GetCtxData(ctx).OrgID) {
return nil, zerrors.ThrowNotFound(nil, "MANAG-drt2a", "Errors.ProjectGrant.NotFound")
}
return &mgmt_pb.GetGrantedProjectByIDResponse{
GrantedProject: project_grpc.GrantedProjectViewToPb(grant),
}, nil
@@ -11,6 +11,7 @@ import (
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/query"
"github.com/zitadel/zitadel/internal/repository/project"
"github.com/zitadel/zitadel/internal/zerrors"
mgmt_pb "github.com/zitadel/zitadel/pkg/grpc/management"
)
@@ -19,13 +20,16 @@ func (s *Server) GetAppByID(ctx context.Context, req *mgmt_pb.GetAppByIDRequest)
if err != nil {
return nil, err
}
if app.ResourceOwner != authz.GetCtxData(ctx).OrgID {
return nil, zerrors.ThrowNotFound(nil, "MANAG-SFf2a", "Errors.Project.App.NotFound")
}
return &mgmt_pb.GetAppByIDResponse{
App: project_grpc.AppToPb(app),
}, nil
}
func (s *Server) ListApps(ctx context.Context, req *mgmt_pb.ListAppsRequest) (*mgmt_pb.ListAppsResponse, error) {
queries, err := ListAppsRequestToModel(req)
queries, err := ListAppsRequestToModel(ctx, req)
if err != nil {
return nil, err
}
@@ -14,7 +14,7 @@ import (
mgmt_pb "github.com/zitadel/zitadel/pkg/grpc/management"
)
func ListAppsRequestToModel(req *mgmt_pb.ListAppsRequest) (*query.AppSearchQueries, error) {
func ListAppsRequestToModel(ctx context.Context, req *mgmt_pb.ListAppsRequest) (*query.AppSearchQueries, error) {
offset, limit, asc := object.ListQueryToModel(req.Query)
queries, err := app_grpc.AppQueriesToModel(req.Queries)
if err != nil {
@@ -24,7 +24,11 @@ func ListAppsRequestToModel(req *mgmt_pb.ListAppsRequest) (*query.AppSearchQueri
if err != nil {
return nil, err
}
queries = append(queries, projectQuery)
resourceOwner, err := query.NewAppResourceOwnerSearchQuery(authz.GetCtxData(ctx).OrgID)
if err != nil {
return nil, err
}
queries = append(queries, projectQuery, resourceOwner)
return &query.AppSearchQueries{
SearchRequest: query.SearchRequest{
Offset: offset,
@@ -9,6 +9,7 @@ import (
object_grpc "github.com/zitadel/zitadel/internal/api/grpc/object"
proj_grpc "github.com/zitadel/zitadel/internal/api/grpc/project"
"github.com/zitadel/zitadel/internal/query"
"github.com/zitadel/zitadel/internal/zerrors"
mgmt_pb "github.com/zitadel/zitadel/pkg/grpc/management"
)
@@ -17,6 +18,9 @@ func (s *Server) GetProjectGrantByID(ctx context.Context, req *mgmt_pb.GetProjec
if err != nil {
return nil, err
}
if !(grant.ResourceOwner == authz.GetCtxData(ctx).OrgID || grant.GrantedOrgID == authz.GetCtxData(ctx).OrgID) {
return nil, zerrors.ThrowNotFound(nil, "MANAG-d3g31", "Errors.ProjectGrant.NotFound")
}
return &mgmt_pb.GetProjectGrantByIDResponse{
ProjectGrant: proj_grpc.GrantedProjectViewToPb(grant),
}, nil
+8
View File
@@ -608,6 +608,10 @@ func (s *Server) ListHumanAuthFactors(ctx context.Context, req *mgmt_pb.ListHuma
if err != nil {
return nil, err
}
err = query.AppendResourceOwnerQuery(authz.GetCtxData(ctx).OrgID)
if err != nil {
return nil, err
}
authMethods, err := s.query.SearchUserAuthMethods(ctx, query, nil)
if err != nil {
return nil, err
@@ -671,6 +675,10 @@ func (s *Server) ListHumanPasswordless(ctx context.Context, req *mgmt_pb.ListHum
if err != nil {
return nil, err
}
err = query.AppendResourceOwnerQuery(authz.GetCtxData(ctx).OrgID)
if err != nil {
return nil, err
}
authMethods, err := s.query.SearchUserAuthMethods(ctx, query, nil)
if err != nil {
return nil, err
+4
View File
@@ -632,6 +632,10 @@ func NewAppProjectIDSearchQuery(id string) (SearchQuery, error) {
return NewTextQuery(AppColumnProjectID, id, TextEquals)
}
func NewAppResourceOwnerSearchQuery(resourceOwner string) (SearchQuery, error) {
return NewTextQuery(AppColumnResourceOwner, resourceOwner, TextEquals)
}
func prepareAppQuery(activeOnly bool) (sq.SelectBuilder, func(*sql.Row) (*App, error)) {
query := sq.Select(
AppColumnID.identifier(),