Saltar al contenido principal
onext technology
DevOps 4 septiembre 2026 - 18 min de lectura

Dependencias generadas por IA: la línea del pull request que nadie discute

Un review discute veinte líneas de lógica y aprueba sin un comentario la única que añade código de terceros, un mantenedor desconocido y una licencia que nadie ha leído. Con código generado esa línea aparece muchas más veces por semana — y sigue costando lo mismo mirarla que ignorarla.

Jordi García
Tech Lead en onext
Un ingeniero firma al anochecer la entrega de un palé de cajas selladas en el muelle de carga de una oficina y sólo levanta la tapa de la de arriba, como metáfora de las dependencias que entran con el código generado por IA

El informe OSSRA de 2026 auditó 947 bases de código de diecisiete sectores y dejó cuatro números en la misma página: los componentes open source por aplicación subieron un 30% en un año, los ficheros un 74%, la media de vulnerabilidades por base de código un 107%, y los conflictos de licencia aparecen ya en dos tercios de las auditorías frente al 56% del año anterior — el mayor salto interanual desde que existe el informe.

Ninguno de los cuatro habla del código que escribe tu equipo. Los cuatro hablan del código que tu equipo importa.

Esta pieza va de esa parte. No de si el asistente escribe buen código —de eso hablamos al rediseñar el review—, sino de las decisiones que toma además de escribirlo: qué librería usa, en qué versión, con qué licencia y con qué cadena de mantenedores detrás. Son decisiones con vida de años, se toman en un segundo y llegan al pull request disfrazadas de una línea.

La línea que nadie discute

Un diff es democrático de una forma que perjudica: todas las líneas ocupan lo mismo. Cambiar el nombre de una variable ocupa una línea. Añadir una dependencia ocupa una línea. La primera se discute en el review; la segunda entra sin comentarios, y es la que trae consigo un árbol de código que no ha abierto ninguno de los dos.

Las proporciones están medidas desde hace años y casi nadie las tiene presentes al aprobar. En el análisis de dependencias de Endor Labs, el 95% de las vulnerabilidades detectadas vive en dependencias transitivas —las que no elegiste tú, sino la que sí elegiste—; en aplicaciones Java, el 71% del código que acaba en la aplicación viene de componentes open source y, de todo ese código importado, se usa alrededor del 12%.

La asimetría de la que va todo lo demás: leer una línea de lógica cuesta lo mismo que leer una línea de dependencia, pero lo que hay detrás no se parece en nada. Una es una decisión reversible en cinco minutos; la otra incorpora un proveedor a vuestro producto, con su cadencia de parches, su licencia y sus propias dependencias. El review las trata igual porque el diff las muestra igual.

Con código generado, esa línea aparece muchas más veces. No porque el modelo sea temerario, sino porque su objetivo es resolver el problema que tiene delante, y traerse una librería es casi siempre la forma más corta de resolverlo. El resultado no es un fallo espectacular: es volumen. Y el volumen se cuela por donde el proceso no mira.

Tres modos de fallo, ordenados al revés de como se cuentan

Conviene separarlos antes de decidir dónde invertir, porque tienen frecuencias muy distintas y ninguno se arregla con el control del otro. Los ordeno de más ruidoso a más frecuente, que resulta ser el orden inverso al que ocupan en la conversación pública.

Modo Qué ocurre Cuánto ocurre
1 · El paquete que no existe El modelo recomienda un nombre inventado. Si alguien lo registra antes de que tú lo instales, ejecuta código en tu equipo y en tu pipeline Entre el 4,6% y el 6,1% de las referencias en los modelos frontera de 2026. Ningún ataque malicioso público documentado todavía
2 · El paquete que existe, en la versión equivocada La librería es real y la versión que propone arrastra vulnerabilidades ya publicadas. El código funciona y las pruebas pasan Entre el 36,7% y el 55,7% de las tareas acaban con al menos un CVE conocido en la versión especificada
3 · El paquete correcto que no debería estar ahí Licencia incompatible, duplicado de algo que ya teníais, o sin nadie dentro de casa que responda por él dentro de un año Dos tercios de las bases de código auditadas tienen conflictos de licencia. El resto no se mide casi nunca

El primero es el que sale en prensa; el tercero es el que os va a pasar esta semana

1 · El paquete que no existe

El trabajo de referencia es de Joseph Spracklen y su equipo, presentado en USENIX Security 2025. Generaron 576.000 muestras de código con dieciséis modelos y dos conjuntos de prompts, y comprobaron cada paquete referenciado contra los índices reales de PyPI y npm: 440.445 referencias, el 19,7%, apuntaban a paquetes que no existen, con 205.474 nombres únicos distintos. La tasa iba del 5,2% en modelos comerciales al 21,7% en modelos abiertos.

