CiberLab
Logotipo Ciência Embarcada Ciência Embarcada
Relatório técnico de análise de vulnerabilidade

CVE-2026-85706

Leitura arbitrária de arquivos sem autenticação no GitLab pela API de commits

Uma falha de severidade máxima no GitLab CE/EE permite que qualquer pessoa, sem conta e sem senha, leia arquivos do servidor. O ponto de entrada é a API de criação de commits: um auxiliar de upload roda antes da checagem de autenticação e usa um parâmetro controlado pelo atacante como caminho absoluto de arquivo, sem confinamento. Ao codificar uma única letra da palavra commits na URL, o atacante engana o roteamento do componente de front-end e ainda alcança o código vulnerável no Rails. Um erro de reparse transforma a resposta de erro em um canal que reflete o conteúdo do arquivo. Basta que exista um projeto público na instância. A falha está no catálogo de vulnerabilidades exploradas da CISA e foi observada sob sondagem ativa na internet dias após a correção.

Objeto analisado GitLab CE/EE, CVE-2026-85706
Severidade avaliada Crítica
Classificação TLP:CLEAR
Base de evidência OSINT verificado
Data de emissão 29 de setembro de 2026
Versão 1.0

00Sumário

  1. 01Sumário executivo
  2. 02Identificação do objeto analisado
  3. 03Contexto técnico: a arquitetura do GitLab
  4. 04Mecanismo da vulnerabilidade e causa raiz
  5. 05Exploração e canais de vazamento
  6. 06Impacto e alvos de alto valor
  7. 07Exploração ativa e exposição
  8. 08Detecção
  9. 09Mitigação e resposta a incidentes
  10. 10Indicadores de comprometimento
  11. 11Limitações da análise
  12. 12Referências
Achado central

O auxiliar que grava o corpo de um upload de commit roda antes da checagem de autenticação e lê um parâmetro controlado pelo atacante, file.path, como caminho absoluto, sem qualquer confinamento ao repositório [1] [2]. Um desvio no roteamento, obtido ao codificar uma letra de commits para %63ommits, impede o componente de front-end (Workhorse) de sobrescrever esse parâmetro, enquanto o Rails ainda decodifica e roteia para o código vulnerável [1]. A leitura acontece sem login. Basta existir um projeto público na instância, condição comum em servidores de código [1] [3].

01Sumário executivo

Em 10 de setembro de 2026, a GitLab publicou correções para o CVE-2026-85706, uma vulnerabilidade de leitura arbitrária de arquivos sem autenticação nas edições Community (CE) e Enterprise (EE) do seu servidor de código [3] [4]. A falha recebeu a pontuação máxima na escala CVSS, 10.0, e foi classificada como travessia de caminho (CWE-22, Path Traversal) [4] [5]. O ponto de entrada é a API de criação de commits de um repositório: uma requisição sem autenticação alcança um trecho de código que lê um arquivo do servidor a partir de um caminho absoluto fornecido pelo atacante [1] [2].

10.0 pontuação CVSS oficial, severidade máxima (crítica) [4] [5]
0 credenciais necessárias: exploração totalmente sem autenticação [1] [4]
1 requisição HTTP basta para ler um arquivo do servidor [1]
KEV no catálogo de exploração ativa da CISA desde 11 de setembro de 2026 [6] [7]

A causa raiz combina três defeitos [1] [2]. Primeiro, o auxiliar de upload que grava o corpo da requisição roda antes da chamada authenticate!, então uma requisição anônima já alcança a lógica de leitura de arquivo. Segundo, esse auxiliar usa o parâmetro file.path diretamente como caminho absoluto, sem restringi-lo ao diretório do repositório. Terceiro, um desvio no roteamento, obtido ao codificar na URL uma letra da palavra commits, faz o componente de front-end (GitLab-Workhorse) ignorar a rota e não sobrescrever file.path, ao passo que o Rails ainda decodifica a URL e entrega a requisição ao código vulnerável [1].

O impacto vai além da simples leitura. Arquivos como gitlab-secrets.json e database.yml guardam as chaves e as credenciais que sustentam a instância, e a leitura deles converte um acesso anônimo em comprometimento potencial de todo o servidor, com posterior acesso autenticado [1] [2]. A falha entrou no catálogo KEV (Known Exploited Vulnerabilities) da CISA em 11 de setembro de 2026, um dia após a correção, e empresas de segurança observaram sondagens contra servidores expostos já nesse mesmo período [6] [7] [8].

