Share
## https://sploitus.com/exploit?id=A80B7830-0196-594A-AA8C-1EF928459222
# CVE-2026-28699 โ€” Gitea OAuth2 Scope Bypass via HTTP Basic Auth

Self-contained lab + writeup for **CVE-2026-28699**: a Gitea OAuth2 access token scoped to only
`read:user` can perform full write actions just by being sent as
`Authorization: Basic base64(:x-oauth-basic)` instead of as a Bearer token. The OAuth2
scope system is bypassed for any token presented over Basic auth.

- **Affected:** ` Basic-auth write succeeds (scope bypassed)
python poc.py 1.26.2              # patched    -> Basic-auth write blocked (403)
```

The single `poc.py` provisions a throwaway Gitea (SQLite, system temp dir), runs the **real**
OAuth2 authorization-code flow to mint a `read:user`-only token, then calls a write endpoint over
both Bearer and Basic and prints the verdict. Set `POC_DEBUG=1` to see the auth-flow steps.

### Expected output

Vulnerable `1.26.1`:
```
[Bearer] PATCH /api/v1/user/settings -> HTTP 403   (blocked)
[Basic ] PATCH /api/v1/user/settings -> HTTP 200   (ALLOWED -- scope BYPASSED)
>>> VULNERABLE: read:user token performed a write via Basic auth.
```

Patched `1.26.2`:
```
[Bearer] PATCH /api/v1/user/settings -> HTTP 403   (blocked)
[Basic ] PATCH /api/v1/user/settings -> HTTP 403   (blocked)
>>> PATCHED: scope enforced on both Bearer and Basic.
```

## Root cause in one table

| Auth presentation | `IsApiToken` | `ApiTokenScope` | scope enforced? |
|---|---|---|---|
| OAuth2 token via Bearer | `true` | set | โœ… yes |
| OAuth2 token via **Basic** | `true` | **missing** | โŒ **no (fails open)** |
| Personal access token | `true` | set | โœ… yes |

`services/auth/basic.go` set `IsApiToken` but not `ApiTokenScope` for OAuth2 tokens; the
`tokenRequiresScopes` middleware early-returns when the scope is absent. The 1.26.2 fix adds the
missing `store.GetData()["ApiTokenScope"] = accessTokenScope`.

## Files

| File | Purpose |
|---|---|
| [`WRITEUP.md`](WRITEUP.md) | Full root-cause analysis, impact, remediation, detection |
| `fetch_binaries.py` | Downloads the 1.26.1 / 1.26.2 binaries for your OS/arch |
| `poc.py` | Provisions Gitea, mints a `read:user` token, demonstrates Bearer-vs-Basic |
| `requirements.txt` | `requests` |

## โš ๏ธ Authorised use only

For education and authorised security testing (your own lab, CTF/HTB boxes, in-scope bug bounty
targets). The PoC stands up its own disposable Gitea โ€” point it at nothing you don't own.