From d9fc183e393d2336edb2ae7faf700905a59dd58c Mon Sep 17 00:00:00 2001 From: Stephanie Hingtgen Date: Tue, 9 Dec 2025 14:00:01 -0700 Subject: [PATCH] Folders: Prevent circular dependencies on apis level (#115040) --- pkg/registry/apis/folders/validate.go | 11 +++++++++++ pkg/registry/apis/folders/validate_test.go | 21 +++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/pkg/registry/apis/folders/validate.go b/pkg/registry/apis/folders/validate.go index 4f8ccd2250d..739c81951f8 100644 --- a/pkg/registry/apis/folders/validate.go +++ b/pkg/registry/apis/folders/validate.go @@ -53,11 +53,22 @@ func validateOnCreate(ctx context.Context, f *folders.Folder, getter parentsGett return folder.ErrFolderCannotBeParentOfItself } + // note: `parents` will include itself as the last item parents, err := getter(ctx, f) if err != nil { return fmt.Errorf("unable to create folder inside parent: %w", err) } + for i, parent := range parents.Items { + // skip the last item, which is itself + if i == len(parents.Items)-1 { + continue + } + if parent.Name == f.Name { + return folder.ErrCircularReference.Errorf("circular reference detected") + } + } + // Can not create a folder that will be too deep. // We need to add +1 as we also have the root folder as part of the parents. if len(parents.Items) > maxDepth+1 { diff --git a/pkg/registry/apis/folders/validate_test.go b/pkg/registry/apis/folders/validate_test.go index c4bf07bc71c..ac21ea4ead0 100644 --- a/pkg/registry/apis/folders/validate_test.go +++ b/pkg/registry/apis/folders/validate_test.go @@ -127,6 +127,27 @@ func TestValidateCreate(t *testing.T) { }, maxDepth: folder.MaxNestedFolderDepth, }, + { + name: "cannot create a circular reference", + folder: &folders.Folder{ + ObjectMeta: metav1.ObjectMeta{ + Name: "3", + Annotations: map[string]string{"grafana.app/folder": "2"}, + }, + Spec: folders.FolderSpec{ + Title: "some title", + }, + }, + expectedErr: "circular reference detected", + getter: &folders.FolderInfoList{ + Items: []folders.FolderInfo{ + {Name: "2", Parent: "1"}, + {Name: "1", Parent: "3"}, + {Name: "3", Parent: folder.GeneralFolderUID}, + {Name: folder.GeneralFolderUID}, + }, + }, + }, } for _, tt := range tests {