diff --git a/src/common/rbac/const.go b/src/common/rbac/const.go
index 6b2ff85f2d6dad90fb80ba49c901cb9b31221df5..0e96d4cd8760d04226448ec2306b39e0429d3357 100755
--- a/src/common/rbac/const.go
+++ b/src/common/rbac/const.go
@@ -28,8 +28,7 @@ const (
 	ActionDelete = Action("delete")
 	ActionList   = Action("list")
 
-	ActionOperate     = Action("operate")
-	ActionScannerPull = Action("scanner-pull") // for robot account created by scanner to pull image, bypass the policy check
+	ActionOperate = Action("operate")
 )
 
 // const resource variables
diff --git a/src/common/security/robot/robot.go b/src/common/security/robot/robot.go
index d01dc1055e6fcb3ca86d350503c7a125ebd1bf6c..c900f672d652a38d23988f3d7236b49f4cb62af2 100644
--- a/src/common/security/robot/robot.go
+++ b/src/common/security/robot/robot.go
@@ -47,22 +47,16 @@ func filterPolicies(namespace rbac.Namespace, policies []*rbac.Policy) []*rbac.P
 		return results
 	}
 
-	mp := getAllPolicies(namespace)
+	mp := map[string]bool{}
+	for _, policy := range project.GetAllPolicies(namespace) {
+		mp[policy.String()] = true
+	}
+
 	for _, policy := range policies {
 		if mp[policy.String()] {
 			results = append(results, policy)
 		}
 	}
-	return results
-}
 
-// getAllPolicies gets all of supported policies supported in project and external policies supported for robot account
-func getAllPolicies(namespace rbac.Namespace) map[string]bool {
-	mp := map[string]bool{}
-	for _, policy := range project.GetAllPolicies(namespace) {
-		mp[policy.String()] = true
-	}
-	scannerPull := &rbac.Policy{Resource: namespace.Resource(rbac.ResourceRepository), Action: rbac.ActionScannerPull}
-	mp[scannerPull.String()] = true
-	return mp
+	return results
 }
