diff --git a/src/controller/tag/controller.go b/src/controller/tag/controller.go index 7351ebbee..1d59302c6 100644 --- a/src/controller/tag/controller.go +++ b/src/controller/tag/controller.go @@ -16,6 +16,7 @@ package tag import ( "context" + "regexp" "time" "github.com/goharbor/harbor/src/common/utils" @@ -35,7 +36,8 @@ import ( var ( // Ctl is a global tag controller instance - Ctl = NewController() + Ctl = NewController() + tagNamePattern = regexp.MustCompile(`^[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}$`) ) // Controller manages the tags @@ -160,9 +162,18 @@ func (c *controller) Get(ctx context.Context, id int64, option *Option) (tag *Ta // Create ... func (c *controller) Create(ctx context.Context, tag *Tag) (id int64, err error) { + if !isValidTag(tag.Name) { + return 0, errors.BadRequestError(errors.Errorf("invalid tag name: %s", tag.Name)) + } return c.tagMgr.Create(ctx, &(tag.Tag)) } +func isValidTag(name string) bool { + // tag name should follow OCI spec + // https://github.com/opencontainers/distribution-spec/blob/main/spec.md#pull + return tagNamePattern.MatchString(name) +} + // Update ... func (c *controller) Update(ctx context.Context, tag *Tag, props ...string) (err error) { return c.tagMgr.Update(ctx, &tag.Tag, props...) diff --git a/src/controller/tag/controller_test.go b/src/controller/tag/controller_test.go index fafddda8c..95d31bdd8 100644 --- a/src/controller/tag/controller_test.go +++ b/src/controller/tag/controller_test.go @@ -236,3 +236,29 @@ func (c *controllerTestSuite) TestAssembleTag() { func TestControllerTestSuite(t *testing.T) { suite.Run(t, &controllerTestSuite{}) } + +func Test_isValidTag(t *testing.T) { + type args struct { + name string + } + tests := []struct { + name string + args args + want bool + }{ + {"normal", args{`latest`}, true}, + {"invalid_char", args{`latest&delete`}, false}, + {"invalid_start", args{`-abc`}, false}, + {"invalid_start_&", args{`&asdf`}, false}, + {"valid_start", args{`_abc`}, true}, + {"pure_number", args{`123456`}, true}, + {"empty", args{` `}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := isValidTag(tt.args.name); got != tt.want { + t.Errorf("isValidTag() = %v, want %v", got, tt.want) + } + }) + } +}