El titular es la tasa. Lo que convierte esto en un problema de seguridad, y no en una molestia, son otros dos hallazgos del mismo estudio, mucho menos citados.

El primero es la repetición. Un 43% de los nombres alucinados volvía a aparecer en las diez consultas repetidas; un 39% no se repetía ninguna vez. Esa bimodalidad es toda la diferencia: una alucinación que no se repite es ruido, y una que se repite siempre es una dirección postal. El atacante no necesita adivinar qué se va a inventar el modelo con tu compañero de equipo — le basta con preguntar diez veces y quedarse con lo estable.

El segundo es que no estamos ante un typosquatting. Sólo el 13,4% de los nombres inventados está a distancia de edición 1 o 2 de un paquete real. No son erratas de un nombre legítimo: son nombres nuevos, plausibles, del tipo que un desarrollador con prisa da por bueno porque suena exactamente a lo que necesitaba. Las defensas clásicas de los registros, pensadas para detectar nombres casi idénticos a uno popular, están mirando otra cosa.

En 2026 se ha replicado el estudio sobre cinco modelos frontera publicados entre octubre de 2025 y marzo de 2026, con 199.845 prompts emparejados de Python y JavaScript. La buena noticia es que la horquilla se comprime un orden de magnitud: todos los modelos evaluados quedan entre el 4,62% y el 6,10%. La mala llega después de la tasa: hay 127 nombres de paquete que los cinco modelos inventan de forma idéntica y, tras la divulgación coordinada con el equipo de seguridad de PyPI y con Socket, 53 seguían disponibles para registrar —41 en PyPI y 12 en npm— pese a las defensas que ya aplican los registros. Un único registro malicioso alcanzaría a la vez a usuarios de cinco proveedores distintos.

Es un preprint de un investigador independiente y no ha pasado revisión por pares; lo cito porque su metodología replica la del estudio de USENIX y porque la parte que más pesa —los 53 nombres libres— la validó Socket contra el registro, descartando seis falsos positivos que eran importaciones válidas de frameworks. Y conviene repetir lo que ellos mismos escriben, porque casi ningún artículo lo recoge: esto es superficie de ataque, no un ataque. No hay constancia pública de que ninguno de esos nombres se haya registrado con fines maliciosos.

El caso documentado de que la cadena se cierra de verdad sigue siendo un experimento. En diciembre de 2023, Bar Lanyado, investigador de Lasso Security, registró en PyPI un paquete llamado huggingface-cli —inofensivo— después de ver que los modelos lo recomendaban una y otra vez, cuando la herramienta real se instala de otra forma. En febrero de 2024, el README de instalación de un repositorio de Alibaba pedía instalar el suyo. En tres meses acumuló más de 15.000 descargas reales. Nadie lo atacó: simplemente, todo el mecanismo funcionó.

2 · El paquete que existe, en la versión equivocada

Este modo no da titulares y es diez veces más frecuente. La librería es real, conocida y perfectamente razonable. Lo que llega mal es la versión.

Endor Labs lo midió sobre más de 10.000 repositorios de GitHub y agentes de código en PyPI, npm, Maven y NuGet: sólo una de cada cinco versiones de dependencia recomendadas por un asistente era segura, entendiendo por segura que ni el paquete es inventado ni la versión arrastra vulnerabilidades conocidas. Entre el 44% y el 49% de las dependencias que los agentes importaban tenían vulnerabilidades ya publicadas.

El estudio que mejor explica por qué es de 2026, sobre diez modelos y mil tareas de programación reales: entre el 36,70% y el 55,70% de las tareas terminan con al menos un CVE conocido en la versión de librería que el modelo especifica, y entre el 62,75% y el 74,51% de esos CVE son de severidad crítica o alta. Todos los modelos convergen además en las mismas versiones problemáticas, lo que descarta el accidente y apunta a algo estructural.

El dato que ordena la conversación es el siguiente: entre el 72,27% y el 91,37% de esos CVE se habían publicado antes del corte de conocimiento del propio modelo. No es que el modelo no pudiera saberlo. Es que nada en la tarea que le diste le pedía mirarlo. El título del trabajo lo resume mejor que cualquier paráfrasis: código correcto, dependencias vulnerables.

La inversión que descoloca a los equipos