A única solução completa é atualizar para as versões corrigidas: 19.3.2, 19.2.6, 19.1.8 e, nas ramificações mais antigas, 19.0.9 e 18.11.12 [3] [4]. Como a leitura sem autenticação pode ter exposto segredos antes da correção, toda instância que esteve acessível na internet deve tratar as credenciais e chaves como comprometidas e girá-las [2] [8].

02Identificação do objeto analisado

Natureza da evidência

Este relatório não executou o exploit contra uma instância própria do CiberLab nem realizou engenharia reversa do código-fonte do GitLab. A descrição técnica da causa raiz e da cadeia de exploração vem da prova de conceito publicada pela equipe EQSTLab da SK Shieldus [1], e os metadados da vulnerabilidade (versões, pontuação, situação de exploração) vêm dos comunicados oficiais e de fontes de inteligência abertas verificadas [3] [4] [5] [6] [7] [8]. As regras de detecção derivadas nas seções 8 devem ser homologadas no ambiente de cada organização antes do uso em bloqueio.

Tabela 1. Ficha técnica da vulnerabilidade CVE-2026-85706
CampoValor
IdentificadorCVE-2026-85706
Produto afetadoGitLab Community Edition (CE) e Enterprise Edition (EE), autogerenciado [4]
Classe de fraquezaCWE-22 (Improper Limitation of a Pathname to a Restricted Directory, Path Traversal) [5]
Componente vulnerávelAPI de commits do repositório, auxiliar de upload de corpo da requisição [1] [2]
Ponto de entradaPOST /api/v4/projects/:id/repository/commits [1]
Vetor de ataqueRede, sem autenticação, sem interação do usuário [1] [4]
Pontuação CVSS v3.110.0 (Crítica) [4] [5]
Pré-condiçãoAo menos um projeto público na instância [1] [3]
Descoberta e reportePesquisador com o codinome "s3ntago", via programa de recompensas da GitLab no HackerOne [7]
Correção10 de setembro de 2026 (19.3.2, 19.2.6, 19.1.8); backport em 23 de setembro de 2026 (19.0.9, 18.11.12) [3] [7]
Situação de exploraçãoExplorada ativamente; catálogo KEV da CISA desde 11 de setembro de 2026 [6] [7] [8]
Tabela 2. Versões afetadas e corrigidas
RamificaçãoVersões vulneráveisPrimeira versão corrigida
18.7 a 18.1118.7 até anterior a 18.11.12 [4]18.11.12 (23 de setembro de 2026) [7]
19.019.0 até anterior a 19.0.9 [4]19.0.9 (23 de setembro de 2026) [7]
19.119.1 até anterior a 19.1.8 [4]19.1.8 (10 de setembro de 2026) [3]
19.219.2 até anterior a 19.2.6 [4]19.2.6 (10 de setembro de 2026) [3]
19.319.3 até anterior a 19.3.2 [4]19.3.2 (10 de setembro de 2026) [3]
Nota sobre o intervalo de versões

A prova de conceito da EQSTLab descreve o alvo como as versões 18.7 a 19.1.7, 19.2.0 a 19.2.5 e 19.3.0 a 19.3.1, e monta o laboratório sobre a 19.1.7 [1]. O comunicado oficial da GitLab abrange também a ramificação 19.0, que recebeu correção por backport em 23 de setembro [4] [7]. A tabela 2 segue os intervalos oficiais, mais abrangentes.

03Contexto técnico: a arquitetura do GitLab

Para entender por que uma única letra codificada na URL derruba a proteção, é preciso conhecer o caminho que uma requisição percorre dentro do GitLab [1]. Diferentemente de uma aplicação web simples, o GitLab não é um único processo: a requisição atravessa camadas com responsabilidades distintas, e a falha nasce justamente na costura entre duas dessas camadas.

3.1GitLab-Workhorse: o porteiro que manuseia uploads

