Skip to content

CSRF token not found in request #23001

@khalil8011

Description

@khalil8011

Versions

  • Harbor version: v2.13.4 (also confirmed on v2.13.5)
  • Infrastructure: Podman (rootless), Ubuntu 24.04
  • Installation method: Manual / customized deployment (external Nginx reverse proxy)
  • Registry version: registry-photon:v2.13.4 (distribution/distribution v2.8.3)

Description

After upgrading to Harbor v2.13.x, pushed images no longer appear in the Web UI or via the API. The docker push command completes successfully, and images can be pulled from another machine, but they are never registered in Harbor's database.

The root cause is a regression introduced in v2.13.x where the registry notification endpoint was moved from /service/notifications to /registry/notifications, but the CSRF middleware skipper (csrfSkipper) was not updated to exempt the new path.

As a result, every push notification sent by harbor-registry to harbor-core is rejected with:

{"errors":[{"code":"FORBIDDEN","message":"CSRF token not found in request"}]}

Since the notification is never processed, harbor-core never writes the artifact to the database → the image is invisible in the UI and API.


Steps to Reproduce

  1. Deploy Harbor v2.13.x (tested on v2.13.4 and v2.13.5)
  2. Configure registry_config.yml with the current notification endpoint:
notifications:
  endpoints:
    - name: harbor
      disabled: false
      url: http://harbor-core:8080/registry/notifications
      headers:
        Authorization: [Harbor-Secret <your-secret>]
      timeout: 3000ms
      threshold: 5
      backoff: 1s
  1. Push any Docker image to Harbor:
docker push harbor.example.com/library/myimage:latest
  1. Check Harbor Web UI or API → image is not listed
  2. Pull the same image from another machine → works fine (blobs exist on disk)

Expected Behavior

The pushed image should appear in the Harbor Web UI and API immediately after a successful docker push.


Actual Behavior

harbor-registry sends a POST /registry/notifications to harbor-core, but receives 403 FORBIDDEN due to CSRF protection. The registry logs show:

level=error msg="retryingsink: error writing events: httpSink{http://harbor-core:8080/registry/notifications}: response status 403 Forbidden unaccepted, retrying"
level=warning msg="httpSink{http://harbor-core:8080/registry/notifications} encountered too many errors, backing off"

Direct curl test from inside harbor-core confirms the issue:

curl -X POST http://localhost:8080/registry/notifications \
  -H "Content-Type: application/vnd.docker.distribution.events.v1+json" \
  -H "Authorization: Harbor-Secret <secret>" \
  -d '{"events":[]}'
# Returns: 403 {"errors":[{"code":"FORBIDDEN","message":"CSRF token not found in request"}]}

Note: /api/v2.0/ping returns 200 OK — harbor-core is running correctly. The issue is exclusively the missing CSRF exemption for /registry/.


Additional Notes

  • The issue is present in both v2.13.4 and v2.13.5 (v2.13.5 release notes do not mention any fix for this)
  • The old endpoint /service/notifications returns 404 in v2.13.x — the route no longer exists
  • This bug only manifests in custom/manual deployments; the official Harbor installer may generate a config that masks the issue
  • A temporary workaround is to deploy a CSRF relay proxy between harbor-registry and harbor-core
  • Affected functionality: artifact registration after push, repository listing, image visibility in UI and API

Environment

OS: Ubuntu 24.04
Container runtime: Podman
Harbor core image: docker.io/goharbor/harbor-core:v2.13.4
Registry image: docker.io/goharbor/registry-photon:v2.13.4
Database: PostgreSQL
Proxy: External Nginx (custom config)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions