Confusão de dependências no Maven e a correção no arquivo settings.xml

Os patches do php2shell (CVE-2026-109618 e CVE-2026-109619) para o PHP em fim de vida (EOL) já estão disponíveis. Como as respostas do atendimento de vendas estão mais demoradas do que o normal devido à alta demanda, a maneira mais rápida de obter os pacotes corrigidos é adquirir o ELS para Runtimes on-line (abre em uma nova aba). Leia as perguntas frequentes sobre os patches

Vá direto para um resumo gerado por IA desta postagem do blog

  • Resuma esta postagem com o Perplexity
  • Resuma esta postagem com o Gemini

Principais conclusões

  • Para versões fixas, o Maven consulta os repositórios em ordem e obtém suas coordenadas do primeiro que as tiver.
  • O próprio POM de uma dependência pode adicionar repositórios à sua compilação, e, por padrão, nada impede que isso aconteça.
  • A mirrorOf Essa linha restringe o lado do Maven, mas seu gerenciador de repositórios ainda precisa manter os repositórios públicos fora do seu namespace.

Muitas equipes de Java corporativo têm um settings.xml Ninguém mexe nisso há anos. Funciona. As compilações são bem-sucedidas, a CI está verde, ninguém abre o arquivo. Mesmo assim, vale a pena dar uma olhada. Esse arquivo determina de onde vem cada artefato, e o que ele codifica costuma ser mais flexível do que a equipe imagina. Uma compilação pode estar a apenas uma declaração de repositório mal posicionada de resolver uma coordenada interna fora da internet pública. Essa lacuna é a confusão de dependências do Maven, e ela funciona de maneira diferente do que no npm e no pip. Para versões fixas, o Maven não compara números de versão. Ele compara qual repositório sua compilação consulta primeiro.

Por que a confusão de dependências no Maven funciona de maneira diferente do npm e do pip

Comparação entre a versão mais alta do pip e a resolução ordenada do Maven em casos de conflito de dependências
O pip pode ser direcionado a vários índices ao mesmo tempo, por meio de --index-url e --extra-index-url, e, em seguida, seleciona a versão mais alta que atenda ao requisito entre todas elas. Publicar internal-utils 99.0.0 publicamente e tem prioridade sobre um pacote interno com o mesmo nome. O npm se comporta de maneira diferente. Um pacote é resolvido a partir de um único registro, seja aquele configurado para seu escopo, seja o público, caso não exista mapeamento de escopo. O ataque ao npm funciona porque o pacote interno nunca foi restrito a um registro privado; assim, o cliente se comunica apenas com o registro público, e não porque o npm agrega e seleciona a versão mais alta. O Maven não funciona dessa maneira para uma versão fixa. Ele resolve a versão a partir do gráfico de dependências primeiro, depois procura exatamente esse groupId:artifactId:version, a coordenada GAV. Publicar uma versão mais recente por si só não tem efeito algum, pois não há nenhuma solicitação para ela. Ele consulta os repositórios no ordem do repositório, primeiro as configurações, depois a hierarquia do POM do projeto, em seguida os POMs de dependências, e seleciona o primeiro que contiver o artefato.

Resolver Regra de seleção O que um atacante precisa
pip Versão mais alta em todos os índices configurados Um número de versão maior, uma vez que ambos os índices estejam no escopo
npm Registro configurado para o escopo do pacote; público por padrão Não há mapeamento de escopo ou de registro para o pacote interno, além de uma publicação pública com o mesmo nome
Maven, versão corrigida Primeiro repositório na ordem que contenha o GAV exato Suas coordenadas exatas, além da posição anterior
Maven, intervalo de versões Versão mais recente entre os metadados agregados Um número de versão maior
Maven, SNAPSHOT Os metadados associam a versão base a uma compilação com registro de data e hora, sujeita à política de pedidos e atualizações Publicar acesso a um repositório consultado

