Harbor insecure default configuration when installed with Harbor-helm #security


Attention Harbor Users:
I want to make everyone aware of the default insecure configuration in Harbor that was reported to us recently.


When installing Harbor with Harbor-helm, there is an option named core.secretName in the values.yaml.
If this configuration item is not specified when installing Harbor with Harbor-helm, it will use the default public/private key to sign the JWT token. which is used to push/pull images in Harbor.
Because the public/private key is public, it is possible for anyone to forge the JWT token and push/pull images in Harbor without any authentication.

The insecure configuration is not present in:

  • Harbor instances installed with harbor-helm where core.secretName is changed from the default to a specific value, or
  • Harbor instances installed with docker-compose, harbor-tile, TKG harbor( carvel packages).


The following Harbor-helm releases have a fix that removes the default insecure configuration possibility:

Harbor-helm: v1.3.18, v1.9.6, 1.10.4, and v1.11.1, In case Harbor is installed with these versions of Harbor-helm, the Harbor instance does not use the default insecure configuration.

Upgrading harbor-helm to a fixed version does NOT fix the issue in existing Harbor instances. The following workaround removes the insecure default configuration.

Note for users of Harbor robot accounts: Because robot accounts use the same key to generate a token, after applying the workaround or upgrading to the latest Harbor helm which fixes this issue, Harbor administrators need to regenerate the robot account token to allow them to log in to Harbor. If the robot account is marked as "Legacy" in the Web UI, administrators cannot rotate it, need to delete it and recreate a new robot account. The affected Harbor helm versions include 1.3.0 - 1.3.17, 1.4.x, 1.5.x, and 1.6.x.


  1. Generate a tls.crt and tls.key pair. make sure the tls.key is a rsa key. if not you need to convert it with OpenSSL.
openssl rsa -in tls.key -out tls.rsa
  1. Encode the tls.crt and tls.key with base64.
cat tls.crt | base64
cat tls.rsa | base64
  1. Create a yaml file and paste the content of base64 output in step 2.
apiVersion: v1
kind: Secret
  name: my-tls-secret
type: kubernetes.io/tls
  tls.crt: |
    <base64 encoding of tls.crt>
  tls.key: |
    <base64 encoding of tls.rsa>
  1. Create a secret with the yaml file.
kubectl -f secret.yaml
  1. Upgrade the instance with the new secret.
helm upgrade --reuse-values <installed_name> <path_to_harbor-helm> --set core.secretName=<secret_name>
  1. Verify if the current key is changed. compare it with the file: tls.key
kubectl exec -it <harbor-core-pod> -- /bin/bash
cat  /etc/core/private_key.pem

For more information

If you have any questions or comments about this advisory:

Open an issue in the Harbor repository


Thanks to Sam Erb from Google for reporting this issue.

For detailed information, please refer:  https://github.com/goharbor/harbor/security/advisories/GHSA-j7jh-fmcm-xxwv

Thank you!

The Harbor Team