CVE-2026-56443

CVE-2026-56443 is a medium-severity incorrect authorization vulnerability in code.gitea.io/gitea (go), affecting versions < 1.27.0. It is fixed in 1.27.0.

Does this CVE actually affect you?

Kodem shows which CVEs are reachable and running in your applications, so you fix what's exploitable, not just what's listed.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Runtime intelligence, not another scanner.

Summary

Gitea: Token public-only scope bypassed on Limited-visibility owners (Repository + Package categories), residual after CVE-2026-25714 / PR #37118

After PR #37118 / CVE-2026-25714
(fix: Unify public-only token filtering in API queries and repo access checks,
merged 2026-05-18, backport #37773 to 1.26.2, the May 2026 unification pass
for public-only token filtering, reporter Medoedus per the 1.26.2 release notes),
the public-only PAT scope is still bypassable on Repository and Package
scope categories when the owner's Visibility = Limited (instance-internal).

The sibling Org / User / ActivityPub cases in the same checkTokenPublicOnly
switch correctly reject Limited owners via !Visibility.IsPublic(). The
Repository / Package cases use repo.IsPrivate or Owner.Visibility.IsPrivate(),
both of which return false for VisibleTypeLimited, so a public-only PAT
strictly exceeds anonymous reach on a Limited owner.

Tested on gitea/gitea:1.26.2. The decisive marker is that PR #37118's
unification IS applied in the version under test (User-category PROBE returns
403 "token scope is limited to public users"). Despite that, the
Repository-category PROBE on the same Limited owner with the same PAT returns
200 and serves content.

Affected entry points (4 spots)

File:Line Function Affected surface
routers/api/v1/api.go:292 checkTokenPublicOnly Package case API v1 packages
routers/api/packages/api.go:76 reqPackageAccess middleware All 24 native package registries (/api/packages/<type>/...)
services/context/api.go TokenCanAccessRepo helper All API v1 Repository-category endpoints, content, issues, PRs, releases, labels, milestones, etc.
services/context/permission.go:32 CheckTokenScopes (called via CheckRepoScopedToken) Web download endpoints /raw, /media, /attachments. LFS routes (services/lfs/server.go:470/472, services/lfs/locks.go:62/151/216/284) also chain through this helper.

All four sinks check repo.IsPrivate or Owner.Visibility.IsPrivate() only.
VisibleTypeLimited falls through.

// modules/structs/visible_type.go
func (vt VisibleType) IsPrivate() bool { return vt == VisibleTypePrivate }   // line 39-40
func (vt VisibleType) IsLimited() bool { return vt == VisibleTypeLimited }   // line 33-34

