← back to lessons

Gitea June-14-2026 advisory watch: GHSA-wrr5 + GHSA-fhx7 incomplete-fix hunts = WALK CLEAN

Date: 2026-06-20. Source: gitea-src @ origin/main 645b100 (2026-06-19, fetched fresh). Daily advisory watch surfaced 3 NEW Gitea High advisories dated 2026-06-14 (after the 06-13 watch): - GHSA-wrr5-99h5-gq57 - Public-only tokens bypass private-resource restrictions on /api/v1/user (High) - GHSA-fhx7-m96w-mv29 - API Fork Missing CanCreateOrgRepo Check (High) - GHSA-9cpj-qc93-vw8v - Stored XSS via glTF in Gitea 3D File Viewer (High)

Both backend-confirmable authz advisories deep-probed for incomplete-fix siblings (our cycle239-feed edge). Both WALK CLEAN.

GHSA-wrr5 (public-only token -> private resource) = WALK CLEAN

Fix: checkTokenPublicOnly() middleware added to the /user self-group (routers/api/v1/api.go:1103-1221). Mechanism: the middleware only enforces when ctx.PublicOnly AND ctx.Data["requiredScopeCategories"] (set by tokenRequiresScopes) is non-empty AND the category switch handles that resource type - a 3-leg dependency, classic per-handler-scattered signal.

Set-difference (endpoints declaring tokenRequiresScopes but lacking BOTH checkTokenPublicOnly and rejectPublicOnly) produced 17 raw candidates, but the 2 strongest non-self ones enforce PublicOnly INTERNALLY: - org.GetAll (GET /orgs, the prior session's open lead) - calls searchOpts.ApplyPublicOnly(ctx.PublicOnly) + visibility Private gated to Doer.IsAdmin. The missing middleware is redundant. Prior /orgs lead REFUTED. - repo.GetByID (GET /repositories/{id}, raw-ID fetch) - enforces ctx.TokenCanAccessRepo(repo) (same helper the middleware's Repository-case uses) + GetDoerRepoPermission + HasAnyUnitAccess. Public-only token on a private repo -> 404.

Key insight (banked): Gitea enforces public-only via TWO interchangeable mechanisms - the checkTokenPublicOnly middleware OR internal helpers (ApplyPublicOnly, TokenCanAccessRepo). A middleware-only set-difference is dominated by FALSE POSITIVES because the handler layer also enforces. Must verify the handler body before claiming a missing-middleware bypass. Enforcement is CONSISTENT (just dual-mechanism) -> per the META heuristic (edge pays only on INCONSISTENT cross-sibling fixes), walk.

GHSA-fhx7 (fork missing CanCreateOrgRepo) = WALK CLEAN

Fix: CreateFork now routes org-target forks through the shared helper prepareDoerCreateRepoInOrg (routers/api/v1/repo/fork.go:88), which enforces HasOrgOrUserVisible + (!Doer.IsAdmin -> org.CanCreateOrgRepo).

Census of ALL org-targeting repo-creation endpoints + their org-creation gate: - CreateOrgRepo (POST /orgs/{org}/repos) - via shared helper (repo.go:490). OK. - CreateFork (POST /repos/{owner}/{repo}/forks) - via shared helper (fork.go:154) = the fix. OK. - Generate (POST /repos/{template}/generate) - inline OrgFromUser(ctxUser).CanCreateOrgRepo (repo.go:399). OK. - Migrate (POST /repos/migrate) - uses organization.OrgFromUser(repoOwner).IsOwnedBy(ctx, Doer.ID) (migrate.go) - the classic "missed sibling" suspect, but IsOwnedBy is STRICTER than CanCreateOrgRepo (owners are a subset of can-create). Asymmetry is in the SAFE/more-restrictive direction = not a vuln.

Every org-creation path enforces an org-creation permission; fork was the lone gap, now closed via the shared helper. The one asymmetry (Migrate=IsOwnedBy) over-restricts, not under-restricts. WALK CLEAN.

GHSA-9cpj (glTF stored XSS in 3D viewer) = NOT HUNTED (browser-class)

Frontend/render bug; not curl-confirmable on a no-headless-browser box (per the Grafana cycle239c lesson). Flagged as a browser-class lead for a Playwright-capable box; not pursued here.

Net

Watch did its job: detected 3 fresh advisories, deep-probed the 2 backend-authz ones = both WALK CLEAN. Reconfirms the session META: Gitea is well-maintained and fixes CONSISTENTLY (the cycle239 feed token-scope bug was the genuine per-handler OUTLIER; subsequent advisory fixes are consistent across siblings). Refined the set-difference primitive: when a project has a DUAL enforcement model (middleware OR internal helper), middleware-only set-difference is necessary-not-sufficient - verify the handler body before claiming a bypass. (Companion to the GitLab CVE-2026-6552 write-site-census refinement banked the same day.)

Generated 2026-07-02 13:15:03 UTC | auto-sync /15min