La confusión de dependencias en Maven y la solución mediante el archivo settings.xml

Ya están disponibles los parches de php2shell (CVE-2026-109618 y CVE-2026-109619) para PHP en fin de vida útil. Dado que las respuestas del departamento de ventas están tardando más de lo habitual debido a la elevada demanda, la forma más rápida de obtener los paquetes parcheados es comprar ELS para Runtimes en línea (se abre en una pestaña nueva). Lee las preguntas frecuentes sobre los parches

Ir directamente al resumen generado por IA de esta entrada del blog

  • Resume esta entrada con Perplexity
  • Resume esta publicación con Gemini

Principales conclusiones

  • En el caso de las versiones fijas, Maven consulta los repositorios por orden y toma las coordenadas del primero que las tenga.
  • El propio POM de una dependencia puede añadir repositorios a tu compilación, y, por defecto, nada lo impide.
  • A mirrorOf Esta línea protege el lado de Maven, pero tu gestor de repositorios aún tiene que mantener los repositorios públicos fuera de tu espacio de nombres.

Muchas empresas que trabajan con Java cuentan con un settings.xml Nadie lo ha tocado en años. Funciona. Las compilaciones se resuelven, la integración continua (CI) está en verde, nadie lo abre. De todos modos, merece la pena echarle un vistazo. Ese archivo determina de dónde procede cada artefacto, y lo que codifica suele ser más permisivo de lo que el equipo cree. Una compilación puede estar a solo una declaración de repositorio mal situada de resolver una coordenada interna fuera de la Internet pública. Esa brecha es la confusión de dependencias de Maven, y funciona de forma diferente a como lo hace en npm y pip. Para las versiones fijas, Maven no compara los números de versión. Compara a qué repositorio recurre primero tu compilación.

Por qué la confusión de dependencias en Maven funciona de forma diferente a como lo hace en npm y pip

Comparación entre la versión más alta de pip y la resolución ordenada de Maven en casos de confusión de dependencias
El pip puede apuntar a varios índices a la vez, mediante --index-url y --extra-index-url, y a continuación selecciona la versión más alta que cumpla el requisito entre todas ellas. Publicar internal-utils 99.0.0 está disponible públicamente y tiene prioridad sobre un paquete interno con el mismo nombre. npm se comporta de forma diferente. Un paquete se resuelve a partir de un único registro, sea cual sea el configurado para su ámbito, o del público si no existe ninguna asignación de ámbito. El ataque a npm funciona porque el paquete interno nunca se asignó a un registro privado, por lo que el cliente solo se comunica con el público, y no porque npm agregue y elija la versión más alta. Maven no funciona así para una versión fija. Resuelve la versión a partir del gráfico de dependencias primero, y luego busca exactamente ese groupId:artifactId:version, la coordenada GAV. Publicar una versión superior no tiene ningún efecto por sí sola, ya que nadie la solicita. Consulta los repositorios en el orden de repositorio, primero la configuración, luego la jerarquía POM del proyecto, después los POM de dependencias, y elige el primero que contenga el artefacto.

Resolver Norma de selección Lo que necesita un atacante
pip La versión más alta en todos los índices configurados Un número de versión más alto, una vez que ambos índices estén incluidos en el ámbito
npm Registro configurado para el ámbito del paquete; público por defecto No hay asignación de ámbito ni de registro para el paquete interno, además de una publicación pública con el mismo nombre.
Maven, versión corregida Primer repositorio de la lista que contiene el GAV exacto Tus coordenadas exactas, además de la posición anterior
Maven, rango de versiones Versión más alta según los metadatos agregados Un número de versión más alto
Maven, SNAPSHOT Los metadatos asocian la versión base a una compilación con marca de tiempo, según lo establecido en la política de pedidos y actualizaciones. Publicar el acceso a un repositorio consultado