El control de moda de este año es el cooldown: no instalar una versión hasta que lleve publicada unos días. Tiene detrás un argumento sólido. En noviembre de 2025, William Woodruff revisó diez ataques de cadena de suministro de 2024 y 2025 —desde la puerta trasera de xz-utils hasta los incidentes de ultralytics, chalk, Nx o web3.js— y midió la ventana entre la publicación del paquete comprometido y su detección: en ocho de los diez fue de menos de una semana. Con siete días de espera se habrían evitado casi todos; con catorce, todos menos uno.

El ecosistema entero lo ha implementado en nueve meses. pnpm lo lleva desde la 10.16 de septiembre de 2025, Yarn desde la 4.10, Bun desde la 1.3 de octubre y npm desde la 11.10.0 de febrero de 2026; en Python, uv desde la 0.9.17 y pip desde la 26.0; y también Poetry, Bundler y el lado de registro de Cargo. Es probablemente el cambio de higiene más rápido que ha adoptado el ecosistema en una década.

Y aquí está la inversión: el cooldown protege del paquete demasiado nuevo, el que se publicó anteanoche con una carga maliciosa. El asistente de IA trae el problema contrario — el paquete demasiado viejo, la versión que era la habitual cuando se entrenó, con sus vulnerabilidades ya publicadas y documentadas. Un equipo que instala el cooldown y da la casilla por marcada ha cubierto el modo de fallo que menos le va a pasar. Son dos controles distintos y hacen falta los dos.

3 · El paquete correcto que no debería estar ahí

El tercer modo no es de seguridad, no tiene CVE y es el que va a aparecer en vuestro repositorio esta semana. Son dependencias reales, mantenidas y sin vulnerabilidades que, aun así, no deberían haber entrado.

Por licencia. Es el hallazgo más contundente del OSSRA de 2026 y el que menos se comenta: los conflictos de licencia pasaron del 56% a dos tercios de las bases auditadas en un solo año. La explicación que da el informe tiene dos mitades — más componentes por aplicación, y fragmentos generados a partir de fuentes con copyleft que llegan sin arrastrar su licencia. El desajuste de proceso está medido en la misma encuesta: el 76% de las organizaciones revisa el código generado buscando riesgos de seguridad, el 54% mira propiedad intelectual y licencias, y sólo el 24% revisa las cuatro dimensiones —seguridad, licencia, propiedad intelectual y calidad—. La revisión de propiedad intelectual se diseñó para un mundo en el que el código entraba a ritmo humano.

Por duplicación. Un generador resuelve el problema que tiene delante; no sabe que tres carpetas más allá ya hay una librería para eso, aprobada hace dos años. Es la misma ceguera estructural que hace que el código generado duplique en lugar de reutilizar, sólo que aplicada al catálogo de proveedores en vez de al código propio. Y donde una función duplicada es deuda, dos librerías que hacen lo mismo son dos superficies que parchear y dos criterios de actualización.

Por orfandad. La pregunta que rara vez se hace en un pull request: dentro de un año, cuando esta librería publique un cambio incompatible o deje de mantenerse, ¿quién de nosotros responde? Si la respuesta es «nadie», la dependencia entra igual, pero el equipo ha asumido una obligación que no ha registrado en ningún sitio.

Por qué el review no lo va a coger

Vale la pena decir por qué esto no se arregla pidiendo más rigor en la revisión, que es la respuesta refleja. Son tres razones y ninguna depende de la profesionalidad de nadie.

El coste de leer no distingue. El revisor invierte los mismos segundos en una línea trivial y en una decisión de cinco años, porque en el diff ocupan lo mismo y llegan mezcladas. Cuando el caudal de cambios se multiplica, lo primero que se pierde es aquello cuya pérdida no se nota.

Lo que entra no está en el pull request. El 95% de las vulnerabilidades vive en las dependencias transitivas, y de esas no hay ni una línea en el diff. Se aprueba una entrada en el fichero de bloqueo y llega un árbol entero.

No hay criterio escrito. Cuando alguien pregunta «¿de verdad necesitamos esta librería?», está aplicando su gusto personal, y por eso la pregunta se hace poco: incomoda y no tiene respaldo. En casi ningún equipo existe un documento que diga qué se puede importar, con qué licencias, desde qué versión mínima y con qué proceso de alta. Sin eso, el review de dependencias es una opinión frente a un compañero con prisa, y esa discusión la gana siempre la prisa.

Seis controles, y qué corta cada uno

Ninguno es nuevo ni caro. Lo que suele fallar no es la elección de herramienta, sino instalar dos y dar por cubierto lo que no cubren. La columna que importa es la segunda.