O GitLab-Workhorse é um proxy reverso escrito em Go que fica na frente da aplicação Rails [1]. Sua função é aliviar o servidor de aplicação das tarefas pesadas de entrada e saída, principalmente o manuseio de uploads e downloads de grandes volumes, como os pacotes de dados do Git [1]. Quando uma requisição corresponde a uma rota de upload conhecida, o Workhorse intercepta o corpo da requisição, grava-o em um arquivo temporário e substitui os parâmetros do upload por valores que apontam para esse arquivo controlado pelo sistema, entre eles o file.path [1].

Esse comportamento é uma proteção implícita: em condições normais, o Workhorse é quem define o file.path, apontando para o arquivo temporário que ele mesmo gravou, e não o cliente [1]. A aplicação Rails, portanto, sempre esperaria receber um caminho seguro, gerado internamente.

3.2Rails e o auxiliar de upload de corpo

Atrás do Workhorse roda a aplicação principal, em Ruby on Rails, servida pelo Puma [1]. A API de commits do GitLab (POST /api/v4/projects/:id/repository/commits) aceita, em fluxos legítimos, o envio de conteúdo de arquivo no corpo da requisição para compor um novo commit [1] [2]. Para isso, existe um auxiliar que processa esse corpo de upload, lendo o arquivo indicado por file.path [1] [2].

3.3find_project! e a superfície anônima

Nem toda a API do GitLab exige autenticação. A resolução do projeto, feita pela rotina find_project!, permite acesso anônimo a projetos de visibilidade pública [1]. Assim, se a instância tem ao menos um projeto público, um atacante sem conta consegue endereçar a API de commits daquele projeto e fazer a requisição chegar ao servidor de aplicação [1] [3]. Servidores de código quase sempre hospedam algum repositório público, o que torna essa pré-condição trivial na prática [1].

04Mecanismo da vulnerabilidade e causa raiz

A vulnerabilidade resulta de três defeitos que, isolados, seriam inofensivos, mas que juntos abrem a leitura irrestrita de arquivos [1] [2]. Esta seção percorre cada um deles na ordem em que a requisição maliciosa os aciona.

4.1Primeiro defeito: leitura de arquivo antes da autenticação

O auxiliar que processa o corpo do upload de commit é executado antes da chamada authenticate! no fluxo do controlador [1] [2]. Isso significa que a operação de acesso ao arquivo, uma verificação de existência seguida da leitura (File.exist? e depois File.read), acontece antes de o GitLab decidir se o solicitante tem permissão para estar ali [1]. Uma requisição anônima já dispara o acesso ao sistema de arquivos. A correção oficial, introduzida a partir da 19.1.8, insere justamente a chamada authenticate! antes desse auxiliar, de modo que a requisição não autenticada é recusada antes de tocar o disco [1].

4.2Segundo defeito: caminho absoluto sem confinamento

Ao ler o corpo do upload, o auxiliar toma o valor de params['file.path'] e o utiliza como caminho absoluto de arquivo, sem verificar se ele permanece dentro do diretório do repositório ou de qualquer área confinada [1] [2]. Não há canonicalização, não há verificação de prefixo, não há bloqueio de caminhos que apontem para fora da árvore esperada [1]. Se o atacante controlar esse valor, ele controla exatamente qual arquivo do servidor será lido, de /etc/passwd a /flag.txt [1].

4.3Terceiro defeito: o desvio de rota no Workhorse

Resta o obstáculo descrito na seção 3.1: em condições normais, o Workhorse sobrescreve file.path com o caminho do arquivo temporário que ele gravou, apagando o valor do atacante [1]. O truque que resolve isso para o atacante é uma dessincronização de roteamento entre o Workhorse (Go) e o Rails (Ruby) [1].

O atacante codifica na URL a primeira letra da palavra commits, trocando o caractere c pela sua forma percent-encoded %63 [1]:

Caminho da requisiçãoDerivado de [1]
/api/v4/projects/1/repository/%63ommits

O casador de rotas do Workhorse compara a cadeia literal e não reconhece %63ommits como a rota de upload de commits. Por isso ele não intercepta o corpo, não grava arquivo temporário e, decisivo, não sobrescreve o file.path [1]. O Rails, por sua vez, decodifica a URL segundo a norma HTTP, converte %63 de volta em c, reconhece a rota commits e entrega a requisição ao controlador vulnerável, com o file.path do atacante intacto [1]. É a diferença de interpretação da mesma URL entre dois componentes que quebra a proteção.

