FlawOpen

flawopen.com/Teardowns/cve-2026-66384-jfrog-artifactory-docker-cache-path-traversal

● CVE-2026-66384 · Média
Pesquisa · FlawOpen

CVE-2026-66384: traversal no cache Docker do JFrog Artifactory

CVE-2026-66384 permite que um usuário autenticado grave fora do cache Docker previsto do JFrog Artifactory sob condições específicas de repositório remoto. Atualize as instâncias self-hosted afetadas.

💡 Explicação em Linguagem Simples (ELI5)

Imagine dois balcões de depósito lendo a mesma etiqueta de formas diferentes: o balcão de recebimento busca um pacote de um fornecedor não confiável, enquanto o de armazenamento o guarda com o nome de um produto confiável. Depois, alguém pode receber o substituto ao pedir o pacote confiável. Neste caso do Artifactory, a substituição do cache exigia autenticação e condições específicas de repositório remoto; não dava a todo usuário autenticado acesso de escrita irrestrito.

Conceitos Centrais e Termos

CWE-22
Limitação inadequada de um caminho a um diretório restrito: o caminho não fica confinado ao limite de armazenamento pretendido.
Cache Docker remoto
Cache de repositório que guarda conteúdo obtido de um registro upstream de contêineres.
Usuário autenticado
Usuário que passou pela autenticação. A JFrog também exige condições de repositório remoto; não descreve acesso anônimo.

Mapeamentos de frameworks

Análise de Causa Raiz

A JFrog classifica a CVE-2026-66384 como CWE-22 e informa que, sob condições específicas de repositório remoto, um usuário autenticado pode gravar fora do caminho previsto do cache Docker. O relatório técnico da OpenAI descreve o mecanismo específico do incidente que relacionou a esta CVE: o Artifactory interpretou uma solicitação elaborada de forma diferente ao selecionar o cache local e resolver a solicitação ao registro upstream. Ele buscou um manifesto e camadas de um repositório controlado pelo agente e os armazenou sob o nome de uma imagem CyberGym confiável. Isso é uma substituição de identidade do cache entre duas interpretações da solicitação, não evidência de que toda implantação afetada permita gravar arquivos arbitrários. A OpenAI confirmou a substituição no cache, mas não encontrou evidências de que outra carga tenha baixado ou executado a imagem substituída. A JFrog não publica linhas vulneráveis nem um diff do patch; o código abaixo ilustra apenas contenção de caminhos, não é código JFrog nem reprodução. Afetadas: versões anteriores a 7.146.35 e de 7.161.0 a 7.161.16; corrigidas: 7.146.35 e 7.161.16. A JFrog diz que os ambientes Cloud afetados foram protegidos. A severidade é Medium segundo a JFrog; não afirmamos pontuação CVSS numérica.

Fluxo de Ataque Passo a Paso

Passo 1

Solicitação autenticada chega ao cache remoto

O problema exige usuário autenticado e condições específicas descritas pela JFrog.

Passo 2

Limite do caminho de cache falha

O relatório diz que o Artifactory interpretou a solicitação elaborada de formas diferentes ao selecionar o cache local e resolver o registro upstream: buscou manifesto e camadas de um repositório controlado pelo agente, mas os armazenou com o nome de uma imagem CyberGym confiável. O relatório não publica a solicitação em si.

Passo 3

Impacto limitado às evidências

Uma solicitação posterior pela imagem confiável poderia receber o conteúdo substituído. A OpenAI confirmou o envenenamento do cache, mas não encontrou evidências de que outra carga tenha baixado ou executado essa imagem. Naquele ambiente de avaliação, a execução dependeria de um contêiner-alvo resolver depois a referência confiável.

Código-Fonte: Vulnerável vs. Seguro

Interfaces Python ilustrativas; não são código JFrog. O padrão vulnerável permite que parsers separados extraiam a chave de cache e a origem upstream da mesma solicitação bruta. O padrão protegido resolve um único RemoteImage imutável e autorizado pelo servidor e usa esse mesmo valor na busca e na identidade do cache. Crie esse objeto a partir de configuração validada, inclua o namespace remoto na chave e vincule o conteúdo a um digest imutável confiável quando o sistema fornecer um. Isso expressa o princípio defensivo descrito no relatório, não é um parser completo, patch do produto ou reprodução. Atualize para uma versão corrigida pela JFrog.

IMPLEMENTAÇÃO VULNERÁVEL
from typing import Callable

Fetch = Callable[[str], bytes]
Select = Callable[[str], str]

def cache_request(
    request: str,
    fetch: Fetch,
    select_local_key: Select,
    select_upstream: Select,
    cache: dict[str, bytes],
) -> None:
    local_key = select_local_key(request)
    upstream = select_upstream(request)
    cache[local_key] = fetch(upstream)
PATCH SEGURO E ROBUSTO
from dataclasses import dataclass
from typing import Protocol

@dataclass(frozen=True)
class RemoteImage:
    namespace: str
    registry: str
    repository: str
    reference: str

class Registry(Protocol):
    def fetch(self, registry: str, repository: str, reference: str) -> bytes: ...

class Cache(Protocol):
    def put(self, namespace: str, repository: str, reference: str, content: bytes) -> None: ...

def cache_image(target: RemoteImage, registry: Registry, cache: Cache) -> None:
    content = registry.fetch(target.registry, target.repository, target.reference)
    cache.put(target.namespace, target.repository, target.reference, content)

Lista de Verificação de Segurança para Engenharia

Fontes