Same-file evidence (routers/api/v1/api.go:246-299 after PR #37118)

case auth_model.AccessTokenScopeCategoryOrganization:
    orgPrivate := ... && !ctx.Org.Organization.Visibility.IsPublic()        // !IsPublic ✓
case auth_model.AccessTokenScopeCategoryUser:
    if ... && !ctx.ContextUser.Visibility.IsPublic() { ... }                // !IsPublic ✓
case auth_model.AccessTokenScopeCategoryActivityPub:
    if ... && !ctx.ContextUser.Visibility.IsPublic() { ... }                // !IsPublic ✓

case auth_model.AccessTokenScopeCategoryPackage:
    if ctx.Package != nil && ctx.Package.Owner.Visibility.IsPrivate() {     // IsPrivate ONLY ✗
        ctx.APIError(http.StatusForbidden, "token scope is limited to public packages")
        return
    }

TokenCanAccessRepo (services/context/api.go) reduces to !repo.IsPrivate:

// A public-only token cannot reach a private repo; any other token is unrestricted by this check.
func (ctx *APIContext) TokenCanAccessRepo(repo *repo_model.Repository) bool {
    return repo == nil || !ctx.PublicOnly || !repo.IsPrivate
}

CheckTokenScopes (services/context/permission.go:32):

if publicOnly && repo != nil && repo.IsPrivate {
    ctx.HTTPError(http.StatusForbidden)
    return
}

PoC (Docker e2e VERIFIED on gitea/gitea:1.26.2, 2026-06-05)

Full script in the report (run-poc.sh). Setup:

  1. Create user limuser. PATCH /api/v1/admin/users/limuser with body
    {"visibility":"limited", ...}, response confirms "visibility":"limited".
  2. Upload a generic package as limuser:
    PUT /api/packages/limuser/generic/secretpkg/1.0.0/secret.txt with body
    secret-content-internal-only201.
  3. Create user attacker.
  4. Mint PAT for attacker with scopes=["read:package","read:user","read:repository","public-only"].

Result on gitea/gitea:1.26.2, nine PROBEs:

PROBE A  (download package via attacker PAT)
    HTTP=200  Body: secret-content-internal-only

PROBE C  (read README of limuser's PUBLIC repo)
    HTTP=200  Body: {"name":"README.md", ...}

PROBE F  (sanity, User category, same PAT, same owner)
    HTTP=403  Body: {"message":"token scope is limited to public users"}

PROBE G  (Repository category, same PAT, same owner)
    HTTP=200  Body: {"name":"README.md", ...}                    ← bypass

PROBE H  (list limuser's repos, User category)
    HTTP=403  Body: {"message":"token scope is limited to public users"}

PROBE M  (git HTTPS smart protocol, info/refs)
    HTTP=200  Body: 001e# service=git-upload-pack ... HEAD ...   ← full clone enabled

PROBE N  (write attempt: POST contents/hacked.txt)
    HTTP=403  Body: {"message":"user should have a permission to write to the target branch"}
                                                                    Integrity:N confirmed

PROBE O  (Limited ORG, same bypass class)
    Org category    : HTTP=403  {"message":"token scope is limited to public orgs"}
    Repo category   : HTTP=200  README content                  ← bypass

Anonymous baseline (no auth) on every above endpoint: HTTP=401/404

Gitea's own server error string in PROBE F / H / O, "token scope is limited
to public users"
/ "public orgs", is the explicit declaration of intent.
Repository / Package category violates that intent on the same Limited owner.

Why this is not a duplicate of CVE-2026-25714

CVE-2026-25714 / PR #37118 (the May 2026 unification pass for public-only token
filtering, merged 2026-05-18, backported to 1.26.2 via PR #37773) realigned
checkTokenPublicOnly's Org / User / ActivityPub cases on !Visibility.IsPublic()
and introduced the TokenCanAccessRepo helper for the Repository / Issue /
Notification cases.

PROBE F on 1.26.2 returns 403 "token scope is limited to public users" for
the User category, i.e. PR #37118's unification IS in effect on the version
under test. The Repository / Package leak occurs after that fix; the Limited
gap is the next residual issue on the same hygiene effort (the Package case was
not touched, and TokenCanAccessRepo reduces to !repo.IsPrivate without
consulting owner visibility), not the same bug.

Suggested fix (4 spots, 1-line shape each)

// routers/api/v1/api.go:292  (checkTokenPublicOnly Package case)
- if ctx.Package != nil && ctx.Package.Owner.Visibility.IsPrivate() {
+ if ctx.Package != nil && !ctx.Package.Owner.Visibility.IsPublic() {

// routers/api/packages/api.go:76  (reqPackageAccess middleware)
- if ctx.Package != nil && ctx.Package.Owner.Visibility.IsPrivate() {
+ if ctx.Package != nil && !ctx.Package.Owner.Visibility.IsPublic() {

// services/context/api.go  (TokenCanAccessRepo helper)
- return repo == nil || !ctx.PublicOnly || !repo.IsPrivate
+ return repo == nil || !ctx.PublicOnly ||
+     (!repo.IsPrivate && repo.Owner != nil && repo.Owner.Visibility.IsPublic())

// services/context/permission.go:32  (CheckTokenScopes)
- if publicOnly && repo != nil && repo.IsPrivate {
+ if publicOnly && repo != nil &&
+     (repo.IsPrivate || (repo.Owner != nil && !repo.Owner.Visibility.IsPublic())) {

This aligns the Repository / Package categories with the User / Org / ActivityPub
siblings already shipped in PR #37118.

Reporter

JebeenLee

Impact

The application does not correctly enforce access controls, allowing a principal to access resources or operations beyond their granted permissions. Typical impact: unauthorized data access or execution of privileged operations.

CVE-2026-56443 has a CVSS score of 4.3 (Medium). The vector is network-reachable, low privileges required, and no user interaction. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (1.27.0); upgrading removes the vulnerable code path.

Affected versions

code.gitea.io/gitea (< 1.27.0)

Security releases

code.gitea.io/gitea → 1.27.0 (go)

Kodem intelligence

Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.

Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.

Already deployed Kodem?

See it in your environmentNew to Kodem? Get a demo →

Remediation advice

Upgrade code.gitea.io/gitea to 1.27.0 or later to resolve this vulnerability.

Kodem Kai can prioritize this vulnerability in your dependency tree and generate a fix recommendation.

Frequently Asked Questions

  1. What is CVE-2026-56443? CVE-2026-56443 is a medium-severity incorrect authorization vulnerability in code.gitea.io/gitea (go), affecting versions < 1.27.0. It is fixed in 1.27.0. The application does not correctly enforce access controls, allowing a principal to access resources or operations beyond their granted permissions.
  2. How severe is CVE-2026-56443? CVE-2026-56443 has a CVSS score of 4.3 (Medium). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
  3. Which versions of code.gitea.io/gitea are affected by CVE-2026-56443? code.gitea.io/gitea (go) versions < 1.27.0 is affected.
  4. Is there a fix for CVE-2026-56443? Yes. CVE-2026-56443 is fixed in 1.27.0. Upgrade to this version or later.
  5. Is CVE-2026-56443 exploitable, and should I be worried? Whether CVE-2026-56443 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
  6. What actually determines whether CVE-2026-56443 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
  7. How do I fix CVE-2026-56443? Upgrade code.gitea.io/gitea to 1.27.0 or later.

Other vulnerabilities in code.gitea.io/gitea

Stop the waste.
Protect your environment with Kodem.