Dessincronização de análise, não bug de um único componente

Nenhum dos dois componentes está, isoladamente, errado ao decodificar a URL: o Workhorse casa rotas por texto literal e o Rails decodifica o percent-encoding, ambos comportamentos defensáveis. O perigo mora na diferença entre eles. Ao proteger uma aplicação atrás de um proxy que reescreve requisições, nunca presuma que o proxy e a aplicação leem a URL do mesmo jeito. Normalize a requisição em um único ponto antes de qualquer decisão de rota ou de segurança.

05Exploração e canais de vazamento

Com os três defeitos alinhados, o atacante já consegue fazer o servidor ler o arquivo escolhido. Falta trazer o conteúdo de volta na resposta, e é aqui que entra o segundo truque do exploit [1].

5.1A requisição de exploração

A requisição completa combina o desvio de rota com os parâmetros de upload passados na query string, e declara o tipo de conteúdo como formulário urlencoded [1]:

HTTPRequisição bruta, transcrita de [1]
POST /api/v4/projects/1/repository/%63ommits?file=&file.path=/flag.txt&file.size=1&Content-Type=application/x-www-form-urlencoded HTTP/1.1
Host: alvo
Content-Length: 0
Connection: close

O parâmetro file.path aponta para o arquivo a ler, e Content-Type=application/x-www-form-urlencoded instrui o auxiliar a tratar o conteúdo lido como um formulário [1].

5.2O canal de vazamento pelo erro de reparse

Ao ver o tipo application/x-www-form-urlencoded, o auxiliar passa o conteúdo do arquivo que acabou de ler para o analisador de formulários do Rack, na função Rack::Utils.parse_nested_query(File.read(path)) [1]. O Rack então tenta interpretar os bytes do arquivo como se fossem pares de um formulário codificado [1].

Aqui está a engenhosidade do exploit: se o conteúdo do arquivo contém um caractere de porcentagem (%) que não seja seguido de dois dígitos hexadecimais, o Rack considera aquilo uma codificação inválida e lança um erro, cuja mensagem é invalid %-encoding (<trecho>) [1]. O trecho reproduzido nessa mensagem é justamente o conteúdo do arquivo, e ele reaparece verbatim no corpo da resposta HTTP 400 [1]. O atacante lê o arquivo do servidor simplesmente lendo a mensagem de erro.

5.3Dois canais: conteúdo e oráculo de existência

Esse mecanismo cria dois canais distintos de divulgação, e a diferença entre eles importa para o defensor avaliar o alcance real [1]:

  1. Divulgação de conteúdo: arquivos cujo conteúdo contém um % inválido têm o conteúdo refletido na resposta 400 [1]. Registros de aplicação (logs) frequentemente se enquadram, e arquivos de configuração e credenciais que embutem valores codificados na forma URL também [1] [2].
  2. Oráculo de existência: arquivos sem esse byte especial, como /etc/passwd, são lidos antes da autenticação, mas não têm conteúdo refletido: a resposta é um 401, que apenas confirma se o arquivo existe ou não [1]. Arquivos puramente hexadecimais ou em base64 caem nesse caso e retornam somente o oráculo [1].

A prova de conceito da EQSTLab automatiza os dois canais. No laboratório dela, o arquivo-bandeira é plantado com um % ao final justamente para acionar a reflexão [1]:

Saída do exploitTranscrito de [1]
[*] target   http://172.17.0.2
[*] endpoint /api/v4/projects/1/repository/%63ommits
[*] file.path /flag.txt
[+] arbitrary file read OK -> content of /flag.txt:
    EQST{gitlab_cve_2026_85706_arbitrary_file_read}%
[+] FLAG: EQST{gitlab_cve_2026_85706_arbitrary_file_read}

O exploit extrai o conteúdo com a expressão invalid %-encoding \((.*)\) sobre o corpo da resposta, e reconhece a ausência de arquivo pela mensagem local file not present, que serve para confirmar apenas que o ponto vulnerável foi alcançado [1].

06Impacto e alvos de alto valor