Control Qué modo corta Qué cuesta de verdad
Espejo del registro con lista de permitidos Modo 1, de raíz Montarlo son días. El coste está en la cola de altas: si tarda más de 48 horas, el equipo la rodea y el control deja de existir
Fichero de bloqueo con hashes e instalación reproducible Sustitución posterior Casi nada, y suele estar a medias: el fichero existe, pero el pipeline instala resolviendo de nuevo en vez de instalar exactamente lo bloqueado
Instalación sin ejecutar scripts Ejecución en el momento de instalar Una tarde de arreglar las tres dependencias que sí necesitan compilar, y documentarlas como excepción
Edad mínima de versión (7-14 días) Compromiso reciente del mantenedor Una línea de configuración, más la lista de excepciones para parches urgentes. No cubre el modo 2
Política de versión mínima aplicada al resolver Modo 2 Es el cambio con más fricción real: rompe builds el primer mes. A cambio, la versión vulnerable deja de instalarse en lugar de reportarse después
Licencia y dueño exigidos en el alta Modo 3 Cero euros y toda la resistencia cultural: obliga a que alguien ponga su nombre al lado de cada dependencia nueva

Los tres primeros son configuración; los tres últimos son decisiones de equipo, y por eso son los que faltan

Lo que sí cambia lo que propone el asistente

Hay un dato en el informe de Endor Labs que se lee como una nota técnica y es, en realidad, el argumento central: cuando el agente tiene conectadas herramientas de seguridad que puede consultar mientras decide, la proporción de recomendaciones de dependencia seguras pasa de en torno al 20% al 57%. Casi el triple, sin cambiar de modelo y sin pedirle a nadie que se esfuerce más.

Merece la pena leerlo despacio, porque desmonta la reacción habitual. El asistente no está incumpliendo vuestra política de dependencias: no la ha visto nunca. Cuando propone una librería y una versión, está reproduciendo lo que era razonable en el corpus con el que se entrenó, que es un promedio de internet de hace dos años. La lista de lo que ya usáis, las versiones mínimas aceptables, las licencias admitidas y el «para esto ya tenemos algo» no son disciplina que haya que exigir: son contexto que hay que darle.

Es exactamente el mismo movimiento que en la seguridad de los agentes: se deja de discutir con el modelo y se cambia lo que el modelo puede ver y hacer. En Spec-Driven Development ese artefacto tiene nombre y sitio — la constitución del proyecto, el documento de reglas inmutables que el agente lee antes de proponer nada. Una política de dependencias que vive en la cabeza del tech lead sirve para regañar; escrita en la constitución, cambia la primera propuesta.

Con una advertencia que también está en el dato: el 57% no es el 100%. Dar contexto al asistente reduce el volumen de lo que hay que atajar aguas abajo, no sustituye a los seis controles. La secuencia sensata es la contraria a la habitual: primero el espejo del registro y la instalación reproducible, que no dependen de que nadie se acuerde; después el contexto, que reduce el caudal; y sólo entonces las conversaciones de proceso, que ya llegan con muchos menos casos.

El inventario de un martes

No hace falta un programa para empezar, ni comprar nada. Hace falta el fichero de bloqueo, que ya tenéis versionado, y cuarenta minutos.

Se saca el historial de ese fichero de los últimos noventa días —el package-lock.json, el uv.lock, el poetry.lock, el pom.xml, el que os toque— y se lista qué dependencias nuevas entraron en ese periodo. A cada una, tres preguntas: quién la pidió, en qué pull request se discutió y si hoy se usa.

Lo interesante casi nunca es encontrar una dependencia peligrosa. Es ver cuántas filas tienen las tres casillas vacías. Ese número —la proporción de proveedores que entraron en vuestro producto sin que nadie decidiera nada— es lo que convierte esto de una intuición del tech lead en una cifra que se puede bajar el trimestre siguiente. Y a diferencia de casi todo lo que se mide en un equipo de desarrollo, se saca esta misma tarde y no admite discusión sobre la metodología.

Preguntas frecuentes

¿El paquete alucinado es un riesgo real o marketing de seguridad?

Es superficie de ataque demostrada y, hasta hoy, sin un incidente malicioso público que la aproveche. Conviene decirlo en ese orden. Spracklen y su equipo midieron 440.445 referencias a paquetes inexistentes sobre 576.000 muestras de código, y el trabajo de 2026 sobre modelos frontera encuentra 127 nombres que los cinco modelos evaluados inventan igual, de los cuales 53 seguían libres para registrar después de las defensas de PyPI y npm. Socket, que participó en la divulgación, deja escrito que no hay constancia de que ninguno se haya registrado con fines maliciosos. El único caso documentado de que esto llega al mundo real sigue siendo el experimento de Bar Lanyado: registró huggingface-cli en diciembre de 2023, en febrero de 2024 el README de un repositorio de Alibaba pedía instalarlo, y acumuló más de 15.000 descargas reales en tres meses con un paquete inofensivo.

