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
- Configure the real shared secret on the caller and send 'Authorization: Secret <value>'
- Check the env var / config key that renders the header on the caller side
- 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
- Validate the secret env var at process start
- Disallow empty values in config templates
- Add an integration test that asserts the header renders with a non-empty token
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.