O valor de uma leitura arbitrária de arquivos depende inteiramente de o que existe no disco para ser lido. Num servidor GitLab, existe muito [1] [2].

6.1Segredos que sustentam a instância

A leitura alcança arquivos que guardam as chaves e as credenciais mestras do servidor [1] [2]:

Tabela 3. Arquivos de alto valor alcançáveis pela leitura
ArquivoConteúdo e consequência
gitlab-secrets.jsonChaves de criptografia da instância, usadas para cifrar tokens, variáveis de CI/CD e segredos armazenados. Sua leitura permite decifrar segredos e forjar sessões [1] [2].
database.ymlCredenciais de acesso ao banco de dados PostgreSQL do GitLab [1] [2].
Registros de aplicação (logs)Frequentemente contêm um % inválido, então têm conteúdo refletido pelo canal de vazamento. Podem expor tokens, parâmetros e caminhos internos [1] [2].
Configurações e credenciais diversasArquivos que embutem valores codificados na forma URL entram no canal de divulgação de conteúdo [1] [2].

6.2Da leitura anônima ao comprometimento total

A cadeia de consequências é direta [1] [2] [8]. A leitura sem autenticação expõe segredos; os segredos dão acesso autenticado ao GitLab; o acesso autenticado a um servidor de código dá acesso ao código-fonte, aos pipelines de CI/CD, às variáveis de ambiente e às credenciais de implantação que a organização guarda ali [2] [8]. Um servidor GitLab é, para muitas empresas, o centro do desenvolvimento e da entrega de software, o que faz dele um alvo de alto retorno e um ponto de partida para ataques à cadeia de suprimento de software [8].

A leitura de um único arquivo pode bastar

Não trate o incidente como "apenas leitura de arquivos". A leitura do gitlab-secrets.json entrega as chaves que cifram todos os outros segredos da instância. Uma única requisição bem-sucedida contra esse arquivo, se ele contiver o byte que aciona a reflexão, converte o acesso anônimo em controle sobre os segredos do servidor [1] [2].

07Exploração ativa e exposição

Diferente de muitas falhas divulgadas de forma teórica, o CVE-2026-85706 passou a ser sondado na internet quase imediatamente após a correção [6] [8]. A tabela a seguir consolida a linha do tempo pública [3] [6] [7] [8].

Tabela 4. Linha do tempo da divulgação e exploração
DataEvento
Antes da divulgaçãoFalha reportada pelo pesquisador "s3ntago" via programa de recompensas da GitLab no HackerOne [7]
10 de setembro de 2026GitLab publica as versões corrigidas 19.3.2, 19.2.6 e 19.1.8 e o comunicado de segurança [3]
11 de setembro de 2026Sondagens contra servidores GitLab expostos observadas na internet; CVE adicionado ao catálogo KEV da CISA [6] [8]
23 de setembro de 2026Correção retroportada para as ramificações mais antigas: 19.0.9 e 18.11.12 [7]

A inclusão no catálogo KEV da CISA significa que há evidência de exploração real, e não apenas potencial [6]. Para os órgãos federais civis dos Estados Unidos, essa inclusão impõe um prazo de correção obrigatório; para qualquer outra organização, é o sinal mais forte de que a correção não pode esperar pela próxima janela de manutenção [6] [7].

A janela entre a correção e a exploração ativa foi de cerca de um dia [3] [6] [8]. Isso reforça um ponto operacional: para vulnerabilidades de servidores de código expostos, o intervalo entre "há correção" e "há exploração em massa" é curto demais para depender de ciclos mensais de atualização.

08Detecção

A detecção segue da observação mais barata e abrangente para a mais específica: identificar as requisições de exploração na borda, depois nos registros da aplicação [1]. O padrão da requisição é distintivo e não aparece em uso legítimo do GitLab [1].

8.1Assinatura da requisição no registro de acesso

A marca mais confiável é a presença do percent-encoding na palavra commits dentro do caminho da API [1]. Nenhum cliente legítimo do GitLab escreve %63ommits; a rota normal é commits em texto claro [1]. Da mesma forma, uma requisição à API de commits que carregue um parâmetro file.path com um caminho absoluto do sistema (iniciado por /) é anômala [1].

