Date 2026-06-21. Reinforced THREE times in one session auditing Forgejo against Gitea security advisories. This is the dominant false-positive trap for the Gitea/Forgejo family (and any app that separates a coarse auth middleware from a deep per-resource access computation).
Gitea/Forgejo route groups apply a COARSE middleware that looks like the access gate but only does a shallow check (is the user valid? is a scope-category present? is it a ghost?). The REAL per-resource authorization happens DEEPER, in a per-object access computation. If you set-difference on the coarse middleware alone, you flag false positives.
ListMyRepos looked unguarded (no checkTokenPublicOnly middleware) but services/authz/ AuthorizationReducer (PublicReposAuthorizationReducer) filters private repos internally. The non-repo routes (keys/emails/secrets) had NO deep gate either -> THAT was the real vuln. Lesson: the deep gate saves SOME routes; the gap is where neither middleware NOR deep gate covers.Scope()/Reducer() + CheckRepoScopedToken covered them internally. WALK.ReqContainerAccess (container.go:125-129) is the coarse, visibility-blind check the CVE describes. But the /{username} route group closes (api.go:190) with PackageAssignment() + reqPackageAccess(AccessModeRead), and determineAccessMode (services/context/package.go:95-148) returns AccessModeNone for a ghost on a Private/Limited owner -> denied. NOT VULNERABLE at HEAD. WALK.For Gitea/Forgejo (and any app with this split), before claiming an authz gap from a missing/weak route middleware:
1. Find the route GROUP's full middleware chain (the closing }, mw1, mw2, ... line) - the real gate is often the LAST middleware (e.g. reqPackageAccess(AccessModeRead), checkTokenPublicOnly, reqRepoReader(unit.TypeX)).
2. Find the deep per-resource access computation it relies on: determineAccessMode (packages), AuthorizationReducer / services/authz/ (API tokens), GetUserRepoPermission / HasAccess (repos), BuildCanSeeUserCondition (listing queries).
3. Confirm THAT computation is visibility/scope/ownership-aware for the attacker's principal (anonymous/ghost, public-only token, cross-tenant). Only if BOTH the middleware AND the deep computation miss the case is it a real gap.
The wrr5 win shows the gap is real when the deep gate is RESOURCE-TYPE-SCOPED and the route is a different type: Forgejo's reducer covers REPO resources only, so the non-repo self-routes (keys/emails/actions-secrets) had no coverage at all -> live HIGH. So: map the deep gate's COVERAGE (which resource types / which principals) and find routes OUTSIDE that coverage. That delta is the true positive; routes INSIDE the deep gate's coverage are false positives.