El caso de la versión fija es el más habitual, y es el que determina cómo se lleva a cabo la corrección. El orden importa, la coincidencia exacta de coordenadas importa, pero la inflación de versiones es irrelevante. Si un repositorio público precede a tu repositorio interno y tus coordenadas existen allí, se obtiene la copia pública. Maven Central complica la versión básica de este proceso. Publicar bajo un espacio de nombres implica demostrar el control del dominio correspondiente mediante un registro TXT de DNS, o de la cuenta correspondiente para io.github espacios de nombres de estilos, para que nadie reclame com.yourcompany solo porque nunca lo hayas registrado. El verdadero riesgo reside en otros lugares: espacios de nombres que no controlas, espacios de nombres cuyo dominio subyacente caducó sin que te dieras cuenta y fue adquirido por otros, repositorios con normas de publicación menos estrictas que las de Central, y todos los repositorios que declare un POM en tu árbol. JitPack compila proyectos Git compatibles bajo demanda, y un POM de dependencias puede añadirlo a tu conjunto de repositorios sin que tú lo declares. Sus coordenadas siguen al host y a la cuenta de Git, por lo que no es un campo abierto, pero es un repositorio en el que nunca decidiste confiar. Los rangos de versiones y los SNAPSHOT son donde sí se aplica la agregación de versiones. Los rangos hacen que Maven fusione maven-metadata.xml entre repositorios y seleccionar la más alta, lo que vuelve a poner sobre la mesa la posibilidad de un secuestro basado en la versión. Las instantáneas (SNAPSHOTs) conllevan un riesgo relacionado, ya que los metadatos asocian la versión base a una compilación con marca de tiempo y cualquier repositorio del conjunto puede modificar esa asociación. Cuidado: Los rangos parecen ofrecer flexibilidad y se comportan como una dependencia sin fijar con alcance entre repositorios. Fija versiones exactas y deja que el gestor del repositorio controle las actualizaciones.

Lo que tu archivo «settings.xml» le está diciendo realmente a Maven

A varias manzanas de settings.xml afectar a la resolución o a sus credenciales. <mirrors> redirige las solicitudes, <profiles> puede añadir repositorios, <activeProfiles> decide cuáles son aplicables, y <servers> proporciona autenticación. El más importante es <mirrors>, porque un espejo con el diseño adecuado anula cualquier declaración de repositorio que haya en cualquier otro lugar. Esa es la parte de la solución que corresponde a Maven. Aún hay que indicar al gestor de repositorios que no sirva tu espacio de nombres interno desde repositorios públicos, lo cual se tratará en la siguiente sección.

<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 todas las solicitudes al repositorio se dirigen a esa URL, independientemente de lo que declare cualquier POM. Eso es lo que quieres. Esto es lo que, en cambio, contienen muchos archivos.

espejoDe valor Interceptaciones Período de inscripción abierto
central Solo Maven Central Cada dos repositorios declarados
external:* Repositorios externos localhost y file:// repositorios
*,!jitpack Todo menos JitPack JitPack, a propósito
* Todo Nada

Solo duplicación central Es un error fácil de cometer, porque parece correcto. Abarca el repositorio en el que todo el mundo piensa, pero hace que cada repositorio declarado en un POM apunte a su propia URL. Averigua cuál es el tuyo.

mvn help:effective-settings

Esto combina la configuración global y la del usuario, y muestra lo que Maven está utilizando realmente, incluida la activación del perfil. Ejecútalo tanto en un agente de integración continua como en un ordenador portátil, ya que pueden haber diferencias entre ambos.

La inyección transitiva de repositorios que nadie configuró

Una dependencia transitiva que añade un repositorio desconocido a una compilación de Maven
Esto es lo que te pilla desprevenido Desarrolladores Java que no han salido a buscarlo. La propia dependencia POM puede declarar repositorios, y Maven los respeta. Basta con añadir una biblioteca para que se añada un repositorio a tu conjunto de resoluciones. Se trata de un comportamiento documentado, que existe desde hace años, y no hay ninguna configuración predeterminada que lo impida. Por lo tanto, es posible que tu compilación esté consultando repositorios de los que nunca has oído hablar, declarados por una dependencia transitiva a cuatro niveles de profundidad, en una URL que nadie ha revisado.

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