Para servidores web e proxies que registram a URL requisitada, busque o padrão nos registros históricos e alerte em tempo real:

Expressão de busca (regex)Derivada de [1], não validada em produção
/api/v4/projects/[^/]+/repository/%[0-9a-fA-F]{2}ommits

8.2Regra Suricata para o tráfego HTTP

Para sensores de rede que inspecionam o tráfego HTTP antes da terminação TLS (por exemplo, atrás de um descarregador de TLS), a regra abaixo alerta o padrão de rota codificada combinado com o parâmetro de caminho absoluto [1]:

SuricataDerivada de [1], não validada em produção
alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"CIBERLAB GITLAB CVE-2026-85706 UNAUTH FILE READ ATTEMPT"; \
    flow:to_server,established; http.method; content:"POST"; \
    http.uri; content:"/repository/"; content:"ommits"; distance:0; content:"file.path="; \
    pcre:"/\/repository\/%[0-9a-f]{2}ommits/i"; \
    classtype:web-application-attack; sid:1000110; rev:1; \
    reference:cve,2026-85706; reference:url,ciberlab.seg.br/reports/gitlab-fileread;)

8.3Regra Sigma para os registros web

A regra Sigma a seguir opera sobre registros de proxy web ou de servidor web que exponham o campo da URI requisitada [1]:

Sigma, categoria webserverDerivada de [1], não validada em produção
title: Tentativa de Leitura Arbitraria de Arquivo no GitLab (CVE-2026-85706)
id: 5234914f-ec3a-473a-b4ca-6d22e88ad2ee
status: experimental
description: Detecta a rota commits com uma letra percent-encoded e o parametro file.path absoluto
author: Lucas Rayan Guerra (CiberLab)
references:
    - https://github.com/EQSTLab/CVE-2026-85706
    - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-85706
logsource:
    category: webserver
detection:
    selection_route:
        cs-uri-stem|re: '/api/v4/projects/[^/]+/repository/%[0-9a-fA-F]{2}ommits'
    selection_param:
        cs-uri-query|contains: 'file.path=/'
    condition: selection_route or selection_param
fields:
    - c-ip
    - cs-uri-stem
    - cs-uri-query
    - sc-status
falsepositives:
    - Desconhecidos em uso legitimo do GitLab
level: high
tags:
    - attack.initial_access
    - attack.t1190
    - attack.collection
    - attack.t1005

8.4Sinais de resposta e de acompanhamento

Além da requisição, dois sinais ajudam a distinguir tentativa de sucesso [1]. Respostas HTTP 400 da API de commits contendo a cadeia invalid %-encoding indicam que o canal de vazamento de conteúdo foi acionado, ou seja, que um arquivo foi lido e refletido [1]. Uma sucessão de requisições à API de commits com valores variados de file.path, partindo de um mesmo endereço sem autenticação, caracteriza a varredura de arquivos [1]. Após qualquer indício, revise os registros de acesso subsequentes em busca de autenticação bem-sucedida com credenciais que possam ter vazado (seção 9) [2] [8].

09Mitigação e resposta a incidentes

9.1Correção definitiva

A única solução completa é atualizar o GitLab autogerenciado para uma versão corrigida [3] [4]. A correção adiciona a verificação de autenticação antes do auxiliar de leitura, de modo que a requisição anônima é recusada antes de tocar o disco [1]:

Instâncias hospedadas no serviço gerenciado da GitLab (GitLab.com) e no GitLab Dedicated foram tratadas pela própria GitLab; a ação de atualização recai sobre as instalações autogerenciadas [4] [8].

9.2Contenção enquanto a atualização não é aplicada

Se a atualização imediata não for possível, reduza a superfície de ataque [2] [8]:

  1. Bloqueio no proxy ou WAF: recuse requisições POST e PUT às rotas */repository/commits* e */repository/files*, inclusive nas formas percent-encoded do caminho [1] [8].
  2. Restrição de acesso: coloque a instância atrás de SSO, VPN ou uma lista de endereços IP permitidos, removendo-a da exposição direta à internet [1] [8].
  3. Revisão de projetos públicos: a exploração exige ao menos um projeto público. Verifique se há projetos públicos realmente necessários; a contenção por remoção da visibilidade pública é possível, mas menos confiável do que a atualização, e não deve substituí-la [1] [3].