O caso da versão fixa é o mais comum, e é ele que determina como você deve proceder. A ordem é importante, a correspondência exata das coordenadas é importante, e a inflação de versões é irrelevante. Se um repositório público vier antes do seu repositório interno e suas coordenadas existirem lá, você receberá a cópia pública. O Maven Central dificulta a versão simplificada disso. Publicar sob um namespace significa comprovar o controle do domínio correspondente por meio de um registro TXT de DNS, ou da conta correspondente para io.github espaços de nomes de estilos, para que ninguém reivindique com.yourcompany apenas porque você nunca o registrou. A verdadeira exposição está em outro lugar: namespaces que você não controla, namespaces cujo domínio associado expirou discretamente e foi adquirido por terceiros, repositórios com regras de publicação mais flexíveis do que as do Central e todos os repositórios declarados por um POM na sua árvore. O JitPack compila projetos Git compatíveis sob demanda, e um POM de dependência pode inseri-lo em seu conjunto de repositórios sem que você precise fazer uma declaração própria. Suas coordenadas seguem o host e a conta do Git, portanto não é um campo aberto, mas é um repositório no qual você nunca escolheu confiar. Intervalos de versão e SNAPSHOTs são onde a agregação de versões se aplica. Intervalos fazem o Maven mesclar maven-metadata.xml em todos os repositórios e selecionar a versão mais alta, o que volta a colocar em jogo o risco de sequestro baseado na versão. Os SNAPSHOTs apresentam um risco relacionado, já que os metadados mapeiam a versão base para uma compilação com registro de data e hora, e qualquer repositório do conjunto pode alterar esse mapeamento. Cuidado: Os intervalos parecem oferecer flexibilidade e funcionam como uma dependência não fixada com alcance entre repositórios. Fixe versões exatas e deixe que o gerente do repositório controle as atualizações.

O que seu arquivo settings.xml está realmente dizendo ao Maven

A alguns quarteirões de settings.xml afetar a resolução ou suas credenciais. <mirrors> redireciona as solicitações, <profiles> pode adicionar repositórios, <activeProfiles> decide quais se aplicam, e <servers> fornece autenticação. O mais importante é <mirrors>, porque um espelho com o padrão certo substitui todas as declarações de repositório em todos os outros locais. Essa é a parte da correção relacionada ao Maven. Ainda é preciso configurar o gerenciador de repositórios para que ele não forneça seu namespace interno a partir de repositórios públicos, o que será abordado na próxima seção.

<mirrors>
  <mirror>
    <id>internal-repo</id>
    <name>Internal Repository Manager</name>
    <url>https://nexus.example.com/repository/maven-public/</url>
    <mirrorOf>*</mirrorOf>
  </mirror>
</mirrors>

<mirrorOf>*</mirrorOf> significa que toda solicitação ao repositório é direcionada para essa URL, independentemente do que qualquer POM declare. É isso que você quer. Veja o que muitos arquivos contêm, em vez disso.

valor do espelho Interceptações Folhas abertas
central Apenas no Maven Central Todos os demais repositórios declarados
external:* Repositórios externos localhost e file:// repositórios
*,!jitpack Tudo, exceto o JitPack JitPack, deliberadamente
* Tudo Nada

Apenas espelhamento central É um erro comum, porque parece correto. Ele abrange o repositório que todos têm em mente – e faz com que cada repositório declarado em um POM seja direcionado para sua própria URL. Descubra qual é o seu caso.

mvn help:effective-settings

Isso combina as configurações globais com as do usuário e exibe o que o Maven está realmente utilizando, incluindo a ativação do perfil. Execute-o tanto em um agente de CI quanto em um laptop, já que as configurações podem variar entre os dois.

A injeção transitiva de repositório que ninguém configurou

Uma dependência transitiva que adiciona um repositório desconhecido a uma compilação do Maven
É isso que dá errado Desenvolvedores Java que não foram procurar. A própria dependência O POM pode declarar repositórios, e o Maven as respeita. Basta adicionar uma biblioteca para que ele possa incluir um repositório no seu conjunto de resoluções. Esse é um comportamento documentado, que já existe há anos, e não há nenhuma configuração padrão que o impeça. Portanto, sua compilação pode estar consultando repositórios dos quais você nunca ouviu falar, declarados por um dependência transitiva quatro níveis de profundidade, em uma URL que ninguém verificou.

