Researchers at Noscope disclosed CVE-2026-27771, an authentication-bypass in Gitea’s container registry that returns “private” OCI images to any anonymous caller on the network. The flaw affects every Gitea release prior to 1.26.2, has lived in the codebase for close to four years, and is reachable on roughly 30,000 internet-exposed instances across more than 30 countries. The Forgejo fork, which inherits Gitea’s registry implementation, is confirmed affected as well.

What happened

Gitea’s container registry implements the OCI distribution spec, which means it serves the same GET /v2/<name>/manifests/<reference> and GET /v2/<name>/blobs/<digest> endpoints any Docker or containerd client expects. The visibility model is supposed to mirror the rest of Gitea: a package marked private should require an authenticated session with read access to the owning user or organization. On the affected versions it does not. The registry handlers fall through to public-access logic before checking the package’s private flag, so a docker pull against a private image path succeeds with no credentials. There is no token in the request, no cookie, no basic-auth — just a manifest and a blob stream.

Noscope’s scan found the misbehavior on roughly 30,000 reachable Gitea instances. The geographic distribution skews heavily toward China, the United States, Germany, France, and the United Kingdom. The downstream sample includes healthcare providers, aerospace manufacturers, retail infrastructure operators, and ISPs — the kind of organizations that run an internal Gitea precisely because they did not want their container images on a SaaS registry. The bug appears to have shipped close to four years ago, when the container registry feature first landed, and quietly survived every subsequent release until now.

Affected versions

All Gitea releases prior to 1.26.2 are vulnerable. Forgejo inherits the same registry code path and is affected up to the corresponding fixed release. There is no version range qualifier here: if your instance predates 1.26.2 and runs the container registry, an unauthenticated pull works.

Impact

A private container image is rarely “just” a binary. Internal images frequently bake in build artifacts, application source, embedded service accounts, customer data fixtures, and infrastructure secrets that the team never expected to leave the perimeter. A few realistic blast-radius items for an exploited Gitea instance:

  • Source disclosure: any image built off COPY . /app ships the repository it was built from, including .env files that were not properly .dockerignore-d.
  • Credential leak: embedded API tokens, signing keys, cloud credentials, and database passwords in image layers become world-readable. Layers are content-addressed, so a single leaked manifest indexes every blob ever pushed.
  • Build-pipeline mapping: tag history exposes release cadence, branch structure, and CI behavior to an attacker planning a later intrusion.
  • Downstream supply chain risk: if the image is consumed by partners or customers that pull from the same registry, the disclosed contents become a blueprint for tampering with future versions or compromising those consumers.

The vulnerability is read-only — there is no write path to publish poisoned images anonymously — but for organizations using a private registry as a soft secret store (which is more common than anyone wants to admit), read is enough.

Mitigation

  1. Upgrade to Gitea 1.26.2 immediately. This is the only fix that actually closes the bug.
  2. Forgejo operators: upgrade to the corresponding patched release on your channel as soon as it lands; until then, apply the configuration mitigation below.
  3. Configuration mitigation if upgrade has to wait: set [service].REQUIRE_SIGNIN_VIEW = true in app.ini. This forces all content access — including the container registry — through an authenticated session. It is a blunt instrument (it also blocks anonymous browsing of legitimately public repositories) but it shuts the door immediately.
  4. Audit the registry’s access logs for unauthenticated GET /v2/... traffic going back as far as your retention allows. If logs are not retained, assume any private image stored on a reachable instance has been pulled and act accordingly.
  5. Rotate anything sensitive that lived in a private image: embedded tokens, signing keys, database creds, customer fixtures. Container layers are immutable; the only mitigation for leaked contents is invalidation at the source.
  6. Restrict network reach in the interim. If the registry must remain online before patching, gate the /v2/ path behind a reverse proxy that enforces authentication, or move it behind a VPN.

Why this one matters

Self-hosted Git servers are running infrastructure in the most literal sense — they hold the code that becomes the binaries that become production. When a four-year-old bug means the “private” flag on a container repository was always a UI convention rather than an access control, the operative question is not “did anyone exploit this” but “what private images did we ever push to this instance, and what’s in them.” The patch is small. The remediation is not.

References