9.3Presunção de comprometimento e rotação de segredos

Como a leitura acontecia sem autenticação e sem registro de sessão, uma instância que esteve acessível na internet antes da atualização deve ser tratada sob a premissa de comprometimento (Assume Breach) [2] [8]. A correção fecha a porta, mas não desfaz o que já pode ter vazado [8].

  1. Gire os segredos da instância: regenere as chaves de gitlab-secrets.json e as credenciais do banco em database.yml, seguindo o procedimento oficial da GitLab para rotação de segredos [2] [8].
  2. Invalide sessões e tokens: encerre as sessões ativas e revogue tokens de acesso pessoal, tokens de projeto e de grupo, e chaves de implantação [2] [8].
  3. Gire os segredos de CI/CD: troque as variáveis de CI/CD, as credenciais de registro de contêineres e quaisquer segredos de implantação armazenados na instância [2] [8].
  4. Investigue acesso posterior: procure, nos registros, autenticações bem-sucedidas ou uso de tokens logo após qualquer tentativa de exploração identificada na seção 8 [8].

9.4Mapeamento de técnicas MITRE ATT&CK

A tabela alinha as ações da exploração ao framework MITRE ATT&CK for Enterprise, com IDs e nomes conferidos na base oficial [9]:

Tabela 5. Mapeamento de táticas e técnicas conforme MITRE ATT&CK
TécnicaNomeRelação com o caso
T1595 Active Scanning Sondagem em massa de servidores GitLab expostos após a divulgação [6] [8]
T1190 Exploit Public-Facing Application Exploração da API de commits do GitLab exposta à internet, sem autenticação [1] [4]
T1083 File and Directory Discovery Uso do oráculo de existência (resposta 401) para mapear arquivos no servidor [1]
T1005 Data from Local System Leitura de arquivos arbitrários do sistema de arquivos do servidor [1] [2]
T1552.001 Unsecured Credentials: Credentials In Files Extração de credenciais e chaves de gitlab-secrets.json e database.yml [1] [2]
T1078 Valid Accounts Reuso das credenciais e tokens vazados para obter acesso autenticado à instância [2] [8]

10Indicadores de comprometimento

Os indicadores desta vulnerabilidade são de comportamento, não de arquivo: a exploração usa apenas requisições HTTP legítimas na forma, e não deposita binários no servidor [1]. A tabela consolida os padrões a caçar nos registros e no tráfego [1].

Tabela 6. Indicadores de comprometimento e artefatos de detecção
TipoIndicadorSeveridadeContexto e ação
Vulnerabilidade CVE-2026-85706 Crítica Leitura arbitrária de arquivos sem autenticação no GitLab CE/EE. Atualize de imediato [3] [4].
Padrão de URL /repository/%63ommits Crítica Rota commits com a letra c percent-encoded; nenhum cliente legítimo a usa [1].
Padrão de URL /repository/%[0-9a-fA-F]{2}ommits Alta Forma geral do desvio de rota, cobrindo outras letras codificadas [1].
Parâmetro file.path=/<caminho absoluto> Alta Caminho absoluto do sistema na API de commits; anômalo em uso legítimo [1].
Resposta HTTP 400 com "invalid %-encoding" Crítica Indica leitura bem-sucedida com conteúdo refletido; provável exfiltração de arquivo [1].
Resposta HTTP "local file not present" Média Confirma que o ponto vulnerável foi alcançado com um caminho inexistente (sondagem) [1].
Arquivo-alvo gitlab-secrets.json, database.yml Crítica Alvos de maior valor; se acessados, presuma vazamento de segredos e gire tudo [1] [2].