mvn help:effective-pom | grep -A 8 '<repository>'

Isso mostra a lista gerada pela sua própria hierarquia de POMs, incluindo os POMs pai e os perfis. O que fica de fora é tudo o que um POM de dependência contribui, já que esses repositórios são adicionados ao conjunto no momento da resolução, em vez de serem incorporados ao seu POM. Para ter uma visão completa, observe uma compilação real.

mvn -X dependency:resolve 2>&1 | grep -E 'Using mirror|Repositories \(' | sort -u

As linhas “Repositories” indicam o conjunto que o Maven utilizou para dependências e plug-ins, e as linhas “Using mirror” mostram quais declarações foram redirecionadas. A execução desse comando pode revelar repositórios que ninguém adicionou conscientemente. Uma olhada na realidade: O fato de o Maven respeitar os repositórios declarados por suas dependências não é uma vulnerabilidade e não vai deixar de existir. Isso já existia antes mesmo de alguém pensar em ataques à cadeia de suprimentos, e <mirrorOf>*</mirrorOf> Essa é a maneira padrão, no nível das configurações, de impedir que essas declarações acessem suas URLs originais. Mais um detalhe. <pluginRepositories> é um bloco separado de <repositories>, e um espelho com * abrange ambos, enquanto os espelhos específicos de repositórios normalmente não. Os plug-ins são executados com acesso total à JVM, o que lhes confere privilégios maiores do que qualquer outro elemento no classpath de execução.

Verificando o que sua compilação já armazenou em cache

O cache é menos simples do que sua reputação sugere. O Maven armazena artefatos em ~/.m2/repository, e o gerenciador de repositórios locais aprimorado do Maven Resolver registra de qual repositório remoto cada download se originou. Se esse artefato for solicitado em uma compilação posterior em que o repositório de origem não esteja no escopo, o Resolver trata a cópia armazenada em cache como ausente, realizando uma nova resolução por meio dos repositórios que estiverem no escopo naquele momento. Esse rastreamento serve como controle e como registro documental. O Maven grava esses dados de origem ao lado de cada artefato.

find ~/.m2/repository -name '_remote.repositories' \
  -exec grep -L 'internal-repo' {} +

Essa lista apresenta arquivos de rastreamento sem nenhuma referência ao ID do seu espelho. Considere-a como uma triagem preliminar, e não como uma proveniência por artefato, já que um único arquivo pode abranger vários artefatos e as instalações locais registram uma origem vazia. Um ID desconhecido significa que ele foi resolvido sob uma configuração de repositório diferente, o que vale a pena investigar. Para suas coordenadas mais importantes, verifique se elas estão disponíveis publicamente.

curl -s -o /dev/null -w "%{http_code}\n" \
  https://repo.maven.apache.org/maven2/com/yourcompany/billing-core/

Um valor 200 significa que o Central possui conteúdo nesse caminho de groupId e artifactId. Se você esperava que fosse privado, descubra o que está lá e quem detém a reivindicação verificada do namespace. Dica profissional: programe verificações como essa para suas coordenadas internas importantes e direcione-as para os outros repositórios públicos aos quais suas compilações têm acesso, onde as regras de namespace são mais flexíveis. Vale a pena identificar primeiro qualquer publicação inesperada nas coordenadas nas quais você confia.

Bloqueando suas próprias coordenadas no Gerenciador de Repositórios

