{"id":645,"date":"2026-02-07T21:25:24","date_gmt":"2026-02-07T20:25:24","guid":{"rendered":"https:\/\/secure-pipelines.com\/?p=645"},"modified":"2026-03-24T18:08:04","modified_gmt":"2026-03-24T17:08:04","slug":"dependency-confusion-artifact-poisoning-attacks-defenses","status":"publish","type":"post","link":"https:\/\/secure-pipelines.com\/es\/ci-cd-security\/dependency-confusion-artifact-poisoning-attacks-defenses\/","title":{"rendered":"Confusi\u00f3n de Dependencias y Envenenamiento de Artefactos: T\u00e9cnicas de Ataque y Defensas"},"content":{"rendered":"<h2>Introducci\u00f3n<\/h2>\n<p>Los ataques a la cadena de suministro de software han aumentado tanto en frecuencia como en sofisticaci\u00f3n en los \u00faltimos a\u00f1os. En lugar de atacar las aplicaciones directamente, los adversarios apuntan cada vez m\u00e1s a las capas de resoluci\u00f3n de dependencias y distribuci\u00f3n de artefactos que sustentan el desarrollo de software moderno. Dos de las t\u00e9cnicas m\u00e1s efectivas en esta categor\u00eda son la <strong>confusi\u00f3n de dependencias<\/strong> (dependency confusion) y el <strong>envenenamiento de artefactos<\/strong> (artifact poisoning).<\/p>\n<p>Estos ataques explotan una verdad fundamental: el software moderno se ensambla, no se escribe desde cero. Una aplicaci\u00f3n t\u00edpica puede incorporar cientos o miles de paquetes de terceros, im\u00e1genes de contenedores, templates de CI y plugins de compilaci\u00f3n \u2014 cada uno representando un eslab\u00f3n en una cadena de confianza. Cuando cualquier eslab\u00f3n se compromete, toda la cadena falla.<\/p>\n<p>Lo que hace estos ataques particularmente peligrosos es que muchas organizaciones permanecen vulnerables a pesar de tener programas de seguridad maduros. Las pruebas tradicionales de seguridad de aplicaciones no detectan una dependencia maliciosa instalada en tiempo de compilaci\u00f3n. Los firewalls y WAFs son irrelevantes cuando el c\u00f3digo del atacante se ejecuta dentro de su pipeline CI\/CD con acceso completo a la red y credenciales de producci\u00f3n.<\/p>\n<p>Esta gu\u00eda proporciona un examen en profundidad de c\u00f3mo funcionan la confusi\u00f3n de dependencias y el envenenamiento de artefactos, por qu\u00e9 los pipelines CI\/CD son objetivos principales y \u2014 lo m\u00e1s importante \u2014 qu\u00e9 defensas pr\u00e1cticas puede implementar hoy.<\/p>\n<h2>Confusi\u00f3n de Dependencias Explicada<\/h2>\n<h3>C\u00f3mo los Package Managers Resuelven Nombres<\/h3>\n<p>La mayor\u00eda de los package managers modernos \u2014 npm, pip, RubyGems, NuGet, Maven \u2014 siguen un proceso de resoluci\u00f3n que consulta uno o m\u00e1s registros cuando se solicita un paquete. Cuando una organizaci\u00f3n utiliza tanto un <strong>registro privado\/interno<\/strong> (para paquetes propietarios) como el <strong>registro p\u00fablico<\/strong> (para paquetes open-source), el package manager debe decidir qu\u00e9 registro tiene prioridad cuando ambos contienen un paquete con el mismo nombre.<\/p>\n<p>El comportamiento predeterminado var\u00eda seg\u00fan el ecosistema, pero un patr\u00f3n com\u00fan es preocupante: muchos package managers preferir\u00e1n el <strong>n\u00famero de versi\u00f3n m\u00e1s alto<\/strong> independientemente de qu\u00e9 registro provenga. Esta decisi\u00f3n de dise\u00f1o aparentemente inocente es la base del ataque de confusi\u00f3n de dependencias.<\/p>\n<h3>La Investigaci\u00f3n Original: Alex Birsan (2021)<\/h3>\n<p>En febrero de 2021, el investigador de seguridad Alex Birsan public\u00f3 una investigaci\u00f3n pionera que demostraba c\u00f3mo este comportamiento de resoluci\u00f3n pod\u00eda ser utilizado como arma. Al examinar nombres de paquetes internos filtrados p\u00fablicamente de empresas como Apple, Microsoft y Tesla \u2014 encontrados en archivos JavaScript, manifiestos de paquetes y mensajes de error \u2014 registr\u00f3 paquetes con nombres id\u00e9nticos en los registros p\u00fablicos de npm, PyPI y RubyGems con n\u00fameros de versi\u00f3n inflados.<\/p>\n<p>El resultado fue devastador. Cuando los sistemas de compilaci\u00f3n de estas empresas resolv\u00edan las dependencias, los package managers obten\u00edan los paquetes p\u00fablicos de Birsan en lugar de los internos leg\u00edtimos. Sus paquetes de prueba de concepto inclu\u00edan callbacks benignos que reportaban a un servidor, confirmando la ejecuci\u00f3n de c\u00f3digo dentro de las redes corporativas. Birsan gan\u00f3 m\u00e1s de $130,000 en bug bounties en m\u00faltiples organizaciones.<\/p>\n<h3>La Mec\u00e1nica del Ataque<\/h3>\n<p>El ataque de confusi\u00f3n de dependencias sigue una secuencia directa:<\/p>\n<ol>\n<li><strong>Reconocimiento:<\/strong> El atacante identifica nombres de paquetes internos\/privados utilizados por la organizaci\u00f3n objetivo. Estos pueden encontrarse en archivos <code>package.json<\/code> filtrados, source maps de JavaScript, mensajes de error, ofertas de empleo o repositorios open-source que referencian dependencias internas.<\/li>\n<li><strong>Registro:<\/strong> El atacante registra un paquete con el nombre id\u00e9ntico en el registro p\u00fablico correspondiente (npm, PyPI, etc.), asign\u00e1ndole un n\u00famero de versi\u00f3n muy alto (por ejemplo, <code>99.0.0<\/code>).<\/li>\n<li><strong>Payload:<\/strong> El paquete p\u00fablico contiene c\u00f3digo malicioso en scripts de instalaci\u00f3n o hooks post-instalaci\u00f3n \u2014 c\u00f3digo que se ejecuta autom\u00e1ticamente cuando el paquete se instala.<\/li>\n<li><strong>Ejecuci\u00f3n:<\/strong> Cuando el sistema de compilaci\u00f3n de la organizaci\u00f3n objetivo ejecuta <code>npm install<\/code>, <code>pip install<\/code> o un comando equivalente, el package manager resuelve la dependencia al paquete p\u00fablico del atacante debido al n\u00famero de versi\u00f3n m\u00e1s alto.<\/li>\n<li><strong>Compromiso:<\/strong> El script de instalaci\u00f3n malicioso se ejecuta con los privilegios del proceso de compilaci\u00f3n, t\u00edpicamente obteniendo acceso a variables de entorno (incluyendo secrets), recursos de red y c\u00f3digo fuente.<\/li>\n<\/ol>\n<h3>Ecosistemas Afectados<\/h3>\n<p>La confusi\u00f3n de dependencias no se limita a un solo lenguaje o ecosistema. Los siguientes son todos susceptibles:<\/p>\n<ul>\n<li><strong>npm (Node.js):<\/strong> El comportamiento predeterminado puede preferir paquetes p\u00fablicos sobre privados cuando no se utiliza scoping.<\/li>\n<li><strong>PyPI (Python):<\/strong> El flag <code>--extra-index-url<\/code> de pip verifica tanto el \u00edndice privado como el p\u00fablico, prefiriendo la versi\u00f3n m\u00e1s alta.<\/li>\n<li><strong>RubyGems (Ruby):<\/strong> Comportamiento de resoluci\u00f3n similar cuando se configuran m\u00faltiples fuentes.<\/li>\n<li><strong>NuGet (.NET):<\/strong> Verifica m\u00faltiples feeds configurados y puede preferir la galer\u00eda p\u00fablica.<\/li>\n<li><strong>Maven (Java):<\/strong> Resuelve desde m\u00faltiples repositorios; los atacantes pueden publicar en Maven Central con group\/artifact IDs coincidentes.<\/li>\n<\/ul>\n<h3>Install Scripts como Vector de Payload<\/h3>\n<p>La raz\u00f3n por la que la confusi\u00f3n de dependencias es tan peligrosa es que los package managers soportan <strong>ejecuci\u00f3n autom\u00e1tica de c\u00f3digo durante la instalaci\u00f3n<\/strong>. En npm, esto ocurre a trav\u00e9s de scripts <code>preinstall<\/code>, <code>install<\/code> y <code>postinstall<\/code> definidos en <code>package.json<\/code>. En Python, <code>setup.py<\/code> puede ejecutar c\u00f3digo arbitrario durante <code>pip install<\/code>. Estos hooks fueron dise\u00f1ados para tareas leg\u00edtimas de compilaci\u00f3n pero proporcionan a los atacantes un vector de ejecuci\u00f3n ideal \u2014 el c\u00f3digo se ejecuta antes de que la aplicaci\u00f3n siquiera se compile, a menudo con privilegios elevados.<\/p>\n<h2>Envenenamiento de Artefactos: M\u00e1s All\u00e1 de los Paquetes<\/h2>\n<p>Mientras que la confusi\u00f3n de dependencias apunta espec\u00edficamente a los registros de paquetes, el <strong>envenenamiento de artefactos<\/strong> es una categor\u00eda m\u00e1s amplia de ataques a la cadena de suministro que puede apuntar a cualquier artefacto externo consumido durante el ciclo de vida del desarrollo de software. La superficie de ataque se extiende mucho m\u00e1s all\u00e1 de los package managers.<\/p>\n<h3>Im\u00e1genes Base de Contenedores Comprometidas<\/h3>\n<p>Las im\u00e1genes de contenedores obtenidas de Docker Hub u otros registros p\u00fablicos son un vector de ataque com\u00fan. Un atacante puede publicar una imagen maliciosa con un nombre similar a una imagen base popular, o comprometer una imagen existente obteniendo acceso a la cuenta del mantenedor. Si su Dockerfile especifica <code>FROM python:3.11<\/code> usando un tag mutable, una imagen comprometida publicada en ese tag ser\u00e1 incorporada en cada compilaci\u00f3n subsiguiente.<\/p>\n<h3>Templates de CI\/CD Manipulados<\/h3>\n<p>Los templates de GitHub Actions y GitLab CI referenciados desde repositorios p\u00fablicos representan otra superficie de ataque significativa. Cuando un workflow referencia <code>uses: some-org\/some-action@main<\/code>, el c\u00f3digo ejecutado en su pipeline es controlado por quien tenga acceso de push a ese repositorio. Si el repositorio de la action es comprometido, cada pipeline que la referencia tambi\u00e9n queda comprometido.<\/p>\n<h3>Typosquatting<\/h3>\n<p>Los ataques de typosquatting explotan errores ortogr\u00e1ficos comunes y similitudes visuales en nombres de paquetes. Los ejemplos incluyen registrar <code>co1ors<\/code> (con un n\u00famero uno) en lugar de <code>colors<\/code>, <code>lodahs<\/code> en lugar de <code>lodash<\/code>, o <code>reqeusts<\/code> en lugar de <code>requests<\/code>. Estos paquetes contienen c\u00f3digo malicioso y dependen de que los desarrolladores cometan errores tipogr\u00e1ficos al agregar dependencias. Las herramientas automatizadas han detectado miles de paquetes de typosquatting en npm y PyPI.<\/p>\n<h3>Cuentas de Mantenedores Secuestradas<\/h3>\n<p>Cuando un atacante obtiene acceso a la cuenta de un mantenedor leg\u00edtimo de paquetes \u2014 a trav\u00e9s de credential stuffing, phishing o ingenier\u00eda social \u2014 puede publicar versiones con backdoor de paquetes ampliamente utilizados. Debido a que el nombre del paquete y el mantenedor son leg\u00edtimos, estas versiones comprometidas son extremadamente dif\u00edciles de detectar por medios automatizados.<\/p>\n<h3>Plugins de Build Tools<\/h3>\n<p>Los sistemas de compilaci\u00f3n como Gradle, Maven y webpack soportan plugins que se ejecutan durante el proceso de compilaci\u00f3n. Los plugins maliciosos o comprometidos en estos ecosistemas pueden modificar los resultados de compilaci\u00f3n, exfiltrar secrets o inyectar backdoors en artefactos compilados. Debido a que los plugins de compilaci\u00f3n a menudo reciben menos escrutinio que las dependencias de aplicaci\u00f3n, representan un objetivo de alto valor.<\/p>\n<h3>Incidentes del Mundo Real<\/h3>\n<p>Varios incidentes importantes ilustran el impacto real del envenenamiento de artefactos:<\/p>\n<ul>\n<li><strong>event-stream (2018):<\/strong> Un nuevo mantenedor recibi\u00f3 derechos de publicaci\u00f3n del popular paquete npm <code>event-stream<\/code> (1.5 millones de descargas semanales). Agreg\u00f3 una dependencia a un paquete malicioso, <code>flatmap-stream<\/code>, que conten\u00eda c\u00f3digo cifrado dirigido a la billetera Bitcoin Copay, intentando robar criptomonedas.<\/li>\n<li><strong>ua-parser-js (2021):<\/strong> El paquete npm <code>ua-parser-js<\/code> (7 millones de descargas semanales) fue secuestrado cuando la cuenta del mantenedor fue comprometida. Se publicaron versiones maliciosas que instalaban cryptominers y malware de robo de credenciales en sistemas Linux y Windows.<\/li>\n<li><strong>node-ipc (2022):<\/strong> El mantenedor del paquete <code>node-ipc<\/code> a\u00f1adi\u00f3 deliberadamente c\u00f3digo que eliminaba archivos en sistemas con direcciones IP rusas o bielorrusas, demostrando que incluso los mantenedores de confianza pueden convertirse en un vector de amenaza (a veces llamado \u00abprotestware\u00bb).<\/li>\n<\/ul>\n<h2>C\u00f3mo Estos Ataques Explotan CI\/CD<\/h2>\n<p>Los pipelines CI\/CD son particularmente vulnerables a la confusi\u00f3n de dependencias y el envenenamiento de artefactos debido a c\u00f3mo est\u00e1n dise\u00f1ados para operar. Comprender por qu\u00e9 los pipelines son objetivos principales es esencial para construir defensas efectivas.<\/p>\n<h3>Ejecuci\u00f3n Autom\u00e1tica de C\u00f3digo Durante las Compilaciones<\/h3>\n<p>Cada vez que un pipeline de CI ejecuta <code>npm install<\/code>, <code>pip install -r requirements.txt<\/code> o <code>docker build<\/code>, est\u00e1 ejecutando c\u00f3digo de fuentes externas. Esto sucede autom\u00e1ticamente en cada commit, pull request o compilaci\u00f3n programada. No hay un humano en el proceso para revisar qu\u00e9 c\u00f3digo se est\u00e1 realmente incorporando y ejecutando.<\/p>\n<h3>Los Entornos de Compilaci\u00f3n Tienen Acceso a Credenciales<\/h3>\n<p>Los entornos CI\/CD t\u00edpicamente est\u00e1n configurados con secrets necesarios para el despliegue: credenciales de proveedores cloud, tokens de API, contrase\u00f1as de bases de datos, claves de firma y credenciales de registros. Una dependencia maliciosa que se ejecuta durante la fase de compilaci\u00f3n puede acceder a estos secrets a trav\u00e9s de variables de entorno o almacenes de secrets montados. Esto hace que los pipelines CI\/CD sean objetivos mucho m\u00e1s valiosos que las laptops de los desarrolladores.<\/p>\n<h3>Las Dependencias Obtenidas en Tiempo de Compilaci\u00f3n No Est\u00e1n Pre-Auditadas<\/h3>\n<p>En la mayor\u00eda de las organizaciones, las versiones de dependencias se especifican en archivos de manifiesto (<code>package.json<\/code>, <code>requirements.txt<\/code>) pero el c\u00f3digo real se obtiene fresco de los registros en tiempo de compilaci\u00f3n. Entre el momento en que un desarrollador agrega una dependencia y cuando el sistema CI la instala, el contenido del paquete podr\u00eda cambiar \u2014 o un paquete de confusi\u00f3n de dependencias podr\u00eda aparecer en el registro p\u00fablico. T\u00edpicamente no hay un paso de verificaci\u00f3n entre la resoluci\u00f3n y la ejecuci\u00f3n.<\/p>\n<h3>Las Dependencias Transitivas Expanden la Superficie de Ataque<\/h3>\n<p>Su aplicaci\u00f3n puede declarar 50 dependencias directas, pero esas dependencias tienen sus propias dependencias, creando un \u00e1rbol que puede incluir miles de paquetes transitivos. Usted no tiene control directo sobre lo que sus dependencias dependen. Cuando una dependencia transitiva es comprometida \u2014 como en el incidente de <code>event-stream<\/code> \u2014 el ataque se propaga a trav\u00e9s de todo el \u00e1rbol de dependencias sin ning\u00fan cambio en sus propios archivos de manifiesto.<\/p>\n<h2>Defensa Contra la Confusi\u00f3n de Dependencias<\/h2>\n<p>Prevenir la confusi\u00f3n de dependencias requiere configurar sus package managers y registros para eliminar la ambig\u00fcedad entre paquetes p\u00fablicos y privados. Aqu\u00ed est\u00e1n las mitigaciones m\u00e1s efectivas.<\/p>\n<h3>Utilice Namespace y Scope en Sus Paquetes Privados<\/h3>\n<p>La defensa individual m\u00e1s efectiva es utilizar nombres de paquetes con namespace o scope para todos los paquetes internos. En npm, esto significa usar paquetes con scope como <code>@yourcompany\/package-name<\/code>. Un atacante no puede registrar paquetes bajo el scope de su organizaci\u00f3n en el registro p\u00fablico de npm.<\/p>\n<h3>Configure la Prioridad del Registro Expl\u00edcitamente<\/h3>\n<p>Nunca conf\u00ede en el comportamiento de resoluci\u00f3n predeterminado. Configure expl\u00edcitamente su package manager para obtener paquetes con scope de su registro privado y todo lo dem\u00e1s del registro p\u00fablico.<\/p>\n<p><strong>Ejemplo de configuraci\u00f3n <code>.npmrc<\/code>:<\/strong><\/p>\n<pre><code># Always fetch @yourcompany scoped packages from private registry\n@yourcompany:registry=https:\/\/npm.yourcompany.com\/\n\n# All other packages come from the public npm registry\nregistry=https:\/\/registry.npmjs.org\/\n\n# Authentication for private registry\n\/\/npm.yourcompany.com\/:_authToken=${NPM_PRIVATE_TOKEN}<\/code><\/pre>\n<p><strong>Ejemplo de <code>pip.conf<\/code> para Python:<\/strong><\/p>\n<pre><code># IMPORTANT: Use --index-url (NOT --extra-index-url) for your private registry\n# --extra-index-url checks BOTH registries and picks the higher version (vulnerable!)\n# --index-url uses ONLY your private registry as the primary source\n\n[global]\nindex-url = https:\/\/pypi.yourcompany.com\/simple\/\n\n# If you need public PyPI packages, configure your private registry\n# (Artifactory, Nexus) to proxy public PyPI \u2014 do NOT use --extra-index-url<\/code><\/pre>\n<p><strong>Ejemplo de <code>.yarnrc.yml<\/code> para Yarn Berry:<\/strong><\/p>\n<pre><code>npmScopes:\n  yourcompany:\n    npmRegistryServer: \"https:\/\/npm.yourcompany.com\"\n    npmAuthToken: \"${NPM_PRIVATE_TOKEN}\"\n\nnpmRegistryServer: \"https:\/\/registry.yarnpkg.com\"<\/code><\/pre>\n<h3>Utilice Proxies de Registro Privado<\/h3>\n<p>Despliegue un proxy de registro como JFrog Artifactory, Sonatype Nexus o GitHub Packages que se sit\u00fae entre sus sistemas de compilaci\u00f3n y los registros p\u00fablicos. Configure el proxy para:<\/p>\n<ul>\n<li>Servir paquetes internos desde su repositorio privado.<\/li>\n<li>Hacer proxy de paquetes p\u00fablicos desde el registro upstream.<\/li>\n<li>Bloquear cualquier paquete p\u00fablico que comparta nombre con un paquete interno.<\/li>\n<li>Aplicar pol\u00edticas de seguridad (escaneo de vulnerabilidades, cumplimiento de licencias) antes de permitir el paso de paquetes.<\/li>\n<\/ul>\n<p>Esto crea una \u00fanica fuente de verdad para todas las dependencias y elimina completamente la ambig\u00fcedad p\u00fablico\/privado.<\/p>\n<h3>Registro Defensivo<\/h3>\n<p>Registre los nombres de sus paquetes internos en registros p\u00fablicos como paquetes placeholder. Estos paquetes no deben contener c\u00f3digo real \u2014 solo un README explicando que el nombre est\u00e1 reservado. Esto evita que los atacantes reclamen esos nombres. Aunque esta no es una defensa primaria, agrega una capa extra de protecci\u00f3n.<\/p>\n<h3>Fije Dependencias por Hash<\/h3>\n<p>Fijar dependencias por hash criptogr\u00e1fico asegura que el artefacto exacto que usted audit\u00f3 sea el que se instala durante las compilaciones. Incluso si un atacante publica una versi\u00f3n maliciosa, el hash no coincidir\u00e1 y la instalaci\u00f3n fallar\u00e1.<\/p>\n<p><strong>Para pip (Python):<\/strong><\/p>\n<pre><code># Generate hashes for your requirements\npip-compile --generate-hashes requirements.in -o requirements.txt\n\n# Install with hash verification\npip install --require-hashes -r requirements.txt<\/code><\/pre>\n<p><strong>Para npm:<\/strong><\/p>\n<p>npm registra autom\u00e1ticamente hashes de integridad en <code>package-lock.json<\/code>. Aseg\u00farese de hacer commit del lockfile y use <code>npm ci<\/code> (no <code>npm install<\/code>) en CI para forzar la verificaci\u00f3n de integridad:<\/p>\n<pre><code># In CI, always use npm ci \u2014 it strictly follows the lockfile\n# and verifies integrity hashes for every package\nnpm ci<\/code><\/pre>\n<h2>Defensa Contra el Envenenamiento de Artefactos<\/h2>\n<p>Debido a que el envenenamiento de artefactos abarca una gama m\u00e1s amplia de vectores de ataque, la defensa requiere controles en capas a trav\u00e9s de im\u00e1genes de contenedores, templates de CI, dependencias y procesos de compilaci\u00f3n.<\/p>\n<h3>Fije Im\u00e1genes de Contenedores por Digest<\/h3>\n<p>Nunca referencie im\u00e1genes de contenedores por tags mutables como <code>latest<\/code> o incluso <code>3.11<\/code>. En su lugar, fije al digest SHA256 inmutable:<\/p>\n<pre><code># Vulnerable: tag can be overwritten with a compromised image\nFROM python:3.11-slim\n\n# Secure: digest is immutable \u2014 this exact image or nothing\nFROM python:3.11-slim@sha256:a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2<\/code><\/pre>\n<h3>Fije GitHub Actions por SHA<\/h3>\n<p>Referencie GitHub Actions por su SHA de commit completo en lugar de un tag mutable:<\/p>\n<pre><code># Vulnerable: v3 tag can be moved to point to compromised code\n- uses: actions\/checkout@v3\n\n# Secure: pinned to specific commit SHA\n- uses: actions\/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2<\/code><\/pre>\n<h3>Verifique Firmas en las Dependencias<\/h3>\n<p>Donde est\u00e9 disponible, verifique firmas criptogr\u00e1ficas para confirmar que los artefactos fueron publicados por sus mantenedores esperados:<\/p>\n<ul>\n<li><strong>npm:<\/strong> Use <code>npm audit signatures<\/code> para verificar firmas del registro en los paquetes.<\/li>\n<li><strong>Im\u00e1genes de contenedores:<\/strong> Use Sigstore\/cosign para verificar firmas de im\u00e1genes de contenedores.<\/li>\n<li><strong>Python:<\/strong> PEP 740 y herramientas como <code>sigstore-python<\/code> est\u00e1n trayendo la verificaci\u00f3n de firmas a PyPI.<\/li>\n<\/ul>\n<h3>Genere y Rastree SBOMs<\/h3>\n<p>Un Software Bill of Materials (SBOM) inventar\u00eda cada componente en su aplicaci\u00f3n. Al generar SBOMs para cada compilaci\u00f3n y compararlos, puede detectar adiciones o cambios inesperados en su \u00e1rbol de dependencias. Herramientas como Syft, Trivy y CycloneDX pueden generar SBOMs en formatos est\u00e1ndar (SPDX, CycloneDX).<\/p>\n<h3>Automatice la Revisi\u00f3n de Dependencias<\/h3>\n<p>Despliegue herramientas automatizadas que escaneen continuamente sus dependencias en busca de vulnerabilidades conocidas y cambios sospechosos:<\/p>\n<ul>\n<li><strong>Dependabot \/ Renovate:<\/strong> Crean autom\u00e1ticamente PRs cuando hay actualizaciones de dependencias disponibles, d\u00e1ndole la oportunidad de revisar antes de hacer merge.<\/li>\n<li><strong>npm audit \/ pip-audit:<\/strong> Escanean vulnerabilidades conocidas en su \u00e1rbol de dependencias.<\/li>\n<li><strong>GitHub Dependency Review Action:<\/strong> Bloquea PRs que introducen dependencias con vulnerabilidades conocidas.<\/li>\n<\/ul>\n<h3>Restrinja el Acceso a Red Durante las Compilaciones (Hermetic Builds)<\/h3>\n<p>Los hermetic builds son compilaciones que no pueden acceder a la red. Todas las dependencias deben ser pre-obtenidas y cacheadas antes de que comience la compilaci\u00f3n. Esto evita que una compilaci\u00f3n obtenga un paquete malicioso reci\u00e9n publicado. Bazel soporta nativamente hermetic builds, y un aislamiento similar puede lograrse con el flag <code>--network=none<\/code> de Docker o pol\u00edticas de red espec\u00edficas de la plataforma CI.<\/p>\n<h3>Pre-Apruebe y Cree Allowlists de Dependencias<\/h3>\n<p>Mantenga una lista aprobada de dependencias y sus versiones. Cualquier nueva dependencia o cambio de versi\u00f3n requiere aprobaci\u00f3n expl\u00edcita a trav\u00e9s de un proceso de revisi\u00f3n. Aunque esto agrega fricci\u00f3n, previene que paquetes no autorizados entren en su pipeline de compilaci\u00f3n.<\/p>\n<h2>Detecci\u00f3n y Monitoreo<\/h2>\n<p>Incluso con controles preventivos fuertes, las capacidades de detecci\u00f3n son esenciales para capturar ataques que eludan sus defensas.<\/p>\n<h3>Monitoree Nuevas Dependencias Inesperadas<\/h3>\n<p>Implemente verificaciones de CI que marquen pull requests que introduzcan nuevas dependencias. Requiera justificaci\u00f3n y revisi\u00f3n expl\u00edcita para cualquier adici\u00f3n a su manifiesto de dependencias. Esto es particularmente importante para dependencias transitivas \u2014 una nueva dependencia directa podr\u00eda traer docenas de transitivas.<\/p>\n<h3>Alerte sobre Saltos de Versi\u00f3n de Dependencias<\/h3>\n<p>Una dependencia que salta de la versi\u00f3n <code>1.2.3<\/code> a <code>99.0.0<\/code> es un fuerte indicador de un ataque de confusi\u00f3n de dependencias. Implemente monitoreo que alerte sobre cambios de versi\u00f3n inusuales, especialmente grandes saltos de versi\u00f3n mayor en paquetes internos.<\/p>\n<h3>Aproveche las Herramientas de Escaneo de Seguridad<\/h3>\n<ul>\n<li><strong>Socket.dev:<\/strong> Analiza el comportamiento de los paquetes (acceso a red, acceso al sistema de archivos, install scripts) en lugar de solo CVEs conocidos, haci\u00e9ndolo efectivo para detectar ataques a la cadena de suministro.<\/li>\n<li><strong>Snyk:<\/strong> Proporciona escaneo y monitoreo de vulnerabilidades en m\u00faltiples ecosistemas.<\/li>\n<li><strong>GitHub Dependency Graph y Dependabot Alerts:<\/strong> Rastrean autom\u00e1ticamente las dependencias y alertan sobre vulnerabilidades conocidas.<\/li>\n<\/ul>\n<h3>Escanee Install Scripts y Hooks Post-Instalaci\u00f3n<\/h3>\n<p>Implemente herramientas que identifiquen espec\u00edficamente paquetes con install scripts. Aunque los install scripts tienen usos leg\u00edtimos, son el vector de ejecuci\u00f3n principal para ataques de confusi\u00f3n de dependencias. Marque y revise cualquier paquete que incluya scripts <code>preinstall<\/code>, <code>install<\/code> o <code>postinstall<\/code> en npm, o un <code>setup.py<\/code> con c\u00f3digo ejecutable en Python.<\/p>\n<h3>Compare SBOMs Entre Compilaciones<\/h3>\n<p>Compare regularmente SBOMs de compilaciones consecutivas. Cambios inesperados \u2014 nuevos paquetes que aparecen, versiones que cambian sin actualizaciones correspondientes del manifiesto, o paquetes de registros inesperados \u2014 deber\u00edan activar alertas e investigaci\u00f3n.<\/p>\n<h2>Hardening Espec\u00edfico de CI\/CD<\/h2>\n<p>M\u00e1s all\u00e1 de la gesti\u00f3n de dependencias, la configuraci\u00f3n de su pipeline CI\/CD en s\u00ed necesita hardening para resistir ataques a la cadena de suministro.<\/p>\n<h3>Haga Commit y Verifique Lock Files en CI<\/h3>\n<p>Los lock files (<code>package-lock.json<\/code>, <code>yarn.lock<\/code>, <code>Pipfile.lock<\/code>, <code>poetry.lock<\/code>) registran las versiones exactas y hashes de cada dependencia. Su pipeline de CI deber\u00eda fallar si el lock file tiene cambios inesperados.<\/p>\n<p><strong>Ejemplo de GitHub Actions \u2014 verificar integridad del lockfile:<\/strong><\/p>\n<pre><code>name: Build\non: [push, pull_request]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2\n\n      - name: Setup Node.js\n        uses: actions\/setup-node@1a4442cacd436585916f1b3aa94e4166f1a22160 # v3.8.2\n        with:\n          node-version: '20'\n\n      - name: Verify lockfile has not been tampered with\n        run: |\n          # npm ci will fail if package-lock.json is out of sync\n          # with package.json or if integrity hashes don't match\n          npm ci\n\n      - name: Check for lockfile modifications\n        run: |\n          if ! git diff --exit-code package-lock.json; then\n            echo \"ERROR: package-lock.json was modified during install.\"\n            echo \"This could indicate a dependency confusion attack.\"\n            exit 1\n          fi\n\n      - name: Audit dependencies\n        run: npm audit --audit-level=high<\/code><\/pre>\n<p><strong>Ejemplo de GitLab CI \u2014 verificaci\u00f3n de lockfile con pip:<\/strong><\/p>\n<pre><code>stages:\n  - verify\n  - build\n  - test\n\nverify-dependencies:\n  stage: verify\n  image: python:3.11-slim@sha256:abc123...  # Pin by digest\n  script:\n    - pip install pip-tools pip-audit\n    # Verify that requirements.txt hashes match actual packages\n    - pip install --require-hashes --no-deps -r requirements.txt\n    # Audit for known vulnerabilities\n    - pip-audit -r requirements.txt\n    # Ensure no unexpected changes to lockfile\n    - pip-compile --generate-hashes requirements.in -o \/tmp\/requirements-check.txt\n    - diff requirements.txt \/tmp\/requirements-check.txt\n  rules:\n    - if: '$CI_PIPELINE_SOURCE == \"merge_request_event\"'\n    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'\n\nbuild:\n  stage: build\n  image: python:3.11-slim@sha256:abc123...\n  script:\n    - pip install --require-hashes --no-deps -r requirements.txt\n    - python -m build\n  needs: [verify-dependencies]<\/code><\/pre>\n<h3>Separe la Resoluci\u00f3n de Dependencias de la Ejecuci\u00f3n de Compilaci\u00f3n<\/h3>\n<p>Use un proceso de compilaci\u00f3n en dos fases: primero resuelva y descargue las dependencias en un entorno aislado, luego ejecute la compilaci\u00f3n real con el acceso a red deshabilitado. Esto evita que una dependencia comprometida exfiltre datos o descargue payloads adicionales durante la compilaci\u00f3n.<\/p>\n<h3>Entornos de Compilaci\u00f3n Air-Gapped o con Red Restringida<\/h3>\n<p>Para compilaciones de alta seguridad, use entornos con red restringida que solo puedan acceder a su proxy de registro interno. Esto elimina la posibilidad de que las dependencias se obtengan directamente de registros p\u00fablicos durante la compilaci\u00f3n.<\/p>\n<pre><code># Docker-based hermetic build example\n# Phase 1: Fetch dependencies (with network)\ndocker run --name dep-fetch my-builder:latest \\\n  npm ci --prefer-offline\n\n# Phase 2: Build (without network)\ndocker run --network=none -v deps:\/app\/node_modules \\\n  my-builder:latest npm run build<\/code><\/pre>\n<h3>Cachee Dependencias en Almacenamiento Interno de Confianza<\/h3>\n<p>En lugar de obtener dependencias de registros p\u00fablicos en cada compilaci\u00f3n, cachee versiones aprobadas en almacenamiento interno (Artifactory, Nexus, buckets de almacenamiento cloud). Su pipeline de CI deber\u00eda obtener exclusivamente de este cach\u00e9 de confianza. Actualice el cach\u00e9 a trav\u00e9s de un proceso controlado y auditado.<\/p>\n<h2>Conclusi\u00f3n<\/h2>\n<p>La confusi\u00f3n de dependencias y el envenenamiento de artefactos explotan suposiciones de confianza profundamente arraigadas en la cadena de suministro de software. Cada <code>npm install<\/code>, cada <code>docker pull<\/code>, cada directiva <code>uses:<\/code> en un workflow de GitHub Actions es una decisi\u00f3n de confianza \u2014 y los atacantes est\u00e1n trabajando activamente para abusar de esa confianza.<\/p>\n<p>La defensa efectiva no es una sola herramienta o cambio de configuraci\u00f3n. Requiere controles en cada capa del ciclo de vida de las dependencias:<\/p>\n<ul>\n<li><strong>Resoluci\u00f3n:<\/strong> Aplique scope a sus paquetes, configure la prioridad del registro, use proxies de registro para eliminar la ambig\u00fcedad p\u00fablico\/privado.<\/li>\n<li><strong>Instalaci\u00f3n:<\/strong> Fije por hash, use lockfiles con <code>npm ci<\/code> o <code>--require-hashes<\/code>, deshabilite install scripts donde sea posible.<\/li>\n<li><strong>Verificaci\u00f3n:<\/strong> Verifique firmas, compare SBOMs, audite dependencias antes de que entren en su compilaci\u00f3n.<\/li>\n<li><strong>Monitoreo:<\/strong> Detecte cambios inesperados de dependencias, alerte sobre anomal\u00edas de versi\u00f3n, escanee comportamiento malicioso en paquetes.<\/li>\n<li><strong>Hardening del pipeline:<\/strong> Restrinja el acceso a red durante las compilaciones, verifique la integridad del lockfile en CI, separe la resoluci\u00f3n de dependencias de la ejecuci\u00f3n de compilaci\u00f3n.<\/li>\n<\/ul>\n<p>Las organizaciones que ser\u00e1n m\u00e1s resilientes a los ataques a la cadena de suministro son aquellas que tratan las dependencias con el mismo rigor que aplican a su propio c\u00f3digo: revisadas, verificadas, monitoreadas y nunca confiadas impl\u00edcitamente. Comience implementando los controles de mayor impacto \u2014 paquetes con scope, configuraci\u00f3n de registro, verificaci\u00f3n de lockfile en CI \u2014 y agregue capas progresivamente a medida que su programa de seguridad de cadena de suministro madure.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introducci\u00f3n Los ataques a la cadena de suministro de software han aumentado tanto en frecuencia como en sofisticaci\u00f3n en los \u00faltimos a\u00f1os. En lugar de atacar las aplicaciones directamente, los adversarios apuntan cada vez m\u00e1s a las capas de resoluci\u00f3n de dependencias y distribuci\u00f3n de artefactos que sustentan el desarrollo de software moderno. Dos de &#8230; <a title=\"Confusi\u00f3n de Dependencias y Envenenamiento de Artefactos: T\u00e9cnicas de Ataque y Defensas\" class=\"read-more\" href=\"https:\/\/secure-pipelines.com\/es\/ci-cd-security\/dependency-confusion-artifact-poisoning-attacks-defenses\/\" aria-label=\"Leer m\u00e1s sobre Confusi\u00f3n de Dependencias y Envenenamiento de Artefactos: T\u00e9cnicas de Ataque y Defensas\">Leer m\u00e1s<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[55,60],"tags":[],"post_folder":[],"class_list":["post-645","post","type-post","status-publish","format-standard","hentry","category-ci-cd-security","category-threats-attacks"],"_links":{"self":[{"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/posts\/645","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/comments?post=645"}],"version-history":[{"count":1,"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/posts\/645\/revisions"}],"predecessor-version":[{"id":657,"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/posts\/645\/revisions\/657"}],"wp:attachment":[{"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/media?parent=645"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/categories?post=645"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/tags?post=645"},{"taxonomy":"post_folder","embeddable":true,"href":"https:\/\/secure-pipelines.com\/es\/wp-json\/wp\/v2\/post_folder?post=645"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}