11Limitações da análise

  1. Ausência de detonação em laboratório próprio: o CiberLab não construiu nem executou o ambiente vulnerável, nem rodou o exploit. A descrição da causa raiz e da cadeia de exploração vem da prova de conceito publicada pela EQSTLab [1], e os metadados vêm de fontes abertas verificadas [3] a [8].
  2. Fonte primária de terceiros: a análise técnica se apoia na prova de conceito da EQSTLab [1], que é a fonte mais detalhada disponível sobre o mecanismo. Não foi possível confirmar cada afirmação contra o código-fonte do GitLab nem contra o comunicado de segurança original, cujas páginas estavam inacessíveis a partir do ambiente de produção deste relatório.
  3. Datas de exploração aproximadas: as datas de sondagem ativa e de inclusão no catálogo KEV vêm de fontes secundárias de inteligência [6] [7] [8] e podem variar em um dia entre publicações. A data de correção (10 de setembro de 2026) e as versões corrigidas são as mais consistentes entre as fontes.
  4. Regras de detecção derivadas: as regras Suricata e Sigma da seção 8 foram deduzidas do padrão de exploração descrito na prova de conceito [1] e não foram testadas em redes de produção. Ajuste-as e homologue-as antes de qualquer uso em bloqueio.
  5. Alcance do canal de conteúdo: a divulgação de conteúdo depende de o arquivo conter um % inválido. Arquivos sem esse byte retornam apenas o oráculo de existência [1]. O alcance prático da exfiltração de um arquivo específico depende, portanto, do seu conteúdo, e não pode ser presumido universal.

12Referências

  1. [1] CVE-2026-85706: GitLab unauthenticated arbitrary file read PoC. EQSTLab (SK Shieldus), repositório oficial no GitHub. Fonte primária técnica: descrição da causa raiz, desvio de rota %63ommits, canal de vazamento por reparse urlencoded, ambiente de laboratório e exploit em Python. https://github.com/EQSTLab/CVE-2026-85706
  2. [2] GitLab CVE-2026-85706: Patch the File Read, Then Rotate What It Exposed. Hive Security, setembro de 2026. Análise de impacto e resposta, com ênfase na rotação de segredos após a exposição. https://hivesecurity.gitlab.io/blog/gitlab-cve-2026-85706-arbitrary-file-read-response/
  3. [3] GitLab Critical Patch Release: 19.3.2, 19.2.6, 19.1.8. GitLab, comunicado oficial de correção, 10 de setembro de 2026. Versões corrigidas e orientação de atualização. https://docs.gitlab.com/releases/patches/patch-release-gitlab-19-3-2-released/
  4. [4] CVE-2026-85706, GitLab Community and Enterprise Edition Path Traversal Vulnerability. CVEFeed, ficha da vulnerabilidade com versões afetadas e situação de exploração ativa. https://cvefeed.io/vuln/detail/CVE-2026-85706
  5. [5] CVE-2026-85706, CVSS 10 Critical. PSIRT.com, registro da vulnerabilidade com pontuação CVSS e classificação CWE-22. https://psirt.com/cve/CVE-2026-85706
  6. [6] GitLab CVE-2026-85706 Added to CISA KEV. SOCRadar, setembro de 2026. Confirmação da inclusão no catálogo de vulnerabilidades exploradas da CISA e da exploração observada. https://socradar.io/blog/gitlab-cve-2026-85706-cisa-kev/
  7. [7] CVE-2026-85706: Critical GitLab Path Traversal Flaw. SOC Prime, setembro de 2026. Crédito de descoberta, cronologia de correção e retroporte para as ramificações 19.0 e 18.11. https://socprime.com/blog/cve-2026-85706-critical-gitlab-path-traversal-flaw/
  8. [8] GitLab CVSS 10 File-Read Flaw Draws In-the-Wild Probes After Disclosure. The Hacker News, setembro de 2026. Cobertura da exploração ativa, do impacto sobre CI/CD e da resposta recomendada. https://thehackernews.com/2026/09/gitlab-cvss-10-file-read-flaw-draws-in.html
  9. [9] MITRE ATT&CK Enterprise. The MITRE Corporation, base STIX oficial (repositório attack-stix-data). Fonte dos IDs e nomes de técnica da tabela 5, conferidos em 29 de setembro de 2026. https://attack.mitre.org/

CVE-2026-85706, leitura arbitrária de arquivos sem autenticação no GitLab. Relatório técnico de análise de vulnerabilidade, versão 1.0, emitido em 29 de setembro de 2026.
Lucas Rayan Guerra, CiberLab, uma iniciativa do Ciência Embarcada.
Classificado TLP:CLEAR: distribuição livre, sem restrição de compartilhamento.