A ordenação de grupos no Maven falha silenciosamente, enquanto uma regra de exclusão falha com o status “fechada”
Reparo settings.xml encaminha todas as solicitações por meio de uma única URL, mas não determina o que essa URL faz em seguida. Um gerente responsável por um grupo que abrange tanto um repositório hospedado internamente quanto um proxy Central ainda precisa fazer uma escolha. Duas configurações são importantes nesse contexto. A primeira é a ordem. No Nexus Repository, os membros do grupo são pesquisados em ordem e a primeira correspondência prevalece; portanto, os repositórios internos hospedados têm prioridade sobre o proxy central. O Artifactory também resolve repositórios virtuais em ordem. A prioridade interna significa que suas coordenadas são resolvidas internamente, mesmo quando as mesmas existem publicamente. A segunda é um bloqueio total de seus próprios padrões de coordenadas no proxy central. O Nexus Repository faz isso com regras de roteamento, o Artifactory com padrões de exclusão no repositório remoto ou, melhor ainda, no repositório virtual que o agrega. De qualquer forma, uma solicitação para com/yourcompany/** nunca chega à internet pública. Esse segundo controle protege contra erros. A ordem depende de a configuração permanecer correta — um bloqueio explícito no seu namespace resulta em “fechado”.

Controle Como dá errado? Permanece inalterado após uma reordenação de grupo
mirrorOf definir como * Encerrado, as compilações apresentam falhas evidentes N/A
Pedidos em grupo: prioridade para os internos Abra, em silêncio Não
Regra de exclusão no proxy central Encerrado, a moção foi rejeitada Sim
Saída restrita a partir dos agentes de compilação Encerrado, a moção foi rejeitada Sim

A regra de exclusão e a restrição de saída transformam a política em ação. Ocorrem desvios na configuração, imagens base são herdadas de outra equipe e sempre há alguém que adiciona um repositório para liberar um lançamento na sexta-feira. Para o tráfego de artefatos, defina como padrão a negação de saída dos agentes de compilação e coloque o gerenciador de repositórios aprovado na lista de permissões, o que impede que o Maven acesse repositórios públicos arbitrários. Bloquear um único nome de host do Central não resolve, já que o Maven acessa o Central por mais de um nome e os POMs de dependência podem introduzir hosts totalmente diferentes. O roteamento e o bloqueio determinam de onde vêm os artefatos. Nenhum dos dois avalia se o artefato é seguro. Um JAR é um resultado da compilação, e nada exige que ele corresponda ao repositório de origem ao qual o projeto está vinculado. A verificação não preenche essa lacuna, já que os verificadores inspecionam o que já foi gerado. Recompilar pacotes a partir de código-fonte verificado em um ambiente controlado oferece uma proveniência independente, em vez de confiança em um binário opaco; e, quando a compilação upstream for reproduzível, você poderá comparar os resultados diretamente.

O Gradle oferece funções básicas mais adequadas para isso

O Gradle lida melhor com o escopo dos repositórios do que o Maven; portanto, use seus recursos nativos em vez de transferir os hábitos do Maven para ele. A filtragem de conteúdo restringe quais coordenadas um repositório pode disponibilizar. Coloque essa configuração em dependencyResolutionManagement em settings.gradle.kts, onde esse mesmo bloqueio também pode impedir que os subprojetos declarem os seus próprios.

// settings.gradle.kts
dependencyResolutionManagement {
  repositoriesMode = RepositoriesMode.FAIL_ON_PROJECT_REPOS
  repositories {
    exclusiveContent {
      forRepository {
        maven { url = uri("https://nexus.example.com/repository/internal/") }
      }
      filter { includeGroupByRegex("com\\.yourcompany(\\..*)?") }
    }
    maven { url = uri("https://nexus.example.com/repository/maven-public/") }
  }
}

exclusiveContent significa que seu namespace é resolvido apenas a partir do repositório interno, sem consultar nenhuma outra fonte. Isso é confusão de dependências fechado por construção, e não por ordem. Observe a ancoragem nessa expressão regular, pois um simples com\.yourcompany.* combina perfeitamente com.yourcompanyevil, exatamente o tipo de acidente que esteve prestes a acontecer e que ele foi projetado para evitar. FAIL_ON_PROJECT_REPOS e, então, interrompe a compilação se algum subprojeto declarar o seu próprio, mantendo a decisão em um único arquivo. O Maven não possui um equivalente de uma linha, embora não esteja indefeso. O plugin Enforcer’s bannedRepositories A regra verifica os repositórios da sessão de compilação e pode funcionar como uma lista de permissões. Dica de quem conhece: Combinar exclusiveContent com o Gradle verificação de dependências. A filtragem determina qual repositório pode fornecer uma coordenada, e os metadados de verificação comparam os artefatos com as somas de verificação esperadas e, quando ativadas, com assinaturas confiáveis. Juntos, eles garantem o roteamento e a integridade, algo que nenhuma configuração isolada do Maven consegue fazer. Dependências em constante mudança, como as versões SNAPSHOT, ficam fora desse processo — mais um motivo para fixar as versões.

O arquivo settings.xml do Gap não consegue ser fechado

Tudo o que foi mencionado acima resolve a confusão de dependências do Maven na camada de roteamento: a correta mirrorOf valor, ordenação de grupos, regras de exclusão, controles de saída. Nada disso responde à próxima pergunta: se o artefato é seguro uma vez que chega do local correto. É isso que SecureChain foi desenvolvido para isso. Ele substitui a resolução pública do Maven Central por uma alternativa verificada e recompilada a partir do código-fonte, analisando cada componente durante a resolução de dependências, em vez de verificar os artefatos após seu envio. Novas vulnerabilidades (CVEs) são corrigidas continuamente, e a cobertura não termina no fim do ciclo de vida. Veja o que SecureChain para Java capas, ou solicitar uma demonstração contra a sua própria versão.

Perguntas frequentes

O que é a confusão de dependências no Maven?

Trata-se de um ataque em que uma compilação resolve uma coordenada interna a partir de um repositório público, em vez de usar o repositório interno. Para versões fixas, a vulnerabilidade decorre da ordem efetiva dos repositórios — configurações, seguida pela hierarquia do POM e, por fim, pelos POMs de dependências —, e não da inflação de versões.

O Maven seleciona a versão mais alta entre os repositórios?

Não se aplica a versões fixas. O Maven determina a versão a partir do gráfico de dependências e, em seguida, localiza essa coordenada exata no primeiro repositório que a possua. Intervalos e SNAPSHOTs são comparados entre repositórios, e é por isso que versões exatas são mais seguras.

Para que valor deve ser definido o `mirrorOf`?

Defina como *, que encaminha todas as solicitações de repositório por meio do seu gerenciador de repositórios, independentemente do que qualquer POM declare. Ao configurá-lo para central intercepta apenas o Maven Central e permite que os repositórios declarados nos arquivos POM do projeto ou das dependências sejam resolvidos diretamente.

Uma dependência pode adicionar um repositório à minha compilação?

Sim. O Maven considera os repositórios declarados no POM de uma dependência; portanto, uma dependência transitiva pode adicionar um deles ao seu conjunto de resolução. Um espelho configurado para * impede que o Maven acesse esses arquivos em suas URLs originais.

Como faço para verificar quais repositórios minha compilação do Maven utiliza?

Correr mvn help:effective-settings para configurações combinadas e ativação do perfil, mvn help:effective-pom para a lista gerada pela sua hierarquia POM, e mvn -X dependency:resolve para ver o conjunto utilizado em uma construção real.

É seguro criptografar senhas no arquivo settings.xml?

Não contra ninguém que consiga ler o sistema de arquivos. O legado do Maven 3 criptografia de senha armazena uma senha mestra no disco, que pode ser recuperada por qualquer pessoa que tenha o arquivo de configurações de segurança. Maven 4 adiciona um despachador configurável que pode obter a chave mestra a partir de uma variável de ambiente ou de um agente GPG, embora quem possuir essa chave ainda decifre todos os valores em settings.xml. De qualquer forma, insira as credenciais de um repositório de segredos real na integração contínua (CI).

Resumo
Confusão de dependências no Maven e a correção no arquivo settings.xml
Nome do artigo
Confusão de dependências no Maven e a correção no arquivo settings.xml
Descrição
A confusão com dependências no Maven funciona de maneira diferente do que no npm ou no pip. A ordem dos repositórios, os espelhos e as regras de namespace determinam sua exposição.
Autor
Nome da editora
TuxCare
Logotipo da editora

Junte-se a mais de 4.500 profissionais de Linux e código aberto!

2 vezes por mês. Sem spam.

Índice
Obtenha as respostas sobre segurança de código aberto de que você precisa

Junte-se a mais de 4.500 profissionais de Linux e código aberto!

2 vezes por mês. Sem spam.