File overwrite in file update API in Gogs
Corrija agora. Ela está sob exploração confirmada pelo CISA e tem exploit funcional público.
Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable.
Resumo
A API PutContents do Gogs (PUT /api/v1/repos/:owner/:repo/contents/:path), usada para criar/editar arquivos de um repositório via REST, não verificava se algum componente do caminho de destino era um link simbólico antes de escrever conteúdo nele. Um usuário autenticado com permissão de escrita num repositório pode commitar um symlink apontando para fora do working copy (por exemplo .git/config) e depois usar a API para 'editar' esse arquivo, fazendo o Gogs seguir o link e sobrescrever o destino real — o que permite escalar para execução de comandos via configuração Git. Está no catálogo KEV da CISA com exploração confirmada; a pesquisa da Wiz citada no próprio repositório do projeto menciona mais de 700 instâncias comprometidas até dezembro de 2025.
Detalhamento técnico
A falha é uma variante de CWE-59 (Improper Link Resolution Before File Access — 'Link Following'). A função UpdateRepoFile, em internal/database/repo_editor.go, resolve os caminhos relativos informados pela API (OldTreeName/NewTreeName) dentro do working copy local do repositório (localPath) e grava o conteúdo diretamente com os.WriteFile. Antes da correção, a única verificação de symlink existente se aplicava apenas ao caso de criação de arquivo novo (IsNewFile) sobre o caminho final — não cobria diretórios intermediários do caminho nem o caso de atualização de arquivo existente.
Isso permite que um atacante com permissão de push num repositório faça, via git push comum (fora da API), o commit de um link simbólico dentro do repositório apontando para um caminho sensível acessível ao processo do Gogs — o exemplo documentado pelos próprios desenvolvedores é um symlink para .git/config. Em seguida, uma chamada à API PutContents referenciando esse caminho faz o servidor seguir o link e escrever ali o conteúdo controlado pelo atacante.
O impacto de maior gravidade é a sobrescrita de .git/config com diretivas como core.sshCommand (ou hooks), que passam a ser executadas pelo processo Git do servidor na próxima operação sobre aquele repositório (fetch, clone, push), resultando em execução de comando arbitrário com os privilégios do serviço Gogs.
O commit de correção (553707f3) introduz a função hasSymlinkInPath(), que percorre cada segmento do caminho relativo e usa osutil.IsSymlink para detectar link simbólico em qualquer nível da hierarquia, tanto para o caminho antigo quanto o novo, rejeitando a operação antes de qualquer escrita — cobertura mais ampla que a checagem anterior, restrita ao arquivo final em caso de criação.
Como é explorada
Pré-requisito real: conta autenticada no Gogs com permissão de escrita (push) em algum repositório — em instâncias com registro de usuário aberto, isso equivale a qualquer visitante que crie conta e um repositório próprio. Não é uma falha pré-autenticação nem exige configuração exótica além do comportamento padrão de hospedagem de repositórios Git.
A exploração ocorre em duas etapas: primeiro o atacante usa git push normal (não a API) para commitar um objeto symlink (modo 120000) dentro do repositório apontando para um caminho sensível, tipicamente .git/config do próprio repositório; em seguida chama a API PutContents referenciando esse caminho como se fosse um arquivo normal, enviando conteúdo em base64. O servidor resolve o link e grava o conteúdo no destino real. Não há necessidade de exploração de memória ou payload binário — é abuso de lógica de validação de caminho para converter uma primitiva de 'escrita de arquivo dentro do repo' em escrita arbitrária, escalada depois para execução de comando via configuração/hooks Git processados pelo servidor.
A presença no catálogo KEV da CISA confirma exploração ativa observada. A pesquisa da Wiz referenciada no pull request de correção do próprio projeto relata centenas de instâncias Gogs expostas publicamente já comprometidas, compatível com campanha de varredura e exploração automatizada contra instâncias com registro aberto de usuários.
Como se proteger
Atualizar para uma versão do Gogs que já incorpore o commit 553707f3fd5f68f47f531cfcff56aa3ec294c6f6 (branch main), que adiciona a verificação hasSymlinkInPath antes de qualquer escrita via PutContents. As fontes consultadas não trazem o número de release exato em que esse commit foi publicado — confirme no changelog/notas de release do projeto antes de considerar corrigido.
Há um pull request adicional (#8078), ainda em revisão com pedido de mudanças do mantenedor em janeiro de 2026, propondo hardening mais amplo (resolução de symlinks com filepath.EvalSymlinks e validação centralizada num pacote pathutil) para cobrir casos como symlinks encadeados ou relativos que escapem do diretório do repositório. Isso sugere que o fix inicial pode não eliminar todos os vetores de bypass — acompanhe o merge desse PR antes de assumir cobertura completa.
Controles compensatórios caso a atualização não seja imediata: restringir ou desabilitar o autorregistro de usuários e a criação livre de repositórios (a falha depende de o atacante controlar conteúdo/commits de um repositório); revisar permissões de escrita em instâncias públicas; monitorar chamadas PUT para /api/v1/repos/*/contents/* de contas não totalmente confiáveis. Bloquear apenas o acesso à API REST não resolve, pois a criação do symlink malicioso ocorre via git push comum, e não pela própria API.