github.com/goharbor/harbor: SSRF in webhook delivery allows ProjectAdmin to reach internal services and cloud metadata endpoints
What fixes it
- 2.13.6github.com/goharbor/harbor, goGitHub
go get github.com/goharbor/harbor@v2.13.6 - 2.14.5github.com/goharbor/harbor, goGitHub
go get github.com/goharbor/harbor@v2.14.5 - 2.15.3github.com/goharbor/harbor, goGitHub
go get github.com/goharbor/harbor@v2.15.3 - 2.16.0github.com/goharbor/harbor, goGitHub
go get github.com/goharbor/harbor@v2.16.0
A fixed version on one release line is not the upgrade target for every line. Check your exact version and any vendor backports.
Description
Impact
A project administrator can configure a webhook (HTTP or Slack) that points at an address inside your network: localhost, private ranges (10/8, 172.16/12, 192.168/16), link-local, or the cloud metadata endpoint 169.254.169.254. When an event fires, Harbor's jobservice sends an HTTP POST to that address from inside your deployment. If the target answers with an error status, the response body is written to the webhook execution log, which project members can read.
In practice this lets a project admin reach services that are not meant to be reachable from outside, and read back parts of their error responses.
Am I affected?
You are affected if all of the following are true:
- You run any Harbor version that supports webhooks (1.7.0 and later).
- Users who are not fully trusted can become project admin. With the default setting Project Creation: Everyone, every registered user can create a project and is its admin.
- jobservice has network access to internal services or a cloud metadata endpoint.
What to do
Upgrade to Harbor v2.15.3, v2.14.5 or v2.13.6, or to v2.16.0 or later.
After upgrading to v2.15.3, v2.14.5 or v2.13.6, webhooks to private, loopback and link-local addresses are rejected, and existing ones stop being delivered.
> [!WARNING] > v2.15.4 and v2.14.6 turn the address check off by default > > v2.15.4 and v2.14.6 allow private, loopback, link-local and cloud metadata targets unless the setting below is false: harbor.yml.tmpl ships network.allow_private_network_access: true, and when HARBOR_ALLOW_PRIVATE_NETWORK_ACCESS is not set (for example in Helm deployments) they are allowed as well. A harbor.yml that already sets false keeps that value. Redirects stay blocked and response bodies stay out of the execution log in every configuration.
To turn the address check on, unless you send webhooks to internal endpoints on purpose:
harbor.ymlinstalls:network.allow_private_network_access: false, then re-runprepare- Helm or other deployments: the environment variable
HARBOR_ALLOW_PRIVATE_NETWORK_ACCESS=falseon both core and jobservice (in the Helm chart:core.extraEnvVarsandjobservice.extraEnvVars)
If you send webhooks to internal endpoints on purpose (for example an in-cluster CI system), set it to true. This turns the protection off, so only use it if you trust all of your project admins.
Until you can upgrade:
- Set Configuration > System Settings > Project Creation to Admin Only, so untrusted users cannot become project admin.
- Restrict outbound traffic from the jobservice container or pod, for example with a Kubernetes NetworkPolicy or firewall rules, so it can only reach the webhook destinations you use. Block
169.254.169.254in all cases. - On cloud instances, require token-based metadata access (AWS IMDSv2, or the equivalent on your provider).
Check for misuse
Review existing webhook targets for internal addresses:
SELECT id, project_id, name, creator, targets FROM notification_policy;
Look for targets using IP literals in private ranges, localhost, 169.254.169.254, or internal service names. The webhook execution logs for these policies show what was sent and what came back.
Text from GitHub Advisory Database
Affected versions 3
- github.com/goharbor/harbor, go>= 1.7.0, < 2.13.6GitHub
- github.com/goharbor/harbor, go>= 2.14.0, < 2.14.5GitHub
- github.com/goharbor/harbor, go>= 2.15.0, < 2.15.3GitHub