goharbor/harbor · error

empty secret is not allowed

Error message

empty secret is not allowed

What it means

Jobservice DoAuth rejects the Authorization header when it carries the 'Secret' prefix but the token after it is empty after trimming (e.g. 'Authorization: Secret' or 'Secret '). The comment in code says 'in case both two are empty' - an absent secret value is never acceptable.

Source

Thrown at src/jobservice/api/authenticator.go:66

// DoAuth implements same method in interface 'Authenticator'.
func (sa *SecretAuthenticator) DoAuth(req *http.Request) error {
	if req == nil {
		return errors.New("nil request")
	}

	h := strings.TrimSpace(req.Header.Get(authHeader))
	if utils.IsEmptyStr(h) {
		return fmt.Errorf("header '%s' missing", authHeader)
	}

	if !strings.HasPrefix(h, secretPrefix) {
		return fmt.Errorf("'%s' should start with '%s'", authHeader, secretPrefix)
	}

	secret := strings.TrimSpace(strings.TrimPrefix(h, secretPrefix))
	// incase both two are empty
	if utils.IsEmptyStr(secret) {
		return errors.New("empty secret is not allowed")
	}

	expectedSecret := config.GetUIAuthSecret()
	if subtle.ConstantTimeCompare([]byte(expectedSecret), []byte(secret)) == 0 {
		return errors.New("unauthorized")
	}

	return nil
}

View on GitHub (pinned to 7b2fd08cc5)

Solutions

  1. Configure the real shared secret on the caller and send 'Authorization: Secret <value>'
  2. Check the env var / config key that renders the header on the caller side
  3. Redeploy so both sides pick up the value

Example fix

// before
Authorization: Secret 

// after
Authorization: Secret aGVsbG8gam9ic2VydmljZSBzZWNyZXQ=
Defensive patterns

Strategy: validation

Validate before calling

secret := strings.TrimSpace(os.Getenv("JOBSERVICE_SECRET"))
if secret == "" {
    return errors.New("JOBSERVICE_SECRET must be set before calling jobservice")
}
req.Header.Set("Authorization", "Secret "+secret)

Type guard

func isEmptySecretErr(err error) bool { return err != nil && strings.Contains(err.Error(), "empty secret is not allowed") }

Try / catch

if err := sa.DoAuth(req); err != nil {
    if strings.Contains(err.Error(), "empty secret") {
        return errors.New("secret env var not rendered: fix caller config")
    }
    return err
}

Prevention

When it happens

Trigger: A component (typically core) calling jobservice APIs with a Secret-scheme header whose value came from an empty environment variable or template placeholder.

Common situations: JOBSERVICE_SECRET unset when the caller rendered its header; config templating produced 'Secret ' with nothing after it.

Related errors


AI-assisted analysis of goharbor/harbor@7b2fd08cc5 (2026-08-16). Data as JSON: /api/errors/e6e6841186a64004. Report an issue: GitHub.