Esto muestra la lista que genera tu propia jerarquía POM, incluidos los elementos principales y los perfiles. Lo que no se muestra es todo aquello que aportan los POM de las dependencias, ya que esos repositorios se incorporan al conjunto en el momento de la resolución, en lugar de fusionarse con tu POM. Para tener una visión completa, observa una compilación real.

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

Las líneas «Repositories» indican el conjunto que Maven ha utilizado para las dependencias y los complementos, y las líneas «Using mirror» muestran qué declaraciones se han redirigido. Al ejecutar esto, pueden aparecer repositorios que nadie haya añadido a propósito. Una mirada a la realidad: El hecho de que Maven respete los repositorios declarados por tus dependencias no es una vulnerabilidad, y no va a desaparecer. Es una característica anterior a que nadie pensara en los ataques a la cadena de suministro, y <mirrorOf>*</mirrorOf> Es la forma estándar, a nivel de configuración, de impedir que esas declaraciones lleguen a sus URL originales. Hay un pequeño inconveniente más. <pluginRepositories> es un bloque independiente de <repositories>, y un espejo con * cubre ambas cosas, mientras que los servidores espejo específicos de un repositorio normalmente no lo hacen. Los complementos se ejecutan con acceso completo a la JVM, lo que les confiere mayores privilegios que cualquier otro elemento de la ruta de clases de tu entorno de ejecución.

Comprobar qué elementos de tu compilación ya están almacenados en caché

La caché es menos «sencilla» de lo que su reputación sugiere. Maven almacena los artefactos en ~/.m2/repository, y el gestor de repositorios locales mejorado de Maven Resolver registra de qué repositorio remoto procede cada descarga. Si se solicita ese artefacto en una compilación posterior en la que el repositorio de origen no se encuentra dentro del ámbito, Resolver trata la copia almacenada en caché como si no existiera y vuelve a buscarlo en los repositorios que se encuentren dentro del ámbito en ese momento. Ese seguimiento sirve como control y como registro documental. Maven escribe esos datos de origen junto a cada artefacto.

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

Esa lista recoge archivos de seguimiento sin ninguna referencia al ID de tu espejo. Tómatelo como una clasificación aproximada más que como la procedencia de cada artefacto, ya que un mismo archivo puede abarcar varios artefactos y las instalaciones locales registran un origen vacío. Un ID desconocido significa que se resolvió bajo una configuración de repositorio diferente, por lo que merece la pena investigarlo. En el caso de tus coordenadas más importantes, comprueba si existen públicamente.

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

Un valor de 200 significa que Central tiene contenido en esa ruta de groupId y artifactId. Si esperabas que fuera privado, averigua qué hay allí y quién es el titular de la reclamación verificada del espacio de nombres. Consejo profesional: programa comprobaciones como esta para tus coordenadas internas importantes y dirígelas a los demás repositorios públicos a los que puedan acceder tus compilaciones, donde las normas sobre espacios de nombres son más flexibles. Merece la pena detectar primero cualquier publicación inesperada en las coordenadas en las que confías.

Cómo bloquear tus propias coordenadas en el gestor de repositorios