diff --git a/src/common/security/robot/robot_test.go b/src/common/security/robot/robot_test.go
index 16b57735b7489bb70314412dfaef41c9fa143a6d..617c4c3fac25df67fd6262f6fca386730fc8808f 100644
--- a/src/common/security/robot/robot_test.go
+++ b/src/common/security/robot/robot_test.go
@@ -44,11 +44,10 @@ func TestGetPolicies(t *testing.T) {
 func TestNewRobot(t *testing.T) {
 	policies := []*rbac.Policy{
 		{Resource: "/project/1/repository", Action: "pull"},
-		{Resource: "/project/1/repository", Action: "scanner-pull"},
 		{Resource: "/project/library/repository", Action: "pull"},
 		{Resource: "/project/library/repository", Action: "push"},
 	}
 
 	robot := NewRobot("test", rbac.NewProjectNamespace(1, false), policies)
-	assert.Len(t, robot.GetPolicies(), 2)
+	assert.Len(t, robot.GetPolicies(), 1)
 }
diff --git a/src/pkg/token/claims/robot/robot.go b/src/common/token/claims.go
similarity index 82%
rename from src/pkg/token/claims/robot/robot.go
rename to src/common/token/claims.go
index 44ffa2633112f543ef92d183e7ef855048fb0be1..bec9f5f2f7f15f4ae2ae3126551baf3876aa56d5 100644
--- a/src/pkg/token/claims/robot/robot.go
+++ b/src/common/token/claims.go
@@ -1,4 +1,4 @@
-package robot
+package token
 
 import (
 	"errors"
@@ -6,8 +6,8 @@ import (
 	"github.com/goharbor/harbor/src/common/rbac"
 )
 
-// Claim implements the interface of jwt.Claims
-type Claim struct {
+// RobotClaims implements the interface of jwt.Claims
+type RobotClaims struct {
 	jwt.StandardClaims
 	TokenID   int64          `json:"id"`
 	ProjectID int64          `json:"pid"`
@@ -15,7 +15,7 @@ type Claim struct {
 }
 
 // Valid valid the claims "tokenID, projectID and access".
-func (rc Claim) Valid() error {
+func (rc RobotClaims) Valid() error {
 	if rc.TokenID < 0 {
 		return errors.New("Token id must an valid INT")
 	}
diff --git a/src/pkg/token/claims/robot/robot_test.go b/src/common/token/claims_test.go
similarity index 90%
rename from src/pkg/token/claims/robot/robot_test.go
rename to src/common/token/claims_test.go
index 054f4b4a84c3da97a1d6437d0e9c717f73934a56..dc25a120a1f60eb8eacc69737523a3cc016abddb 100644
--- a/src/pkg/token/claims/robot/robot_test.go
+++ b/src/common/token/claims_test.go
@@ -1,4 +1,4 @@
-package robot
+package token
 
 import (
 	"github.com/goharbor/harbor/src/common/rbac"
@@ -15,7 +15,7 @@ func TestValid(t *testing.T) {
 	policies := []*rbac.Policy{}
 	policies = append(policies, rbacPolicy)
 
-	rClaims := &Claim{
+	rClaims := &RobotClaims{
 		TokenID:   1,
 		ProjectID: 2,
 		Access:    policies,
@@ -32,7 +32,7 @@ func TestUnValidTokenID(t *testing.T) {
 	policies := []*rbac.Policy{}
 	policies = append(policies, rbacPolicy)
 
-	rClaims := &Claim{
+	rClaims := &RobotClaims{
 		TokenID:   -1,
 		ProjectID: 2,
 		Access:    policies,
@@ -49,7 +49,7 @@ func TestUnValidProjectID(t *testing.T) {
 	policies := []*rbac.Policy{}
 	policies = append(policies, rbacPolicy)
 
-	rClaims := &Claim{
+	rClaims := &RobotClaims{
 		TokenID:   1,
 		ProjectID: -2,
 		Access:    policies,
@@ -59,7 +59,7 @@ func TestUnValidProjectID(t *testing.T) {
 
 func TestUnValidPolicy(t *testing.T) {
 
-	rClaims := &Claim{
+	rClaims := &RobotClaims{
 		TokenID:   1,
 		ProjectID: 2,
 		Access:    nil,
diff --git a/src/common/token/htoken.go b/src/common/token/htoken.go
new file mode 100644
index 0000000000000000000000000000000000000000..897c504672a82021f5ce262f665855fcb8eb0af2
--- /dev/null
+++ b/src/common/token/htoken.go
@@ -0,0 +1,87 @@
+package token
+
+import (
+	"crypto/ecdsa"
+	"crypto/rsa"
+	"errors"
+	"fmt"
+	"github.com/dgrijalva/jwt-go"
+	"github.com/goharbor/harbor/src/common/rbac"
+	"github.com/goharbor/harbor/src/common/utils/log"
+	"time"
+)
+
+// HToken htoken is a jwt token for harbor robot account,
+// which contains the robot ID, project ID and the access permission for the project.
+// It used for authn/authz for robot account in Harbor.
+type HToken struct {
+	jwt.Token
+}
+
+// New ...
+func New(tokenID, projectID, expiresAt int64, access []*rbac.Policy) (*HToken, error) {
+	rClaims := &RobotClaims{
+		TokenID:   tokenID,
+		ProjectID: projectID,
+		Access:    access,
+		StandardClaims: jwt.StandardClaims{
+			IssuedAt:  time.Now().UTC().Unix(),
+			ExpiresAt: expiresAt,
+			Issuer:    DefaultOptions().Issuer,
+		},
+	}
+	err := rClaims.Valid()
+	if err != nil {
+		return nil, err
+	}
+	return &HToken{
+		Token: *jwt.NewWithClaims(DefaultOptions().SignMethod, rClaims),
+	}, nil
+}
+
+// Raw get the Raw string of token
+func (htk *HToken) Raw() (string, error) {
+	key, err := DefaultOptions().GetKey()
+	if err != nil {
+		return "", nil
+	}
+	raw, err := htk.Token.SignedString(key)
+	if err != nil {
+		log.Debugf(fmt.Sprintf("failed to issue token %v", err))
+		return "", err
+	}
+	return raw, err
+}
+
+// ParseWithClaims ...
+func ParseWithClaims(rawToken string, claims jwt.Claims) (*HToken, error) {
+	key, err := DefaultOptions().GetKey()
+	if err != nil {
+		return nil, err
+	}
+	token, err := jwt.ParseWithClaims(rawToken, claims, func(token *jwt.Token) (interface{}, error) {
+		if token.Method.Alg() != DefaultOptions().SignMethod.Alg() {
+			return nil, errors.New("invalid signing method")
+		}
+		switch k := key.(type) {
+		case *rsa.PrivateKey:
+			return &k.PublicKey, nil
+		case *ecdsa.PrivateKey:
+			return &k.PublicKey, nil
+		default:
+			return key, nil
+		}
+	})
+	if err != nil {
+		log.Errorf(fmt.Sprintf("parse token error, %v", err))
+		return nil, err
+	}
+
+	if !token.Valid {
+		log.Errorf(fmt.Sprintf("invalid jwt token, %v", token))
+		return nil, errors.New("invalid jwt token")
+	}
+	return &HToken{
+		Token: *token,
+	}, nil
+}
diff --git a/src/pkg/token/token_test.go b/src/common/token/htoken_test.go
similarity index 79%
rename from src/pkg/token/token_test.go
rename to src/common/token/htoken_test.go
index eab75a4743be660ff2e04b751abab0cee3e37e04..38e187ef74967ab1dd0776678ba86bfef69dd891 100644
--- a/src/pkg/token/token_test.go
+++ b/src/common/token/htoken_test.go
@@ -5,10 +5,8 @@ import (
 	"testing"
 	"time"
 
-	"github.com/dgrijalva/jwt-go"
 	"github.com/goharbor/harbor/src/common/rbac"
 	"github.com/goharbor/harbor/src/core/config"
-	robot_claim "github.com/goharbor/harbor/src/pkg/token/claims/robot"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -35,15 +33,7 @@ func TestNew(t *testing.T) {
 	projectID := int64(321)
 	tokenExpiration := time.Duration(10) * 24 * time.Hour
 	expiresAt := time.Now().UTC().Add(tokenExpiration).Unix()
-	robot := robot_claim.Claim{
-		TokenID:   tokenID,
-		ProjectID: projectID,
-		Access:    policies,
-		StandardClaims: jwt.StandardClaims{
-			ExpiresAt: expiresAt,
-		},
-	}
-	token, err := New(DefaultTokenOptions(), robot)
+	token, err := New(tokenID, projectID, expiresAt, policies)
 
 	assert.Nil(t, err)
 	assert.Equal(t, token.Header["alg"], "RS256")
@@ -64,15 +54,7 @@ func TestRaw(t *testing.T) {
 
 	tokenExpiration := time.Duration(10) * 24 * time.Hour
 	expiresAt := time.Now().UTC().Add(tokenExpiration).Unix()
-	robot := robot_claim.Claim{
-		TokenID:   tokenID,
-		ProjectID: projectID,
-		Access:    policies,
-		StandardClaims: jwt.StandardClaims{
-			ExpiresAt: expiresAt,
-		},
-	}
-	token, err := New(DefaultTokenOptions(), robot)
+	token, err := New(tokenID, projectID, expiresAt, policies)
 	assert.Nil(t, err)
 
 	rawTk, err := token.Raw()
@@ -82,8 +64,8 @@ func TestRaw(t *testing.T) {
 
 func TestParseWithClaims(t *testing.T) {
 	rawTk := "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJJRCI6MTIzLCJQcm9qZWN0SUQiOjAsIkFjY2VzcyI6W3siUmVzb3VyY2UiOiIvcHJvamVjdC9saWJyYXkvcmVwb3NpdG9yeSIsIkFjdGlvbiI6InB1bGwiLCJFZmZlY3QiOiIifV0sIlN0YW5kYXJkQ2xhaW1zIjp7ImV4cCI6MTU0ODE0MDIyOSwiaXNzIjoiaGFyYm9yLXRva2VuLWlzc3VlciJ9fQ.Jc3qSKN4SJVUzAvBvemVpRcSOZaHlu0Avqms04qzPm4ru9-r9IRIl3mnSkI6m9XkzLUeJ7Kiwyw63ghngnVKw_PupeclOGC6s3TK5Cfmo4h-lflecXjZWwyy-dtH_e7Us_ItS-R3nXDJtzSLEpsGHCcAj-1X2s93RB2qD8LNSylvYeDezVkTzqRzzfawPJheKKh9JTrz-3eUxCwQard9-xjlwvfUYULoHTn9npNAUq4-jqhipW4uE8HL-ym33AGF57la8U0RO11hmDM5K8-PiYknbqJ_oONeS3HBNym2pEFeGjtTv2co213wl4T5lemlg4SGolMBuJ03L7_beVZ0o-MKTkKDqDwJalb6_PM-7u3RbxC9IzJMiwZKIPnD3FvV10iPxUUQHaH8Jz5UZ2pFIhi_8BNnlBfT0JOPFVYATtLjHMczZelj2YvAeR1UHBzq3E0jPpjjwlqIFgaHCaN_KMwEvadTo_Fi2sEH4pNGP7M3yehU_72oLJQgF4paJarsmEoij6ZtPs6xekBz1fccVitq_8WNIz9aeCUdkUBRwI5QKw1RdW4ua-w74ld5MZStWJA8veyoLkEb_Q9eq2oAj5KWFjJbW5-ltiIfM8gxKflsrkWAidYGcEIYcuXr7UdqEKXxtPiWM0xb3B91ovYvO5402bn3f9-UGtlcestxNHA"
-	rClaims := &robot_claim.Claim{}
-	_, _ = Parse(DefaultTokenOptions(), rawTk, rClaims)
+	rClaims := &RobotClaims{}
+	_, _ = ParseWithClaims(rawTk, rClaims)
 	assert.Equal(t, int64(123), rClaims.TokenID)
 	assert.Equal(t, int64(0), rClaims.ProjectID)
 	assert.Equal(t, "/project/libray/repository", rClaims.Access[0].Resource.String())
diff --git a/src/pkg/token/options.go b/src/common/token/options.go
similarity index 83%
rename from src/pkg/token/options.go
rename to src/common/token/options.go
index e1d96d47642942f30a573349b85446cfc9001160..747d7435d57694cd95bcbd07c3f4c7d8717f797e 100644
--- a/src/pkg/token/options.go
+++ b/src/common/token/options.go
@@ -11,9 +11,9 @@ import (
 )
 
 const (
-	defaultTTL          = 60 * time.Minute
-	defaultIssuer       = "harbor-token-defaultIssuer"
-	defaultSignedMethod = "RS256"
+	ttl          = 60 * time.Minute
+	issuer       = "harbor-token-issuer"
+	signedMethod = "RS256"
 )
 
 // Options ...
@@ -25,6 +25,23 @@ type Options struct {
 	Issuer     string
 }
 
+// DefaultOptions ...
+func DefaultOptions() *Options {
+	privateKeyFile := config.TokenPrivateKeyPath()
+	privateKey, err := ioutil.ReadFile(privateKeyFile)
+	if err != nil {
+		log.Errorf(fmt.Sprintf("failed to read private key %v", err))
+		return nil
+	}
+	opt := &Options{
+		SignMethod: jwt.GetSigningMethod(signedMethod),
+		PrivateKey: privateKey,
+		Issuer:     issuer,
+		TTL:        ttl,
+	}
+	return opt
+}
+
 // GetKey ...
 func (o *Options) GetKey() (interface{}, error) {
 	var err error
@@ -59,20 +76,3 @@ func (o *Options) GetKey() (interface{}, error) {
 		return nil, fmt.Errorf(fmt.Sprintf("unsupported sign method, %s", o.SignMethod))
 	}
 }
-
-// DefaultTokenOptions ...
-func DefaultTokenOptions() *Options {
-	privateKeyFile := config.TokenPrivateKeyPath()
-	privateKey, err := ioutil.ReadFile(privateKeyFile)
-	if err != nil {
-		log.Errorf(fmt.Sprintf("failed to read private key %v", err))
-		return nil
-	}
-	opt := &Options{
-		SignMethod: jwt.GetSigningMethod(defaultSignedMethod),
-		PrivateKey: privateKey,
-		Issuer:     defaultIssuer,
-		TTL:        defaultTTL,
-	}
-	return opt
-}
diff --git a/src/pkg/token/option_test.go b/src/common/token/options_test.go
similarity index 74%
rename from src/pkg/token/option_test.go
rename to src/common/token/options_test.go
index 421bf0cbbfb677532e39625875b4856d1503d709..5f64fb3802b9766ce3cb7c6f4b8df56cbdd444fc 100644
--- a/src/pkg/token/option_test.go
+++ b/src/common/token/options_test.go
@@ -8,15 +8,15 @@ import (
 )
 
 func TestNewOptions(t *testing.T) {
-	defaultOpt := DefaultTokenOptions()
+	defaultOpt := DefaultOptions()
 	assert.NotNil(t, defaultOpt)
 	assert.Equal(t, defaultOpt.SignMethod, jwt.GetSigningMethod("RS256"))
-	assert.Equal(t, defaultOpt.Issuer, "harbor-token-defaultIssuer")
+	assert.Equal(t, defaultOpt.Issuer, "harbor-token-issuer")
 	assert.Equal(t, defaultOpt.TTL, 60*time.Minute)
 }
 
 func TestGetKey(t *testing.T) {
-	defaultOpt := DefaultTokenOptions()
+	defaultOpt := DefaultOptions()
 	key, err := defaultOpt.GetKey()
 	assert.Nil(t, err)
 	assert.NotNil(t, key)
diff --git a/src/common/utils/oidc/helper.go b/src/common/utils/oidc/helper.go
index 7cbec4aa96a932f08d0a421317f4b734f746822c..7de72a8b87405fba8304bb6f908e9f93427800c2 100644
--- a/src/common/utils/oidc/helper.go
+++ b/src/common/utils/oidc/helper.go
@@ -208,7 +208,7 @@ func RefreshToken(ctx context.Context, token *Token) (*Token, error) {
 	return &Token{Token: *t, IDToken: it}, nil
 }
 
-// GroupsFromToken returns the list of group name in the token, the claims of the group list is set in OIDCSetting.
+// GroupsFromToken returns the list of group name in the token, the claim of the group list is set in OIDCSetting.
 // It's designed not to return errors, in case of unexpected situation it will log and return empty list.
 func GroupsFromToken(token *gooidc.IDToken) []string {
 	if token == nil {
@@ -217,7 +217,7 @@ func GroupsFromToken(token *gooidc.IDToken) []string {
 	}
 	setting := provider.setting.Load().(models.OIDCSetting)
 	if len(setting.GroupsClaim) == 0 {
-		log.Warning("Group claims is not set in OIDC setting returning empty group list.")
+		log.Warning("Group claim is not set in OIDC setting returning empty group list.")
 		return []string{}
 	}
 	var c map[string]interface{}
@@ -233,7 +233,7 @@ func groupsFromClaim(claimMap map[string]interface{}, k string) []string {
 	var res []string
 	g, ok := claimMap[k].([]interface{})
 	if !ok {
-		log.Warningf("Unable to get groups from claims, claims: %+v, groups claims key: %s", claimMap, k)
+		log.Warningf("Unable to get groups from claims, claims: %+v, groups claim key: %s", claimMap, k)
 		return res
 	}
 	for _, e := range g {
diff --git a/src/core/filter/security.go b/src/core/filter/security.go
index 891fcb5e465c4fceb03f7c186a7d15442eeb2062..b8bbbac5b08d933bb14ce99e7acb292292c1d2fe 100644
--- a/src/core/filter/security.go
+++ b/src/core/filter/security.go
@@ -34,6 +34,7 @@ import (
 	"github.com/goharbor/harbor/src/common/security/local"
 	robotCtx "github.com/goharbor/harbor/src/common/security/robot"
 	"github.com/goharbor/harbor/src/common/security/secret"
+	"github.com/goharbor/harbor/src/common/token"
 	"github.com/goharbor/harbor/src/common/utils/log"
 	"github.com/goharbor/harbor/src/core/auth"
 	"github.com/goharbor/harbor/src/core/config"
@@ -43,8 +44,6 @@ import (
 
 	"github.com/goharbor/harbor/src/pkg/authproxy"
 	"github.com/goharbor/harbor/src/pkg/robot"
-	pkg_token "github.com/goharbor/harbor/src/pkg/token"
-	robot_claim "github.com/goharbor/harbor/src/pkg/token/claims/robot"
 )
 
 // ContextValueKey for content value
@@ -189,16 +188,15 @@ func (r *robotAuthReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
 	if !strings.HasPrefix(robotName, common.RobotPrefix) {
 		return false
 	}
-	rClaims := &robot_claim.Claim{}
-	opt := pkg_token.DefaultTokenOptions()
-	rtk, err := pkg_token.Parse(opt, robotTk, rClaims)
+	rClaims := &token.RobotClaims{}
+	htk, err := token.ParseWithClaims(robotTk, rClaims)
 	if err != nil {
 		log.Errorf("failed to decrypt robot token, %v", err)
 		return false
 	}
 	// Do authn for robot account, as Harbor only stores the token ID, just validate the ID and disable.
 	ctr := robot.RobotCtr
-	robot, err := ctr.GetRobotAccount(rtk.Claims.(*robot_claim.Claim).TokenID)
+	robot, err := ctr.GetRobotAccount(htk.Claims.(*token.RobotClaims).TokenID)
 	if err != nil {
 		log.Errorf("failed to get robot %s: %v", robotName, err)
 		return false
@@ -217,7 +215,7 @@ func (r *robotAuthReqCtxModifier) Modify(ctx *beegoctx.Context) bool {
 	}
 	log.Debug("creating robot account security context...")
 	pm := config.GlobalProjectMgr
-	securCtx := robotCtx.NewSecurityContext(robot, pm, rtk.Claims.(*robot_claim.Claim).Access)
+	securCtx := robotCtx.NewSecurityContext(robot, pm, htk.Claims.(*token.RobotClaims).Access)
 	setSecurCtxAndPM(ctx.Request, securCtx, pm)
 	return true
 }
diff --git a/src/core/middlewares/chain.go b/src/core/middlewares/chain.go
index 630a8e8d45549c0314a5b2f7edb316723109afde..79617c73568972fd3f2c50a361810fd6cdbf0a4f 100644
--- a/src/core/middlewares/chain.go
+++ b/src/core/middlewares/chain.go
@@ -25,7 +25,6 @@ import (
 	"github.com/goharbor/harbor/src/core/middlewares/listrepo"
 	"github.com/goharbor/harbor/src/core/middlewares/multiplmanifest"
 	"github.com/goharbor/harbor/src/core/middlewares/readonly"
-	"github.com/goharbor/harbor/src/core/middlewares/regtoken"
 	"github.com/goharbor/harbor/src/core/middlewares/sizequota"
 	"github.com/goharbor/harbor/src/core/middlewares/url"
 	"github.com/goharbor/harbor/src/core/middlewares/vulnerable"
@@ -73,7 +72,6 @@ func (b *DefaultCreator) geMiddleware(mName string) alice.Constructor {
 		SIZEQUOTA:        func(next http.Handler) http.Handler { return sizequota.New(next) },
 		COUNTQUOTA:       func(next http.Handler) http.Handler { return countquota.New(next) },
 		IMMUTABLE:        func(next http.Handler) http.Handler { return immutable.New(next) },
-		REGTOKEN:         func(next http.Handler) http.Handler { return regtoken.New(next) },
 	}
 	return middlewares[mName]
 }
diff --git a/src/core/middlewares/config.go b/src/core/middlewares/config.go
index f8147b49dbbc9f01a32a07618f69fe5beab80dba..fa2b536f5bf4ec20ed046d61168b34d157927bc4 100644
--- a/src/core/middlewares/config.go
+++ b/src/core/middlewares/config.go
@@ -26,14 +26,13 @@ const (
 	SIZEQUOTA        = "sizequota"
 	COUNTQUOTA       = "countquota"
 	IMMUTABLE        = "immutable"
-	REGTOKEN         = "regtoken"
 )
 
 // ChartMiddlewares middlewares for chart server
 var ChartMiddlewares = []string{CHART}
 
 // Middlewares with sequential organization
-var Middlewares = []string{READONLY, URL, REGTOKEN, MUITIPLEMANIFEST, LISTREPO, CONTENTTRUST, VULNERABLE, SIZEQUOTA, IMMUTABLE, COUNTQUOTA}
+var Middlewares = []string{READONLY, URL, MUITIPLEMANIFEST, LISTREPO, CONTENTTRUST, VULNERABLE, SIZEQUOTA, IMMUTABLE, COUNTQUOTA}
 
 // MiddlewaresLocal ...
 var MiddlewaresLocal = []string{SIZEQUOTA, IMMUTABLE, COUNTQUOTA}
diff --git a/src/core/middlewares/contenttrust/handler.go b/src/core/middlewares/contenttrust/handler.go
index 049a2a88b673d554633bd6e27510ff291edd8855..bcc4de44a736501488dc8fad26fcfed24ac7a292 100644
--- a/src/core/middlewares/contenttrust/handler.go
+++ b/src/core/middlewares/contenttrust/handler.go
@@ -49,10 +49,6 @@ func (cth contentTrustHandler) ServeHTTP(rw http.ResponseWriter, req *http.Reque
 		cth.next.ServeHTTP(rw, req)
 		return
 	}
-	if scannerPull, ok := util.ScannerPullFromContext(req.Context()); ok && scannerPull {
-		cth.next.ServeHTTP(rw, req)
-		return
-	}
 	if !util.GetPolicyChecker().ContentTrustEnabled(img.ProjectName) {
 		cth.next.ServeHTTP(rw, req)
 		return
diff --git a/src/core/middlewares/regtoken/handler.go b/src/core/middlewares/regtoken/handler.go
deleted file mode 100644
index d1f561e123666896b3c0b2601a4e0d042c1cb179..0000000000000000000000000000000000000000
--- a/src/core/middlewares/regtoken/handler.go
+++ /dev/null
@@ -1,71 +0,0 @@
-package regtoken
-
-import (
-	"github.com/docker/distribution/registry/auth"
-	"github.com/goharbor/harbor/src/common/rbac"
-	"github.com/goharbor/harbor/src/common/utils/log"
-	"github.com/goharbor/harbor/src/core/middlewares/util"
-	pkg_token "github.com/goharbor/harbor/src/pkg/token"
-	"github.com/goharbor/harbor/src/pkg/token/claims/registry"
-	"net/http"
-	"strings"
-)
-
-// regTokenHandler is responsible for decoding the registry token in the docker pull request header,
-// as harbor adds customized claims action into registry auth token, the middlerware is for decode it and write it into
-// request context, then for other middlerwares in chain to use it to bypass request validation.
-type regTokenHandler struct {
-	next http.Handler
-}
-
-// New ...
-func New(next http.Handler) http.Handler {
-	return &regTokenHandler{
-		next: next,
-	}
-}
-
-// ServeHTTP ...
-func (r *regTokenHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
-	imgRaw := req.Context().Value(util.ImageInfoCtxKey)
-	if imgRaw == nil {
-		r.next.ServeHTTP(rw, req)
-		return
-	}
-	img, _ := req.Context().Value(util.ImageInfoCtxKey).(util.ImageInfo)
-	if img.Digest == "" {
-		r.next.ServeHTTP(rw, req)
-		return
-	}
-
-	parts := strings.Split(req.Header.Get("Authorization"), " ")
-	if len(parts) != 2 || strings.ToLower(parts[0]) != "bearer" {
-		r.next.ServeHTTP(rw, req)
-		return
-	}
-	rawToken := parts[1]
-	opt := pkg_token.DefaultTokenOptions()
-	regTK, err := pkg_token.Parse(opt, rawToken, &registry.Claim{})
-	if err != nil {
-		log.Errorf("failed to decode reg token: %v, the error is skipped and round the request to native registry.", err)
-		r.next.ServeHTTP(rw, req)
-		return
-	}
-
-	accessItems := []auth.Access{}
-	accessItems = append(accessItems, auth.Access{
-		Resource: auth.Resource{
-			Type: rbac.ResourceRepository.String(),
-			Name: img.Repository,
-		},
-		Action: rbac.ActionScannerPull.String(),
-	})
-
-	accessSet := regTK.Claims.(*registry.Claim).GetAccess()
-	for _, access := range accessItems {
-		if accessSet.Contains(access) {
-			*req = *(req.WithContext(util.NewScannerPullContext(req.Context(), true)))
-		}
-	}
-	r.next.ServeHTTP(rw, req)
-}
diff --git a/src/core/middlewares/regtoken/handler_test.go b/src/core/middlewares/regtoken/handler_test.go
deleted file mode 100644
index 5736781a2f46d75d1c89cf10ed73833246863490..0000000000000000000000000000000000000000
--- a/src/core/middlewares/regtoken/handler_test.go
+++ /dev/null
@@ -1,55 +0,0 @@
-package regtoken
-
-import (
-	"fmt"
-	"github.com/goharbor/harbor/src/core/middlewares/util"
-	"github.com/stretchr/testify/suite"
-	"net/http"
-	"net/http/httptest"
-	"os"
-	"testing"
-)
-
-type HandlerSuite struct {
-	suite.Suite
-}
-
-func doPullManifestRequest(projectName, name, tag string, next ...http.HandlerFunc) int {
-	repository := fmt.Sprintf("%s/%s", projectName, name)
-
-	url := fmt.Sprintf("/v2/%s/manifests/%s", repository, tag)
-	req, _ := http.NewRequest("GET", url, nil)
-
-	token := "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IkNWUTc6REM3NTpHVEROOkxTTUs6VUFJTjpIUUVWOlZVSDQ6Q0lRRDpRV01COlM0Qzc6U0c0STpGRUhYIn0.eyJpc3MiOiJoYXJib3ItdG9rZW4taXNzdWVyIiwic3ViIjoicm9ib3QkZGVtbzExIiwiYXVkIjoiaGFyYm9yLXJlZ2lzdHJ5IiwiZXhwIjoxNTcxNzYzOTI2LCJuYmYiOjE1NzE3NjM4NjYsImlhdCI6MTU3MTc2Mzg2NiwianRpIjoiTnRaZWx4Z01KTUU1MXlEMCIsImFjY2VzcyI6W3sidHlwZSI6InJlcG9zaXRvcnkiLCJuYW1lIjoibGlicmFyeS9oZWxsby13b3JsZCIsImFjdGlvbnMiOlsicHVzaCIsIioiLCJwdWxsIiwic2Nhbm5lcnB1bGwiXX1dfQ.GlWuvtoxmChnpvbWaG5901Z9-g63DrzyNUREWlDbR5gnNeuOKjLNyE4QpogAQKx2yYtcGxbqNL3VfJkExJ_gMS0Qw8e10utGOawwqD4oqf_J06eKq4HzpZJengZfcjMA4g2RoeOlqdVdwimB_PdX9vkBO1od0wX0Cc2v0p2w5TkibcThKRoeLeVs2oRewkKLuVHNSM8wwRIlAvpWJuNnvRCFlHRkLcZM_KpGXqT7H-PZETTisWCi1pMxeYEwIsDFLlTKdV8LaiDeDmH-RaLOsuyAySYEW9Ynk5K3P_dUl2c_SYQXloPyi0MvXxSn6EWE4eHF2oQDM_SvIzR9sOVB8TtjMjKKMQ4yr_mqgMcfEpnInJATExBR56wmxNdLESncHl8rUYCe2jCjQFuR9NGQA1tGdjI4NoBN-OVD0dBs9rm_mkb2tgD-3gEhyzAw6hg0uzDsF7bj5Aq8scoi42UurhX2bZM89s4-TWBp4DWuBG0HDiwpOiBvB3RMm6MpQxsqrl0hQm_WH18L6QCknAW2e3d_6DJWJ0eBzISrhDr7LkqJKl1J8pv4zqoh_EUVeLyzTmjEULm-VbnpVF4wW5yTLF3S6F7Ox4vwWtVfi1XQNVOcJDB3VPUsRgiTTuCW-ZGcBLw-OdIcwaJ3T_QZkEjUw1f6i1JcGa0Mpgl83aLiSdQ 0xc0003c77c0 map[alg:RS256 kid:CVQ7:DC75:GTDN:LSMK:UAIN:HQEV:VUH4:CIQD:QWMB:S4C7:SG4I:FEHX typ:JWT] 0xc000496000 GlWuvtoxmChnpvbWaG5901Z9-g63DrzyNUREWlDbR5gnNeuOKjLNyE4QpogAQKx2yYtcGxbqNL3VfJkExJ_gMS0Qw8e10utGOawwqD4oqf_J06eKq4HzpZJengZfcjMA4g2RoeOlqdVdwimB_PdX9vkBO1od0wX0Cc2v0p2w5TkibcThKRoeLeVs2oRewkKLuVHNSM8wwRIlAvpWJuNnvRCFlHRkLcZM_KpGXqT7H-PZETTisWCi1pMxeYEwIsDFLlTKdV8LaiDeDmH-RaLOsuyAySYEW9Ynk5K3P_dUl2c_SYQXloPyi0MvXxSn6EWE4eHF2oQDM_SvIzR9sOVB8TtjMjKKMQ4yr_mqgMcfEpnInJATExBR56wmxNdLESncHl8rUYCe2jCjQFuR9NGQA1tGdjI4NoBN-OVD0dBs9rm_mkb2tgD-3gEhyzAw6hg0uzDsF7bj5Aq8scoi42UurhX2bZM89s4-TWBp4DWuBG0HDiwpOiBvB3RMm6MpQxsqrl0hQm_WH18L6QCknAW2e3d_6DJWJ0eBzISrhDr7LkqJKl1J8pv4zqoh_EUVeLyzTmjEULm-VbnpVF4wW5yTLF3S6F7Ox4vwWtVfi1XQNVOcJDB3VPUsRgiTTuCW-ZGcBLw-OdIcwaJ3T_QZkEjUw1f6i1JcGa0Mpgl83aLiSdQ"
-	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
-	rr := httptest.NewRecorder()
-
-	var n http.HandlerFunc
-	if len(next) > 0 {
-		n = next[0]
-	} else {
-		n = func(w http.ResponseWriter, req *http.Request) {
-			w.WriteHeader(http.StatusNotFound)
-		}
-	}
-
-	h := New(http.HandlerFunc(n))
-	h.ServeHTTP(util.NewCustomResponseWriter(rr), req)
-
-	return rr.Code
-}
-
-func (suite *HandlerSuite) TestPullManifest() {
-	code1 := doPullManifestRequest("library", "photon", "release-1.10")
-	suite.Equal(http.StatusNotFound, code1)
-}
-
-func TestMain(m *testing.M) {
-	if result := m.Run(); result != 0 {
-		os.Exit(result)
-	}
-}
-
-func TestRunHandlerSuite(t *testing.T) {
-	suite.Run(t, new(HandlerSuite))
-}
diff --git a/src/core/middlewares/util/util.go b/src/core/middlewares/util/util.go
index e023fc8021082fbc93c3a8fdc7bcde0f87f15c51..9c05b7599ff9f0efaa12ade6de8100ef620afb3e 100644
--- a/src/core/middlewares/util/util.go
+++ b/src/core/middlewares/util/util.go
@@ -49,8 +49,6 @@ type contextKey string
 const (
 	// ImageInfoCtxKey the context key for image information
 	ImageInfoCtxKey = contextKey("ImageInfo")
-	// ScannerPullCtxKey the context key for robot account to bypass the pull policy check.
-	ScannerPullCtxKey = contextKey("ScannerPullCheck")
 	// TokenUsername ...
 	// TODO: temp solution, remove after vmware/harbor#2242 is resolved.
 	TokenUsername = "harbor-core"
@@ -445,17 +443,6 @@ func ManifestInfoFromContext(ctx context.Context) (*ManifestInfo, bool) {
 	return info, ok
 }
 
-// NewScannerPullContext returns context with policy check info
-func NewScannerPullContext(ctx context.Context, scannerPull bool) context.Context {
-	return context.WithValue(ctx, ScannerPullCtxKey, scannerPull)
-}
-
-// ScannerPullFromContext returns whether to bypass policy check
-func ScannerPullFromContext(ctx context.Context) (bool, bool) {
-	info, ok := ctx.Value(ScannerPullCtxKey).(bool)
-	return info, ok
-}
-
 // NewBlobInfoContext returns context with blob info
 func NewBlobInfoContext(ctx context.Context, info *BlobInfo) context.Context {
 	return context.WithValue(ctx, blobInfoKey, info)
diff --git a/src/core/middlewares/vulnerable/handler.go b/src/core/middlewares/vulnerable/handler.go
index 108d683f4b32421522b0586b270fd25d1c0bcae3..a1ba6bda98cacd687de807403461492baffdb3d8 100644
--- a/src/core/middlewares/vulnerable/handler.go
+++ b/src/core/middlewares/vulnerable/handler.go
@@ -52,11 +52,6 @@ func (vh vulnerableHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request)
 		return
 	}
 
-	if scannerPull, ok := util.ScannerPullFromContext(req.Context()); ok && scannerPull {
-		vh.next.ServeHTTP(rw, req)
-		return
-	}
-
 	// Is vulnerable policy set?
 	projectVulnerableEnabled, projectVulnerableSeverity, wl := util.GetPolicyChecker().VulnerablePolicy(img.ProjectName)
 	if !projectVulnerableEnabled {
@@ -114,10 +109,10 @@ func (vh vulnerableHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request)
 		return
 	}
 
-	// Print scannerPull CVE list
+	// Print bypass CVE list
 	if len(summary.CVEBypassed) > 0 {
 		for _, cve := range summary.CVEBypassed {
-			log.Infof("Vulnerable policy check: scannerPull CVE %s", cve)
+			log.Infof("Vulnerable policy check: bypass CVE %s", cve)
 		}
 	}
 
diff --git a/src/core/service/token/authutils.go b/src/core/service/token/authutils.go
index d04fe264d0cc35c8cca2280abdc209dd5cbd35cd..8de8a50ca50d105b1b9759d09cb8060dd7932335 100644
--- a/src/core/service/token/authutils.go
+++ b/src/core/service/token/authutils.go
@@ -133,9 +133,6 @@ func permToActions(p string) []string {
 	if strings.Contains(p, "R") {
 		res = append(res, "pull")
 	}
-	if strings.Contains(p, "S") {
-		res = append(res, "scanner-pull")
-	}
 	return res
 }
 
diff --git a/src/core/service/token/creator.go b/src/core/service/token/creator.go
index ad002e51132897027f9dc95dcdc8525e8a9df291..feca191e6e20c5b36a7930e4bf6cf26b2f12e9d1 100644
--- a/src/core/service/token/creator.go
+++ b/src/core/service/token/creator.go
@@ -177,8 +177,6 @@ func (rep repositoryFilter) filter(ctx security.Context, pm promgr.ProjectManage
 		permission = "RWM"
 	} else if ctx.Can(rbac.ActionPush, resource) {
 		permission = "RW"
-	} else if ctx.Can(rbac.ActionScannerPull, resource) {
-		permission = "RS"
 	} else if ctx.Can(rbac.ActionPull, resource) {
 		permission = "R"
 	}
diff --git a/src/pkg/robot/controller.go b/src/pkg/robot/controller.go
index 1d5acc170c2561060390e64f925a1e3b2f7d3244..5a65657116feaba019a223ae4d4854f0fe176e5b 100644
--- a/src/pkg/robot/controller.go
+++ b/src/pkg/robot/controller.go
@@ -2,14 +2,12 @@ package robot
 
 import (
 	"fmt"
-	"github.com/dgrijalva/jwt-go"
 	"github.com/goharbor/harbor/src/common"
+	"github.com/goharbor/harbor/src/common/token"
 	"github.com/goharbor/harbor/src/common/utils/log"
 	"github.com/goharbor/harbor/src/core/config"
 	"github.com/goharbor/harbor/src/pkg/q"
 	"github.com/goharbor/harbor/src/pkg/robot/model"
-	"github.com/goharbor/harbor/src/pkg/token"
-	robot_claim "github.com/goharbor/harbor/src/pkg/token/claims/robot"
 	"github.com/pkg/errors"
 	"time"
 )
@@ -78,23 +76,13 @@ func (d *DefaultAPIController) CreateRobotAccount(robotReq *model.RobotCreate) (
 
 	// generate the token, and return it with response data.
 	// token is not stored in the database.
-	opt := token.DefaultTokenOptions()
-	rClaims := &robot_claim.Claim{
-		TokenID:   id,
-		ProjectID: robotReq.ProjectID,
-		Access:    robotReq.Access,
-		StandardClaims: jwt.StandardClaims{
-			IssuedAt:  time.Now().UTC().Unix(),
-			ExpiresAt: expiresAt,
-			Issuer:    opt.Issuer,
-		},
-	}
-	tk, err := token.New(opt, rClaims)
+	jwtToken, err := token.New(id, robotReq.ProjectID, expiresAt, robotReq.Access)
 	if err != nil {
 		deferDel = err
 		return nil, fmt.Errorf("failed to valid parameters to generate token for robot account, %v", err)
 	}
-	rawTk, err := tk.Raw()
+
+	rawTk, err := jwtToken.Raw()
 	if err != nil {
 		deferDel = err
 		return nil, fmt.Errorf("failed to sign token for robot account, %v", err)
diff --git a/src/pkg/token/claims/registry/accesses.go b/src/pkg/token/claims/registry/accesses.go
deleted file mode 100644
index 3665a415d5e00adf76cd0bdf9ff858028b9b97a2..0000000000000000000000000000000000000000
--- a/src/pkg/token/claims/registry/accesses.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package registry
-
-import (
-	"github.com/docker/distribution/registry/auth"
-)
-
-// Accesses ...
-type Accesses map[auth.Resource]actions
-
-// Contains ...
-func (s Accesses) Contains(access auth.Access) bool {
-	actionSet, ok := s[access.Resource]
-	if ok {
-		return actionSet.contains(access.Action)
-	}
-
-	return false
-}
-
-type actions struct {
-	stringSet
-}
-
-func newActions(set ...string) actions {
-	return actions{newStringSet(set...)}
-}
-
-func (s actions) contains(action string) bool {
-	return s.stringSet.contains(action)
-}
-
-type stringSet map[string]struct{}
-
-func newStringSet(keys ...string) stringSet {
-	ss := make(stringSet, len(keys))
-	ss.add(keys...)
-	return ss
-}
-
-func (ss stringSet) add(keys ...string) {
-	for _, key := range keys {
-		ss[key] = struct{}{}
-	}
-}
-
-func (ss stringSet) contains(key string) bool {
-	_, ok := ss[key]
-	return ok
-}
diff --git a/src/pkg/token/claims/registry/registry.go b/src/pkg/token/claims/registry/registry.go
deleted file mode 100644
index 07d18ce58debb8be832ea642cc98796db7c2ad0f..0000000000000000000000000000000000000000
--- a/src/pkg/token/claims/registry/registry.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package registry
-
-import (
-	"github.com/dgrijalva/jwt-go"
-	"github.com/docker/distribution/registry/auth"
-	"github.com/docker/distribution/registry/auth/token"
-)
-
-// Claim implements the interface of jwt.Claims
-type Claim struct {
-	jwt.StandardClaims
-	Access []*token.ResourceActions `json:"access"`
-}
-
-// Valid valid the standard claims
-func (rc *Claim) Valid() error {
-	return rc.StandardClaims.Valid()
-}
-
-// GetAccess ...
-func (rc *Claim) GetAccess() Accesses {
-	accesses := make(Accesses, len(rc.Access))
-	for _, resourceActions := range rc.Access {
-		resource := auth.Resource{
-			Type: resourceActions.Type,
-			Name: resourceActions.Name,
-		}
-		set, exists := accesses[resource]
-		if !exists {
-			set = newActions()
-			accesses[resource] = set
-		}
-		for _, action := range resourceActions.Actions {
-			set.add(action)
-		}
-	}
-	return accesses
-}
diff --git a/src/pkg/token/claims/registry/registry_test.go b/src/pkg/token/claims/registry/registry_test.go
deleted file mode 100644
index 600a07edd7b50b5aa5ce13817176c80ef7284004..0000000000000000000000000000000000000000
--- a/src/pkg/token/claims/registry/registry_test.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package registry
-
-import (
-	"github.com/docker/distribution/registry/auth"
-	"github.com/docker/distribution/registry/auth/token"
-	"github.com/goharbor/harbor/src/common/rbac"
-	"github.com/stretchr/testify/assert"
-	"testing"
-)
-
-func TestValid(t *testing.T) {
-	access := &token.ResourceActions{
-		Type:    "type",
-		Name:    "repository",
-		Actions: []string{"pull", "push"},
-	}
-	accesses := []*token.ResourceActions{}
-	accesses = append(accesses, access)
-	rClaims := &Claim{
-		Access: accesses,
-	}
-	assert.Nil(t, rClaims.Valid())
-}
-
-func TestGetAccessSet(t *testing.T) {
-	access := &token.ResourceActions{
-		Type:    "repository",
-		Name:    "hello-world",
-		Actions: []string{"pull", "push", "scanner-pull"},
-	}
-	accesses := []*token.ResourceActions{}
-	accesses = append(accesses, access)
-	rClaims := &Claim{
-		Access: accesses,
-	}
-
-	auth1 := auth.Access{
-		Resource: auth.Resource{
-			Type: "repository",
-			Name: "hello-world",
-		},
-		Action: rbac.ActionScannerPull.String(),
-	}
-	auth2 := auth.Access{
-		Resource: auth.Resource{
-			Type: "repository",
-			Name: "busubox",
-		},
-		Action: rbac.ActionScannerPull.String(),
-	}
-	set := rClaims.GetAccess()
-	assert.True(t, set.Contains(auth1))
-	assert.False(t, set.Contains(auth2))
-}
diff --git a/src/pkg/token/token.go b/src/pkg/token/token.go
deleted file mode 100644
index 62e1e3fec76203cd8bcc3b4746a666fc762ab7fc..0000000000000000000000000000000000000000
--- a/src/pkg/token/token.go
+++ /dev/null
@@ -1,77 +0,0 @@
-package token
-
-import (
-	"crypto/ecdsa"
-	"crypto/rsa"
-	"errors"
-	"fmt"
-	"github.com/dgrijalva/jwt-go"
-	"github.com/goharbor/harbor/src/common/utils/log"
-)
-
-// Token is a jwt token for harbor robot account,
-type Token struct {
-	jwt.Token
-	Opt   *Options
-	Claim jwt.Claims
-}
-
-// New ...
-func New(opt *Options, claims jwt.Claims) (*Token, error) {
-	err := claims.Valid()
-	if err != nil {
-		return nil, err
-	}
-	return &Token{
-		Token: *jwt.NewWithClaims(opt.SignMethod, claims),
-		Opt:   opt,
-		Claim: claims,
-	}, nil
-}
-
-// Raw get the Raw string of token
-func (tk *Token) Raw() (string, error) {
-	key, err := tk.Opt.GetKey()
-	if err != nil {
-		return "", nil
-	}
-	raw, err := tk.Token.SignedString(key)
-	if err != nil {
-		log.Debugf(fmt.Sprintf("failed to issue token %v", err))
-		return "", err
-	}
-	return raw, err
-}
-
-// Parse ...
-func Parse(opt *Options, rawToken string, claims jwt.Claims) (*Token, error) {
-	key, err := opt.GetKey()
-	if err != nil {
-		return nil, err
-	}
-	token, err := jwt.ParseWithClaims(rawToken, claims, func(token *jwt.Token) (interface{}, error) {
-		if token.Method.Alg() != opt.SignMethod.Alg() {
-			return nil, errors.New("invalid signing method")
-		}
-		switch k := key.(type) {
-		case *rsa.PrivateKey:
-			return &k.PublicKey, nil
-		case *ecdsa.PrivateKey:
-			return &k.PublicKey, nil
-		default:
-			return key, nil
-		}
-	})
-	if err != nil {
-		log.Errorf(fmt.Sprintf("parse token error, %v", err))
-		return nil, err
-	}
-
-	if !token.Valid {
-		log.Errorf(fmt.Sprintf("invalid jwt token, %v", token))
-		return nil, errors.New("invalid jwt token")
-	}
-	return &Token{
-		Token: *token,
-	}, nil
-}