¿Cómo se corta el paquete que no existe sin frenar al equipo?

Con un espejo del registro y una lista de nombres permitidos. Es el único control que ataca este modo de fallo en la raíz, porque un nombre inventado no está en el espejo y la instalación falla en el primer intento, en local, antes de llegar a nadie. El coste real no es técnico —montar un proxy de artefactos es cuestión de días— sino de proceso: alguien tiene que aprobar altas, y si esa cola tarda una semana el equipo la rodea. La regla que lo sostiene es que el alta tenga un plazo corto y un responsable con nombre, no que la lista sea larga.

Si la IA propone una versión con CVE conocido, ¿no lo coge el escáner que ya tenemos?

Lo coge tarde y con ruido, que en la práctica es no cogerlo. El escáner avisa después del merge, sobre un repositorio entero y mezclado con hallazgos de dependencias transitivas que nadie va a tocar esta semana. El hallazgo de Wang y su equipo sobre diez modelos y mil tareas es que entre el 36,70% y el 55,70% de las tareas acaban con al menos un CVE conocido en la versión especificada, y que entre el 72,27% y el 91,37% de esos CVE se habían publicado antes del corte de conocimiento del propio modelo. El control que cambia algo es una política de versión mínima aplicada en la resolución de dependencias: la versión vulnerable no se instala, en lugar de instalarse y reportarse.

¿Los cooldowns no retrasan las actualizaciones de seguridad?

Retrasan las actualizaciones, sí, y por eso se configuran con excepciones. El argumento a favor lo puso William Woodruff en noviembre de 2025 revisando diez ataques de cadena de suministro de 2024 y 2025: en ocho de los diez, la ventana entre publicar el paquete comprometido y detectarlo fue de menos de una semana; con siete días de espera se evitan casi todos y con catorce, todos menos uno. La contrapartida se gestiona con una lista de exclusión para parches urgentes, que pnpm trae desde el principio y npm todavía discute. Lo que no hay que esperar del cooldown es que cubra el otro modo de fallo: protege del paquete demasiado nuevo, no del demasiado viejo.

¿Qué pasa con la licencia del código y las dependencias que trae la IA?

Es la parte que menos se mira y la que peor envejece. El informe OSSRA de 2026, sobre 947 bases de código auditadas, encuentra conflictos de licencia en dos tercios de ellas frente al 56% del año anterior: el mayor salto interanual de su historia. La explicación que da es doble: más componentes por aplicación —un 30% más en un año— y fragmentos generados a partir de fuentes con copyleft que llegan sin su licencia detrás. El desajuste organizativo aparece en la misma encuesta: el 76% de las empresas revisa el código generado buscando riesgos de seguridad, sólo el 54% mira propiedad intelectual y licencias, y apenas el 24% revisa las cuatro dimensiones.

¿Por dónde empiezo esta semana sin montar un programa?

Por un inventario de cuarenta minutos sobre el fichero de bloqueo, que ya tenéis versionado. Se sacan las dependencias que entraron en los últimos noventa días con el historial de ese fichero, y a cada una se le hacen tres preguntas: quién la pidió, en qué pull request se discutió y si hoy se usa. Lo que suele aparecer no es una dependencia peligrosa, sino que la mayoría no tiene respuesta para ninguna de las tres. Esa lista, con las casillas vacías a la vista, es una conversación distinta a la de pedir presupuesto para una herramienta: convierte una intuición en un número que se puede reducir el trimestre siguiente.

Fuentes citadas

Jordi García
Escrito por
Jordi García
Tech Lead en onext

Jordi García es Tech Lead en onext. Trabaja en llevar la IA a producción gobernada en equipos de desarrollo y de producto —con Spec-Driven Development, ingeniería de contexto y verificación humana en cada paso— y firma los insights técnicos de onext sobre método, calidad y coste de la IA aplicada.

LinkedIn →

¿Cuántas dependencias entraron en vuestro repositorio el último trimestre sin que nadie decidiera nada?

Sacamos esa lista de vuestro fichero de bloqueo, marcamos las que no tienen dueño ni uso, y dejamos escrita la política de dependencias en el sitio donde el asistente la lee antes de proponer nada.

Ver cómo trabajamos

Sin plataforma nueva. Sin parar entregas.