La ordenación de grupos de Maven falla de forma silenciosa, mientras que una regla de exclusión falla y se cierra.
Reparación settings.xml dirige todas las solicitudes a través de una URL, pero no determina qué hace esa URL a continuación. Un administrador que gestiona un grupo que incluye tanto un repositorio interno alojado como un proxy central sigue teniendo que tomar una decisión. Hay dos configuraciones importantes en este caso. La primera es el orden. En Nexus Repository, los miembros del grupo se buscan por orden y prevalece la primera coincidencia, por lo que los repositorios internos alojados tienen prioridad sobre el proxy central. Artifactory también resuelve los repositorios virtuales por orden. La prioridad interna significa que tus coordenadas se resuelven internamente incluso cuando existen otras iguales de forma pública. La segunda es un bloqueo total de tus propios patrones de coordenadas en el proxy central. Nexus Repository lo hace con reglas de enrutamiento, Artifactory con patrones de exclusión en el repositorio remoto o, mejor aún, en el repositorio virtual que lo agrega. En cualquier caso, una solicitud de com/yourcompany/** nunca llega a la Internet pública. Ese segundo control evita los errores. El orden depende de que la configuración sea correcta: un bloqueo explícito en tu espacio de nombres falla y queda cerrado.

Controlar ¿En qué falla? Se mantiene intacto tras una reordenación de grupos
mirrorOf establecer en * Cerrado, las compilaciones fallan estrepitosamente N/A
Pedidos grupales: primero los internos Abre, en silencio No
Regla de exclusión en el proxy central Cerrado, la resolución no prospera Sí
Salida restringida desde los agentes de compilación Cerrado, la resolución no prospera Sí

La regla de exclusión y la restricción de salida convierten la política en una medida de cumplimiento. Se producen desviaciones en la configuración, las imágenes base se heredan de otro equipo y siempre hay alguien que añade un repositorio para desbloquear un lanzamiento de viernes. En cuanto al tráfico de artefactos, se debe establecer por defecto el rechazo de la salida desde los agentes de compilación y añadir a la lista de permitidos el gestor de repositorios aprobado, lo que impide que Maven acceda a repositorios públicos arbitrarios. Bloquear un único nombre de host de Central no es suficiente, ya que Maven accede a Central bajo más de un nombre y los POM de dependencias pueden introducir hosts completamente diferentes. El enrutamiento y el bloqueo determinan de dónde proceden los artefactos. Ninguno de los dos evalúa si el artefacto es seguro. Un JAR es un resultado de la compilación, y nada exige que coincida con el repositorio de código fuente al que enlaza el proyecto. El escaneo no subsana esa brecha, ya que los escáneres inspeccionan lo que ya se ha generado. Recompilar paquetes a partir de código fuente verificado en un entorno controlado te proporciona una procedencia independiente en lugar de confiar en un binario opaco, y cuando la compilación de origen es reproducible, puedes comparar los resultados directamente.

Gradle cuenta con mejores funciones básicas para esto

Gradle gestiona el ámbito de los repositorios mejor que Maven, así que es mejor utilizar sus funciones nativas en lugar de trasladar los hábitos de Maven. El filtrado de contenido restringe las coordenadas que puede servir un repositorio. Introduce esa configuración en dependencyResolutionManagement en settings.gradle.kts, donde ese mismo bloque también puede impedir que los subproyectos declaren los suyos propios.

// 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 tu espacio de nombres se resuelve únicamente a partir del repositorio interno, sin consultar ninguna otra fuente. Eso es confusión de dependencias cerrado por construcción, en lugar de por orden. Fíjate en el anclaje de esa expresión regular, ya que un simple com\.yourcompany.* encaja perfectamente com.yourcompanyevil, precisamente el «casi accidente» para el que está diseñado. FAIL_ON_PROJECT_REPOS y, si algún subproyecto declara la suya propia, la compilación falla, de modo que la decisión se mantiene en un solo archivo. Maven no tiene un equivalente en una sola línea, aunque no carece de soluciones. El plugin Enforcer permite bannedRepositories La regla analiza los repositorios de la sesión de compilación y puede funcionar como una lista de permitidos. Consejo de experto: Combinar exclusiveContent con Gradle verificación de dependencias. El filtrado determina qué repositorio puede proporcionar una coordenada, y los metadatos de verificación comparan los artefactos con las sumas de comprobación esperadas y, cuando está habilitado, con las firmas de confianza. Juntos garantizan el enrutamiento y la integridad, algo que ninguna configuración de Maven por sí sola consigue. Los cambios en las dependencias, como los SNAPSHOT, quedan fuera de este proceso, lo que constituye una razón más para fijar las versiones.

El archivo settings.xml de Gap no se puede cerrar

Todo lo anterior resuelve la confusión de dependencias de Maven en la capa de enrutamiento: la correcta mirrorOf valor, ordenación de grupos, reglas de exclusión, controles de salida. Nada de eso responde a la siguiente pregunta: si el artefacto es seguro una vez que llega desde el lugar correcto. Eso es lo que SecureChain para lo que está diseñado. Sustituye la resolución pública de Maven Central por una alternativa verificada y recompilada a partir del código fuente, que examina cada componente durante la resolución de dependencias en lugar de analizar los artefactos una vez que se han incorporado al sistema. Las nuevas vulnerabilidades (CVE) se corrigen de forma continua, y la cobertura no finaliza al término de la vida útil del producto. Descubre qué SecureChain para Java cubiertas, o solicitar una demostración frente a tu propia versión.

PREGUNTAS FRECUENTES

¿Qué es la confusión de dependencias de Maven?

Se trata de un ataque en el que una compilación resuelve una coordenada interna a partir de un repositorio público en lugar de hacerlo a partir del repositorio interno. En el caso de las versiones fijas, la vulnerabilidad se debe al orden efectivo de los repositorios —primero la configuración, luego la jerarquía POM y, por último, los POM de dependencias— y no a la inflación de versiones.

¿Maven selecciona la versión más alta de entre todos los repositorios?

No es así en el caso de las versiones fijas. Maven determina la versión a partir del grafo de dependencias y, a continuación, busca esa coordenada exacta en el primer repositorio que la contenga. Los rangos y las versiones SNAPSHOT sí se comparan entre repositorios, por lo que las versiones exactas son más seguras.

¿Qué valor se debe asignar a «mirrorOf»?

Configurarlo en *, que redirige todas las solicitudes relacionadas con el repositorio a través de tu gestor de repositorios, independientemente de lo que declare cualquier POM. Al configurarlo en central solo intercepta Maven Central y deja que los repositorios declarados en los archivos POM de los proyectos o de las dependencias se resuelvan directamente.

¿Puede una dependencia añadir un repositorio a mi compilación?

Sí. Maven tiene en cuenta los repositorios declarados en el archivo POM de una dependencia, por lo que una dependencia transitiva puede añadir uno a tu conjunto de resolución. Un espejo configurado en * impide que Maven se ponga en contacto con ellos a través de sus URL originales.

¿Cómo puedo comprobar qué repositorios utiliza mi compilación de Maven?

Ejecutar mvn help:effective-settings para la fusión de ajustes y la activación del perfil, mvn help:effective-pom para la lista que genera tu jerarquía POM, y mvn -X dependency:resolve para ver el conjunto que se utilizó en una construcción real.

¿Es seguro cifrar las contraseñas del archivo settings.xml?

No contra nadie que pueda leer el sistema de archivos. El legado de Maven 3 cifrado de contraseñas almacena una contraseña maestra en el disco, que puede recuperar cualquier persona que tenga el archivo de configuración de seguridad. Maven 4 añade un distribuidor configurable que puede obtener la clave maestra de una variable de entorno o, en su lugar, de un agente GPG, aunque quien posea dicha clave seguirá descifrando todos los valores de settings.xml. En cualquier caso, introduce las credenciales de un almacén de secretos real en la integración continua (CI).

Resumen
La confusión de dependencias en Maven y la solución mediante el archivo settings.xml
Nombre del artículo
La confusión de dependencias en Maven y la solución mediante el archivo settings.xml
Descripción
La gestión de las dependencias en Maven funciona de forma diferente a como lo hace en npm o pip. El orden de los repositorios, los servidores espejo y las reglas de los espacios de nombres determinan tu exposición.
Autor
Nombre del editor
TuxCare
Logotipo de la editorial

Únase a más de 4.500 profesionales de Linux y el código abierto.

2 veces al mes. Sin spam.

Índice
Obtenga las respuestas de seguridad de código abierto que necesita

Únase a más de 4.500 profesionales de Linux y el código abierto.

2 veces al mes. Sin spam.