<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: lu1tr0n</title>
    <description>The latest articles on DEV Community by lu1tr0n (@lu1tr0n).</description>
    <link>https://dev.to/lu1tr0n</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F806044%2F070ecfe6-05a6-44e1-95e3-81211fc13ab4.png</url>
      <title>DEV Community: lu1tr0n</title>
      <link>https://dev.to/lu1tr0n</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lu1tr0n"/>
    <language>en</language>
    <item>
      <title>Licencia BSD: qué es y por qué sigue viva en FreeBSD y macOS</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Mon, 02 Nov 2026 08:30:53 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/licencia-bsd-que-es-y-por-que-sigue-viva-en-freebsd-y-macos-23dn</link>
      <guid>https://dev.to/lu1tr0n/licencia-bsd-que-es-y-por-que-sigue-viva-en-freebsd-y-macos-23dn</guid>
      <description>&lt;p&gt;En 1977, Bill Joy grabó un compilador de Pascal y un editor de texto en una cinta magnética y la envió por correo a otra universidad. Treinta copias después, esa cinta dio origen a la &lt;strong&gt;licencia BSD&lt;/strong&gt;, el acuerdo legal que todavía permite que FreeBSD, OpenBSD y macOS compartan código entre sí sin pedir permiso.&lt;/p&gt;

&lt;p&gt;Casi cincuenta años después, cada vez que alguien abre una Mac o levanta un servidor con FreeBSD está usando una rama directa de ese primer envío de Berkeley. Entender esa licencia explica por qué estos sistemas se parecen a Linux en la superficie, pero se comportan distinto en las reglas del juego.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;La licencia BSD, nacida en Berkeley en 1977, permite copiar y modificar código sin obligar a publicar los cambios, a diferencia de la GPL.&lt;/li&gt;
&lt;li&gt;FreeBSD, OpenBSD y NetBSD descienden del mismo código 386BSD liberado en 1992 por Bill Jolitz.&lt;/li&gt;
&lt;li&gt;macOS corre Darwin, un núcleo Mach combinado con utilidades de 4.4BSD-Lite heredadas de ese mismo linaje.&lt;/li&gt;
&lt;li&gt;pkg y los ports reemplazan a apt en FreeBSD, pero el kernel y el userland se desarrollan juntos en un solo repositorio.&lt;/li&gt;
&lt;li&gt;OpenBSD se separó de NetBSD en 1995 para priorizar auditorías de seguridad por sobre la compatibilidad de hardware.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Qué es la licencia BSD?
&lt;/h2&gt;

&lt;p&gt;La licencia BSD es un permiso de software libre creado en la Universidad de California en Berkeley a fines de los años setenta que autoriza copiar, modificar y redistribuir código, incluso en productos cerrados, con la única condición de mantener el aviso de copyright original.&lt;/p&gt;

&lt;p&gt;Existen dos variantes activas: la licencia BSD de 2 cláusulas, que solo pide mantener el aviso de copyright y la lista de condiciones en el código fuente y en la documentación, y la de 3 cláusulas, que además prohíbe usar el nombre de la universidad o de los autores originales para promocionar productos derivados sin permiso.&lt;/p&gt;

&lt;h2&gt;
  
  
  El origen: de Bell Labs a una cinta mandada por correo
&lt;/h2&gt;

&lt;p&gt;Cuando Ken Thompson volvió a Bell Labs en 1976 tras un año dando clases en Berkeley, dejó atrás a dos estudiantes, Bill Joy y Chuck Haley, metidos de lleno en el código del kernel de Unix. Empezaron a optimizarlo y, en paralelo, a empaquetar herramientas propias: un compilador de Pascal y &lt;code&gt;ex&lt;/code&gt;, un editor de línea del que después saldría &lt;code&gt;vi&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A principios de 1977, Joy armó la primera Berkeley Software Distribution con ese compilador de Pascal y &lt;code&gt;ex&lt;/code&gt;. No era un sistema operativo aparte: era un paquete para instalar sobre un Unix que ya tenías. En el año siguiente salieron &lt;a href="https://fosscomics.com/posts/13.%20BSD%20Unix%20Part%203%20-%20The%20Beginning%20of%20BSD%20Unix/" rel="noopener noreferrer"&gt;unas treinta copias en cinta&lt;/a&gt;, cada una copiada y enviada a mano por el propio Joy.&lt;/p&gt;

&lt;p&gt;Para conseguirla hacía falta ya tener una licencia de fuente de Unix de AT&amp;amp;T; Berkeley solo cobraba el costo de la cinta y el envío. Esa política de precio casi simbólico, sumada a la tradición de Berkeley de compartir software académico, hizo que la distribución se expandiera rápido entre universidades que ya tenían la licencia base.&lt;/p&gt;

&lt;p&gt;La segunda distribución, 2BSD, llegó con &lt;code&gt;vi&lt;/code&gt; (el modo visual de &lt;code&gt;ex&lt;/code&gt;), el C shell y mejoras al compilador de Pascal; &lt;a href="https://fosscomics.com/posts/13.%20BSD%20Unix%20Part%203%20-%20The%20Beginning%20of%20BSD%20Unix/" rel="noopener noreferrer"&gt;cerca de 75 cintas&lt;/a&gt; salieron de Berkeley en el año siguiente, otra vez copiadas y enviadas por Joy en persona.&lt;/p&gt;

&lt;p&gt;El salto real llegó en 1978, cuando el grupo del profesor Richard Fateman consiguió una VAX de 32 bits con un megabyte de memoria para correr Macsyma, un sistema de álgebra simbólica. La VAX ya tenía una versión de Unix de Bell Labs llamada 32/V, pero sin soporte real para memoria virtual: el espacio de direcciones de cada programa quedaba limitado a la memoria física disponible, insuficiente para Macsyma.&lt;/p&gt;

&lt;p&gt;Ozalp Babaoglu, estudiante de posgrado dirigido por el profesor Domenico Ferrari, escribió el soporte de memoria virtual para 32/V. Joy ayudó a integrar y depurar ese código durante las vacaciones de fin de 1978, cuando había menos gente usando la VAX. Para enero de 1979 la mayoría de los errores estaban resueltos.&lt;/p&gt;

&lt;p&gt;Joy portó &lt;code&gt;ex&lt;/code&gt;, &lt;code&gt;vi&lt;/code&gt;, el C shell y el resto de 2BSD a la VAX; Peter Kessler y Marshall Kirk McKusick portaron el sistema de Pascal. Todo ese trabajo, sumado al kernel con memoria virtual ya depurado, salió en diciembre de 1979 como 3BSD.&lt;/p&gt;

&lt;p&gt;La red ARPANET, operativa desde 1969 y financiada por la agencia de proyectos avanzados de defensa de Estados Unidos, conectaba instituciones con hardware y sistemas operativos distintos que no podían compartir software fácilmente. DARPA se interesó en la portabilidad de Unix y tomó nota del éxito de 3BSD distribuyéndose entre centros de investigación, lo que abrió la puerta a financiar directamente el desarrollo de BSD en los años siguientes.&lt;/p&gt;

&lt;p&gt;La primera distribución de Berkeley de 1977 viajó en cinta magnética a unas treinta universidades.&lt;/p&gt;

&lt;h2&gt;
  
  
  La guerra legal que terminó liberando el código
&lt;/h2&gt;

&lt;p&gt;A fines de los años ochenta, Berkeley ya distribuía 4.3BSD con buena parte de utilidades propias, pero todavía dependía de código fuente de AT&amp;amp;T con licencia. En 1991, un grupo de desarrolladores, incluido Keith Bostic, fundó Berkeley Software Design Inc. (BSDi) para vender una versión comercial basada en ese trabajo.&lt;/p&gt;

&lt;p&gt;Unix System Laboratories, la filial de AT&amp;amp;T dueña entonces de los derechos de Unix, &lt;a href="https://en.wikipedia.org/wiki/UNIX_System_Laboratories,_Inc._v._Berkeley_Software_Design,_Inc." rel="noopener noreferrer"&gt;demandó a BSDi y a la Universidad de California en 1992&lt;/a&gt; alegando que el producto todavía contenía código y secretos comerciales de AT&amp;amp;T. El litigio frenó durante casi dos años cualquier avance claro sobre qué partes de BSD eran realmente libres de reclamos.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;📌 Nota:&lt;/strong&gt; el acuerdo no declaró ganador a ninguna parte; obligó a reescribir o eliminar un puñado de archivos puntuales, no todo el sistema.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;El caso se resolvió en 1994 con un acuerdo que obligó a reescribir o eliminar esos archivos en disputa. El resultado fue &lt;strong&gt;4.4BSD-Lite&lt;/strong&gt;, una distribución sin una sola línea de código de AT&amp;amp;T, publicada bajo la licencia BSD sin restricciones heredadas. Esa es la base legalmente limpia sobre la que se construyeron después FreeBSD, NetBSD y, vía NeXTSTEP, el propio macOS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué hace distinta a la licencia BSD de la GPL
&lt;/h2&gt;

&lt;p&gt;La diferencia central entre las &lt;a href="https://en.wikipedia.org/wiki/BSD_licenses" rel="noopener noreferrer"&gt;licencias tipo BSD&lt;/a&gt; y la GPL es qué pasa cuando alguien redistribuye una versión modificada. BSD no pregunta qué hiciste con el código después de tocarlo; la GPL sí, y te obliga a publicar el resultado bajo la misma licencia.&lt;/p&gt;

&lt;p&gt;Esa diferencia tiene consecuencias prácticas concretas. Una empresa puede tomar el stack de red de FreeBSD, meterlo en un router comercial cerrado y nunca publicar sus cambios, algo que la GPLv2 del kernel Linux no permite sin publicar el código derivado.&lt;/p&gt;

&lt;p&gt;LicenciaObligación al redistribuirPermite cerrar el código derivado&lt;/p&gt;

&lt;p&gt;Licencia BSD (2 o 3 cláusulas)Mantener el aviso de copyright y la lista de condicionesSí&lt;br&gt;
MITMantener el aviso de copyright, casi idéntica en espíritu a BSDSí&lt;br&gt;
GPLv2 / GPLv3Publicar el código fuente completo del derivado bajo la misma licenciaNo&lt;/p&gt;
&lt;h2&gt;
  
  
  El linaje vivo: FreeBSD, NetBSD, OpenBSD y macOS
&lt;/h2&gt;

&lt;p&gt;En 1992, Bill y Lynne Jolitz portaron 4.3BSD-Lite al hardware de PC bajo el nombre 386BSD y lo publicaron como shareware. El proyecto acumuló cientos de parches sin un proceso ordenado de integración, y hacia 1993 dos grupos distintos tomaron ese código y lo organizaron por su cuenta: uno se convirtió en FreeBSD, enfocado en facilidad de uso en PC y servidores; otro en NetBSD, enfocado en portabilidad a la mayor cantidad de arquitecturas posible.&lt;/p&gt;

&lt;p&gt;En 1995, Theo de Raadt se separó de NetBSD por diferencias internas y fundó OpenBSD, con énfasis explícito en auditar cada línea del código base buscando errores de seguridad antes de aceptarla. Ese énfasis explica por qué OpenBSD inventó &lt;a href="https://www.openssh.com/" rel="noopener noreferrer"&gt;OpenSSH&lt;/a&gt;, el cliente y servidor SSH que terminó empaquetado en prácticamente todas las distribuciones de Linux y en Windows.&lt;/p&gt;

&lt;p&gt;El cuarto heredero es menos obvio: cuando Steve Jobs fundó NeXT tras salir de Apple, construyó NeXTSTEP sobre un microkernel Mach combinado con utilidades y una capa de compatibilidad de BSD. Cuando Apple compró NeXT en 1997, esa base se convirtió en Darwin, el núcleo open source que corre debajo de macOS, iOS, iPadOS y watchOS. Por eso una terminal de Mac entiende flags de &lt;code&gt;ls&lt;/code&gt; que no existen en la versión GNU de la misma herramienta.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;flowchart&lt;/span&gt; &lt;span class="nv"&gt;TD&lt;/span&gt;
 &lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Unix en Bell Labs (AT&amp;amp;T)"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"BSD 1977 (Pascal + ex)"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
 &lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"2BSD (vi, csh)"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
 &lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"3BSD en VAX (1979)"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
 &lt;span class="nv"&gt;D&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;E&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"4.3BSD"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
 &lt;span class="nv"&gt;E&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"386BSD (1992)"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
 &lt;span class="nv"&gt;F&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;G&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"FreeBSD"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
 &lt;span class="nv"&gt;F&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;H&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"NetBSD"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
 &lt;span class="nv"&gt;H&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"OpenBSD (1995)"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
 &lt;span class="nv"&gt;E&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;J&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"4.4BSD-Lite (1994)"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
 &lt;span class="nv"&gt;J&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;K&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Darwin / macOS"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OpenBSD se separó de NetBSD en 1995; macOS hereda utilidades de 4.4BSD-Lite liberado en 1994.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo empezar: probar FreeBSD sin tocar tu sistema principal
&lt;/h2&gt;

&lt;p&gt;No necesitás instalar nada sobre tu equipo real para ver el linaje BSD funcionando: un emulador de máquinas virtuales alcanza. Esto es lo que hace falta antes de arrancar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;QEMU&lt;/strong&gt; instalado (&lt;code&gt;sudo apt install qemu-system-x86&lt;/code&gt; en Debian o Ubuntu, &lt;code&gt;brew install qemu&lt;/code&gt; en macOS).&lt;/li&gt;
&lt;li&gt;Al menos 20 GB libres en disco y 2 GB de RAM disponibles para la máquina virtual.&lt;/li&gt;
&lt;li&gt;La imagen ISO oficial de instalación, descargada desde la &lt;a href="https://www.freebsd.org/where/" rel="noopener noreferrer"&gt;página oficial de descargas de FreeBSD&lt;/a&gt; (arquitectura amd64, disco 1 de la versión RELEASE más reciente).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Con el ISO ya descargado como &lt;code&gt;FreeBSD.iso&lt;/code&gt;, estos dos comandos crean el disco virtual y arrancan el instalador:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;qemu-img create &lt;span class="nt"&gt;-f&lt;/span&gt; qcow2 freebsd.qcow2 20G
qemu-system-x86_64 &lt;span class="nt"&gt;-m&lt;/span&gt; 2048 &lt;span class="nt"&gt;-cdrom&lt;/span&gt; FreeBSD.iso &lt;span class="nt"&gt;-hda&lt;/span&gt; freebsd.qcow2 &lt;span class="nt"&gt;-boot&lt;/span&gt; d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El primer comando crea un disco virtual de 20 GB en formato qcow2; el segundo arranca una máquina con 2 GB de RAM usando ese disco y el ISO como medio de arranque. A los pocos segundos aparece &lt;code&gt;bsdinstall&lt;/code&gt;, el mismo instalador de texto que usa FreeBSD en hardware real.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Tip:&lt;/strong&gt; antes de aplicar &lt;code&gt;freebsd-update&lt;/code&gt; por primera vez, apagá la VM y copiá el archivo &lt;code&gt;freebsd.qcow2&lt;/code&gt; a un lado; si algo falla, volver atrás es pegar el archivo de vuelta en lugar de reinstalar.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Una vez dentro del sistema instalado, este comando confirma que estás parado sobre el linaje BSD real y no sobre una capa de compatibilidad:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La salida tiene el formato &lt;code&gt;FreeBSD nombrehost 14.x-RELEASE FreeBSD 14.x-RELEASE releng/14.x amd64&lt;/code&gt;, donde &lt;code&gt;FreeBSD&lt;/code&gt; aparece dos veces: una como sistema operativo y otra como nombre del kernel. En Linux, el mismo comando devuelve &lt;code&gt;Linux&lt;/code&gt; seguido de la versión del kernel, nunca del nombre de una distribución.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ejemplo progresivo: instalar software en FreeBSD vs Linux
&lt;/h3&gt;

&lt;p&gt;En FreeBSD el gestor de paquetes binarios se llama &lt;code&gt;pkg&lt;/code&gt; y funciona parecido a &lt;code&gt;apt&lt;/code&gt; o &lt;code&gt;dnf&lt;/code&gt;, pero reconstruye desde el árbol de ports si lo necesitás:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pkg &lt;span class="nb"&gt;install &lt;/span&gt;nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La salida muestra el plan de instalación antes de ejecutarlo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The following 1 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
 nginx: 1.27.x

Proceed with this action? [y/N]:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Es el mismo flujo mental de &lt;code&gt;apt install nginx&lt;/code&gt; en Debian, pero el binario instalado viene del árbol de ports de FreeBSD, no de un repositorio de Canonical ni de ninguna distribución GNU/Linux: la cadena completa, desde el código fuente hasta el paquete binario, vive dentro del mismo proyecto que mantiene el kernel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparativa: elegir entre un sistema BSD y Linux
&lt;/h2&gt;

&lt;p&gt;CriterioFreeBSD / OpenBSDLinux (cualquier distro)&lt;/p&gt;

&lt;p&gt;Modelo de licenciaPermisiva: podés cerrar tus cambiosKernel bajo GPLv2: los cambios al kernel deben publicarse&lt;br&gt;
Quién empaqueta kernel y utilidadesUn solo proyecto, un solo releaseKernel y userland vienen de proyectos separados, ensamblados por la distro&lt;br&gt;
Hardware soportadoMenor variedad de drivers listosCatálogo de hardware mucho más amplio&lt;br&gt;
Caso de uso típicoFirewalls (pfSense, OPNsense), appliances de red, servidores que priorizan estabilidadServidores de propósito general, escritorio, contenedores, nube&lt;br&gt;
Cuándo NO convieneSi necesitás soporte inmediato de hardware de escritorio reciente o drivers propietariosSi necesitás un árbol único auditado de punta a punta sin piezas de terceros&lt;/p&gt;
&lt;h2&gt;
  
  
  Errores comunes al pensar en BSD Unix
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"BSD está muerto"&lt;/strong&gt;: es falso. Netflix construyó buena parte de &lt;a href="https://openconnect.netflix.com/" rel="noopener noreferrer"&gt;Open Connect&lt;/a&gt;, su plataforma de entrega de video, sobre FreeBSD, y Sony usa un derivado de FreeBSD como base de los &lt;a href="https://en.wikipedia.org/wiki/PlayStation_4_system_software" rel="noopener noreferrer"&gt;firmwares de PlayStation 4 y PlayStation 5&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"La licencia BSD es dominio público"&lt;/strong&gt;: tampoco. El código sigue con copyright de sus autores; la licencia solo renuncia al requisito de compartir los cambios, no a la autoría.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"OpenBSD es FreeBSD con otro nombre"&lt;/strong&gt;: son proyectos con bases de código, calendarios de release y prioridades distintas desde que Theo de Raadt bifurcó OpenBSD de NetBSD en 1995 para poner la auditoría de seguridad por delante de la compatibilidad de hardware.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"macOS es Unix, por lo tanto es BSD"&lt;/strong&gt;: macOS combina el microkernel Mach con utilidades heredadas de 4.4BSD-Lite dentro de Darwin; tiene &lt;a href="https://www.opengroup.org/" rel="noopener noreferrer"&gt;certificación Unix 03&lt;/a&gt;, pero su núcleo no es un fork de un kernel BSD monolítico como el de FreeBSD.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Profundizando: por qué importa que el kernel y el userland vivan juntos
&lt;/h2&gt;

&lt;p&gt;La diferencia más técnica entre un sistema BSD y una distribución Linux no es el kernel en sí, sino quién lo empaqueta. FreeBSD, OpenBSD y NetBSD publican el kernel, las herramientas base (&lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cp&lt;/code&gt;, el compilador, el sistema de arranque) y la documentación desde un único repositorio y bajo un único proceso de release.&lt;/p&gt;

&lt;p&gt;Linux, en cambio, es solo el kernel: las herramientas que lo rodean (coreutils, systemd o su alternativa, el gestor de paquetes) las aporta un ecosistema de proyectos independientes, y cada distribución decide cómo combinarlos. Eso explica por qué dos instalaciones de Linux pueden diferir radicalmente en comandos e inicialización, mientras dos instalaciones de FreeBSD rara vez se sorprenden entre sí.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;flowchart&lt;/span&gt; &lt;span class="nv"&gt;TD&lt;/span&gt;
 &lt;span class="k"&gt;subgraph&lt;/span&gt; &lt;span class="nv"&gt;BSD&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"FreeBSD u OpenBSD: un solo árbol"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
 &lt;span class="nv"&gt;K1&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Kernel"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;U1&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Userland y utilidades"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
 &lt;span class="nv"&gt;end&lt;/span&gt;
 &lt;span class="k"&gt;subgraph&lt;/span&gt; &lt;span class="nv"&gt;LINUX&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Ecosistema Linux"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
 &lt;span class="nv"&gt;K2&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Kernel Linux"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;U2&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Userland (GNU, systemd, etc.)"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
 &lt;span class="nv"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esa coherencia tiene un costo: el ciclo de un sistema BSD es más lento para adoptar hardware nuevo, porque cada driver tiene que entrar al mismo árbol auditado en lugar de llegar como un módulo externo compilado aparte, algo habitual en Linux.&lt;/p&gt;

&lt;p&gt;Tu próximo paso: levantá la VM de FreeBSD del apartado anterior y corré &lt;code&gt;pkg install bash git&lt;/code&gt; para comparar en carne propia cómo se siente el árbol de ports frente a tu gestor de paquetes habitual.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: &lt;a href="https://telegra.ph/Licencia-BSD-qu%C3%A9-es-y-por-qu%C3%A9-sigue-viva-en-FreeBSD-y-macOS-11-02" rel="noopener noreferrer"&gt;Ver resumen&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿La licencia BSD obliga a publicar el código modificado?
&lt;/h3&gt;

&lt;p&gt;No. A diferencia de la GPL, la licencia BSD solo exige mantener el aviso de copyright original; podés modificar el código y vender el resultado cerrado.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿FreeBSD y OpenBSD comparten el mismo kernel?
&lt;/h3&gt;

&lt;p&gt;No. Ambos nacieron del código 386BSD de 1992, pero desde que NetBSD y FreeBSD se separaron en 1993, y OpenBSD de NetBSD en 1995, cada proyecto mantiene su propio kernel con decisiones de diseño distintas.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Por qué macOS se considera parte del linaje BSD si usa un kernel Mach?
&lt;/h3&gt;

&lt;p&gt;Porque Darwin, el núcleo de macOS, combina ese microkernel Mach con utilidades y una capa de compatibilidad heredadas de 4.4BSD-Lite; buena parte de los comandos de terminal en Mac vienen directo de ese código.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué diferencia práctica hay entre pkg de FreeBSD y apt de Linux?
&lt;/h3&gt;

&lt;p&gt;Ambos instalan paquetes binarios con una sintaxis parecida, pero pkg se construye desde el mismo árbol de ports que mantiene el proyecto FreeBSD, mientras que apt depende del repositorio de una distribución externa al kernel Linux.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Sigue siendo relevante elegir un sistema BSD en 2026?
&lt;/h3&gt;

&lt;p&gt;Sí, en nichos concretos: firewalls como pfSense y OPNsense corren sobre FreeBSD, y OpenBSD sigue siendo referencia en auditorías de seguridad, aunque para escritorio o soporte de hardware reciente Linux tiene catálogo más amplio.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://fosscomics.com/posts/13.%20BSD%20Unix%20Part%203%20-%20The%20Beginning%20of%20BSD%20Unix/" rel="noopener noreferrer"&gt;FOSS Comics&lt;/a&gt;: la historieta que narra el nacimiento de BSD en Berkeley, con las anécdotas de Bill Joy y la VAX de 1978.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.freebsd.org/" rel="noopener noreferrer"&gt;FreeBSD Project&lt;/a&gt;: sitio oficial del proyecto, con la página de descargas y el manual de instalación.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.openbsd.org/" rel="noopener noreferrer"&gt;OpenBSD Project&lt;/a&gt;: sitio oficial del proyecto fundado por Theo de Raadt en 1995.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Berkeley_Software_Distribution" rel="noopener noreferrer"&gt;Wikipedia: Berkeley Software Distribution&lt;/a&gt;: resumen histórico de las distribuciones BSD y su cronología.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/BSD_licenses" rel="noopener noreferrer"&gt;Wikipedia: BSD licenses&lt;/a&gt;: comparación de las variantes de 2 y 3 cláusulas de la licencia BSD.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/UNIX_System_Laboratories,_Inc._v._Berkeley_Software_Design,_Inc." rel="noopener noreferrer"&gt;Wikipedia: USL v. BSDi&lt;/a&gt;: detalle del litigio entre AT&amp;amp;T y Berkeley que llevó a 4.4BSD-Lite.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>linux</category>
      <category>programming</category>
      <category>devops</category>
    </item>
    <item>
      <title>JEPA: qué es la arquitectura de LeCun que no genera píxeles</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Mon, 02 Nov 2026 02:31:55 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/jepa-que-es-la-arquitectura-de-lecun-que-no-genera-pixeles-23oj</link>
      <guid>https://dev.to/lu1tr0n/jepa-que-es-la-arquitectura-de-lecun-que-no-genera-pixeles-23oj</guid>
      <description>&lt;p&gt;Yann LeCun lleva años insistiendo en que los modelos generativos, los mismos que producen texto o imágenes token por token, no son el camino hacia una inteligencia artificial con sentido común. El 29 de octubre de 2026 publicó, junto a Randall Balestriero, la prueba matemática de esa intuición. Su &lt;a href="https://arxiv.org/abs/2610.39302" rel="noopener noreferrer"&gt;paper en arXiv&lt;/a&gt; demuestra que la arquitectura JEPA que ambos diseñaron converge a la misma representación del mundo sin importar la modalidad de entrada, algo que la predicción de próximo token logra con mucha menos eficiencia.&lt;/p&gt;

&lt;p&gt;Esa demostración no es el tema de este artículo. Lo que importa para un desarrollador es entender qué hace distinta a esta arquitectura, que Meta ya usa en producción en I-JEPA y V-JEPA. Su apuesta central es predecir representaciones en vez de píxeles.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;JEPA predice la representación latente de una parte oculta, sin reconstruir píxeles ni tokens.- Meta usa este diseño en I-JEPA para imágenes y en V-JEPA para video en producción.- Un codificador objetivo con pesos EMA y stop-gradient evita el colapso representacional.- Las vistas positivas necesitan 42 veces menos muestras que el next-token prediction para alinear representaciones.- A diferencia de la difusión, JEPA predice embeddings para entender el mundo, no para generar contenido nuevo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Qué es la arquitectura JEPA?
&lt;/h2&gt;

&lt;p&gt;La arquitectura JEPA es una familia de modelos de aprendizaje autosupervisado que predice la representación latente de una parte faltante de los datos a partir de una parte visible, sin generar los datos originales pixel por pixel. LeCun la propuso en 2022 como alternativa a los generativos.&lt;/p&gt;

&lt;p&gt;LeCun presentó la idea en su ensayo &lt;em&gt;A Path Towards Autonomous Machine Intelligence&lt;/em&gt;, donde argumentaba que un sistema inteligente necesita un modelo del mundo capaz de predecir sin gastar cómputo en detalles irrelevantes. Reconstruir cada píxel de un video, por ejemplo, obliga al modelo a aprender ruido de cámara o texturas de fondo que no ayudan a entender la escena.&lt;/p&gt;

&lt;p&gt;JEPA evita ese desperdicio prediciendo en el espacio de las representaciones (embeddings) en lugar del espacio de los datos crudos. En la práctica significa entrenar dos codificadores que nunca comparten gradiente directo y un predictor que conecta ambos. El resultado es un modelo que aprende qué información importa de una escena sin que nadie le diga qué es importante.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué importa el enfoque predictivo de LeCun
&lt;/h2&gt;

&lt;p&gt;El problema que resuelve JEPA es concreto: entrenar modelos de visión sin millones de etiquetas humanas. Los modelos generativos de imágenes (difusión, autoencoders variacionales) también aprenden sin etiquetas, pero gastan su capacidad reconstruyendo cada textura y cada pixel de ruido, justo lo que después hay que ignorar para tareas como clasificación o segmentación.&lt;/p&gt;

&lt;p&gt;El paper de Balestriero y LeCun le pone números a esa intuición. Usando un corpus de &lt;a href="https://arxiv.org/abs/2610.39302" rel="noopener noreferrer"&gt;145.000 descripciones de imágenes y 940 millones de imágenes web&lt;/a&gt;, encontraron que las vistas positivas (dos observaciones de la misma escena) alinean representaciones usando 42 veces menos muestras que el next-token prediction entrenado sobre el mismo texto.&lt;/p&gt;

&lt;p&gt;Eso explica por qué los modelos de lenguaje alinean con la visión solo a gran escala. La predicción de próximo token es, &lt;a href="https://arxiv.org/abs/2610.39302" rel="noopener noreferrer"&gt;según los propios autores&lt;/a&gt;, una JEPA con "vistas malas", fragmentos de un mismo documento en lugar de observaciones reales de una escena compartida. Un modelo de texto de apenas 109 millones de parámetros entrenado con vistas buenas alineó mejor con los encoders de imagen de DINOv2 y CLIP que cualquier modelo de lenguaje evaluado, incluso uno de 72.000 millones de parámetros.&lt;/p&gt;

&lt;p&gt;Para quien entrena modelos con presupuesto limitado la lección es práctica. Elegir una arquitectura que prediga en espacio latente ahorra cómputo y datos etiquetados, dos recursos que escasean fuera de los laboratorios grandes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo funciona JEPA por dentro
&lt;/h2&gt;

&lt;p&gt;La arquitectura tiene tres piezas. El codificador de contexto procesa la parte visible de la entrada, un bloque de parches de una imagen o un clip de video. El codificador objetivo procesa la parte oculta, pero sus pesos no se entrenan por gradiente, se actualizan como un promedio móvil exponencial (EMA) de los pesos del codificador de contexto. El predictor toma la salida del codificador de contexto y trata de adivinar la salida del codificador objetivo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;flowchart&lt;/span&gt; &lt;span class="nv"&gt;TD&lt;/span&gt;
    &lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Entrada (imagen o video)"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Codificador de contexto"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;A&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Codificador objetivo (EMA)"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Embedding de contexto"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;E&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Embedding objetivo"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;D&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Predictor"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;F&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;G&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Embedding predicho"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;G&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;H&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Perdida en espacio latente"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;E&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;H&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La pérdida de entrenamiento compara esa predicción contra el embedding objetivo real, casi siempre con una distancia L2 o smooth L1, nunca contra los píxeles originales. Como el codificador objetivo nunca recibe gradiente directo y el predictor ve menos información que el codificador objetivo, el sistema no puede memorizar una salida constante para hacer trampa, y ese detalle es lo que previene el colapso representacional, el fracaso más común de este tipo de entrenamiento.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💭 Clave:&lt;/strong&gt; Sin la asimetría entre el codificador de contexto y el codificador objetivo (EMA más stop-gradient), el modelo encuentra el camino más corto: predecir siempre el mismo vector y minimizar la pérdida sin aprender nada.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I-JEPA divide una imagen en parches y oculta varios bloques grandes y contiguos, no parches sueltos al azar. Ocultar bloques grandes obliga al predictor a razonar sobre la estructura de la escena, dónde termina un objeto, qué hay detrás, en lugar de copiar textura del parche vecino, que es lo que pasa si el hueco es minúsculo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;flowchart&lt;/span&gt; &lt;span class="nv"&gt;LR&lt;/span&gt;
    &lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Imagen dividida en parches"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Bloque de contexto visible"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;A&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Bloques objetivo ocultos"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Codificador de contexto"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;E&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Codificador objetivo"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;D&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Predictor predice embeddings de C"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;E&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;G&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Embeddings reales de C"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;F&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;H&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Comparar con perdida L2"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;G&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;H&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;V-JEPA extiende la misma idea al tiempo. En vez de ocultar solo una región espacial, oculta bloques que se extienden a lo largo de varios cuadros consecutivos, así el predictor tiene que modelar tanto la estructura de la escena como su evolución, el primer paso hacia lo que Meta llama un modelo de mundo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ejemplos prácticos: así se ve una predicción de JEPA en código
&lt;/h2&gt;

&lt;p&gt;El mecanismo central de JEPA, predecir un embedding a partir de otro, se puede ilustrar con un fragmento mínimo en PyTorch. No es el código real de los repositorios de Meta, es un esqueleto que muestra la forma del problema.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch.nn&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Predictor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;768&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;proj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Linear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context_embedding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mask_tokens&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;proj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context_embedding&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;mask_tokens&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;context_embedding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;196&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;768&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# embeddings del bloque visible
&lt;/span&gt;&lt;span class="n"&gt;mask_tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;196&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;768&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;         &lt;span class="c1"&gt;# tokens posicionales del bloque oculto
&lt;/span&gt;&lt;span class="n"&gt;predictor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Predictor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;predicted_embedding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;predictor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context_embedding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mask_tokens&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;predicted_embedding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La salida es &lt;code&gt;torch.Size([1, 196, 768])&lt;/code&gt;: un batch, 196 parches (14x14 en una imagen de 224x224 con parches de 16 píxeles) y 768 dimensiones por embedding. Esa misma forma es la que debe tener el embedding objetivo real para poder compararlos con la función de pérdida.&lt;br&gt;
El codificador objetivo nunca recibe gradiente directo, solo un promedio móvil exponencial.&lt;/p&gt;
&lt;h2&gt;
  
  
  Cómo empezar con I-JEPA y V-JEPA
&lt;/h2&gt;

&lt;p&gt;Para correr el código oficial necesitás Python 3.9 o superior, Git y, para entrenar en serio, una GPU con soporte CUDA. Para solo cargar un checkpoint preentrenado alcanza con CPU, aunque mucho más lento. Los pasos siguientes son para Linux y macOS; en Windows corren igual dentro de WSL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/facebookresearch/ijepa.git
&lt;span class="nb"&gt;cd &lt;/span&gt;ijepa
python &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para V-JEPA el repositorio es distinto: &lt;code&gt;git clone https://github.com/facebookresearch/jepa.git&lt;/code&gt;, seguido de los mismos tres pasos de entorno virtual e instalación.&lt;/p&gt;

&lt;p&gt;No hay una forma de confirmar la instalación con un solo comando genérico, porque cada repositorio expone su propio script de evaluación. La señal de que todo cargó bien es que ese script termine e imprima la métrica final (la accuracy del linear probe, en el caso de I-JEPA) en vez de interrumpirse con un traceback de dependencias faltantes.&lt;/p&gt;

&lt;h2&gt;
  
  
  JEPA vs. modelos generativos y contrastivos
&lt;/h2&gt;

&lt;p&gt;JEPA no es la única forma de aprender sin etiquetas. Comparado con otras dos familias, la diferencia queda más clara.&lt;br&gt;
EnfoqueQué prediceVentajaLimitaciónJEPA (I-JEPA, V-JEPA)Embedding de una parte oculta a partir de una parte visibleNo gasta capacidad en detalles irrelevantes; más eficiente en datosNecesita trucos anticolapso (EMA, stop-gradient); no genera contenidoModelos generativos (difusión, autoregresivos de píxeles)Los datos originales completos, pixel por pixel o token por tokenSirven para crear contenido nuevo directamenteMás cómputo y datos para la misma calidad de representaciónAprendizaje contrastivo (SimCLR, CLIP)Si dos vistas vienen de la misma imagen, comparando embeddings completosRepresentaciones robustas sin reconstruir nadaDepende de aumentaciones manuales y bancos grandes de negativosNext-token prediction (LLMs de texto)El siguiente token de una secuenciaEscala muy bien con datos y cómputo en lenguajeEs una JEPA con vistas malas y alinea con otras modalidades solo a gran escala&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;flowchart&lt;/span&gt; &lt;span class="nv"&gt;TD&lt;/span&gt;
    &lt;span class="k"&gt;subgraph&lt;/span&gt; &lt;span class="nv"&gt;Generativo&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Modelo generativo"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;P1&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Entrada parcial"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;P2&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Decodificador"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;P2&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;P3&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Reconstruccion en espacio de pixeles"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;subgraph&lt;/span&gt; &lt;span class="nv"&gt;JEPA&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Arquitectura JEPA"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;J1&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Entrada parcial"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;J2&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Predictor"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;J2&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;J3&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Prediccion en espacio latente"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La elección no es ideológica. Si el objetivo final es generar una imagen o un texto, un modelo generativo sigue siendo la herramienta correcta. Si el objetivo es que un sistema entienda una escena para después actuar sobre ella, un robot, un auto autónomo, predecir en espacio latente rinde más por cada muestra de entrenamiento.&lt;/p&gt;

&lt;h2&gt;
  
  
  Casos de uso reales: de la clasificación de imágenes a los modelos de mundo
&lt;/h2&gt;

&lt;p&gt;Meta publicó I-JEPA en 2023 como su primer modelo de visión entrenado con esta arquitectura, pensado para tareas de clasificación y segmentación con pocas etiquetas disponibles. &lt;a href="https://arxiv.org/abs/2301.08243" rel="noopener noreferrer"&gt;El paper original&lt;/a&gt; lo mostró compitiendo con modelos contrastivos usando una fracción de su cómputo de entrenamiento.&lt;br&gt;
V-JEPA oculta bloques que se extienden en el tiempo, no solo en el espacio.&lt;br&gt;
V-JEPA, publicado en 2024, extendió la idea a video para tareas como reconocimiento de acciones y comprensión de movimiento físico. &lt;a href="https://arxiv.org/abs/2404.08471" rel="noopener noreferrer"&gt;El paper de V-JEPA&lt;/a&gt; lo presenta como un paso hacia modelos que entienden causa y efecto en el mundo físico, lo que LeCun describe como "modelos de mundo": sistemas capaces de predecir qué pasa después de una acción sin haber visto exactamente esa secuencia antes.&lt;/p&gt;

&lt;p&gt;El caso de uso más concreto hoy es el preentrenamiento: entrenar primero con JEPA sobre datos sin etiquetar y después afinar una cabeza pequeña para la tarea final, con muchas menos imágenes o videos etiquetados que los que necesitaría un modelo entrenado desde cero.&lt;/p&gt;

&lt;h2&gt;
  
  
  Errores comunes y buenas prácticas
&lt;/h2&gt;

&lt;p&gt;El error más citado en la literatura de aprendizaje autosupervisado es el colapso representacional: el modelo aprende a producir el mismo embedding para cualquier entrada, minimizando la pérdida sin aprender nada útil. JEPA lo evita con la asimetría entre codificadores, pero esa asimetría no es automática. Si el codificador objetivo se actualiza demasiado rápido (un EMA con momentum bajo) o demasiado lento, el riesgo de colapso vuelve.&lt;/p&gt;

&lt;p&gt;Otro error común es confundir JEPA con aprendizaje contrastivo. SimCLR y CLIP necesitan pares negativos, ejemplos que NO deben parecerse, y aumentaciones de datos cuidadosamente diseñadas. I-JEPA y V-JEPA no usan negativos explícitos; la asimetría arquitectónica hace ese trabajo.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Ojo:&lt;/strong&gt; La limitación real, y la razón por la que JEPA no reemplaza a los modelos generativos, es que sus embeddings no sirven para generar contenido directamente. Si el proyecto necesita un generador de imágenes o un chatbot, un modelo generativo sigue siendo la pieza correcta.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Profundizando: la hipótesis platónica y el teorema de representación
&lt;/h2&gt;

&lt;p&gt;El resultado más fuerte del paper de Balestriero y LeCun es lo que llaman el teorema de representación platónica. &lt;a href="https://arxiv.org/abs/2610.39302" rel="noopener noreferrer"&gt;Los autores&lt;/a&gt; demuestran que dos JEPA entrenadas por separado sobre modalidades distintas, texto e imagen, por ejemplo, convergen a la misma representación salvo una rotación, siempre que sus pares positivos sean "vistas buenas", dos observaciones reales de la misma escena. Con vistas malas, fragmentos arbitrarios de un documento, la convergencia tiene un límite acotado pero no desaparece.&lt;/p&gt;

&lt;p&gt;La consecuencia práctica, no solo teórica, es que esa rotación se puede calcular sin reentrenar nada. Los autores tomaron un encoder de texto y un encoder de imagen entrenados por separado, calcularon la rotación que los alinea y construyeron un generador de descripciones que obtuvo un &lt;strong&gt;CIDEr de 0,838 en COCO&lt;/strong&gt;, sin que los dos encoders hubieran visto jamás un par imagen-texto durante el entrenamiento. En un benchmark sin pares, ese mismo text JEPA superó el zero-shot de todos los modelos de lenguaje evaluados hasta 8.000 millones de parámetros, con 64% contra un máximo de 56% top-5 en ImageNet-100.&lt;/p&gt;

&lt;p&gt;Esto no significa que la arquitectura JEPA resuelva la hipótesis platónica de LeCun por completo. El propio paper aclara que el límite de desalineación depende de qué tan "buena" sea la vista, y construir vistas buenas para cada modalidad nueva, audio, sensores de robots, sigue siendo un problema de diseño abierto, no una receta universal.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: &lt;a href="https://telegra.ph/JEPA-qu%C3%A9-es-la-arquitectura-de-LeCun-que-no-genera-p%C3%ADxeles-11-02" rel="noopener noreferrer"&gt;Ver resumen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tu próximo paso: cloná el repositorio de I-JEPA, cargá un checkpoint preentrenado y corré el script de linear probing sobre un dataset chico propio para ver cuántas etiquetas necesitás realmente para una accuracy aceptable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿La arquitectura JEPA reemplaza a los transformers generativos?
&lt;/h3&gt;

&lt;p&gt;No. JEPA resuelve el problema de aprender representaciones sin etiquetas; los transformers generativos siguen siendo la herramienta cuando el objetivo final es producir texto, imagen o audio nuevo. Son complementarios, no rivales directos.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué diferencia a I-JEPA de V-JEPA?
&lt;/h3&gt;

&lt;p&gt;I-JEPA trabaja sobre imágenes estáticas y oculta bloques espaciales de parches. V-JEPA extiende la idea a video, ocultando bloques que se extienden en el tiempo para que el modelo aprenda también la dinámica de una escena.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿JEPA necesita pares negativos como el aprendizaje contrastivo?
&lt;/h3&gt;

&lt;p&gt;No. SimCLR y CLIP comparan pares positivos contra negativos explícitos. I-JEPA y V-JEPA evitan el colapso con la asimetría entre el codificador de contexto y el codificador objetivo, sin necesitar negativos.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Por qué next-token prediction alinea peor con la visión, según el paper de LeCun?
&lt;/h3&gt;

&lt;p&gt;Porque sus pares de entrenamiento son fragmentos de un mismo documento de texto, no dos observaciones reales de una escena compartida. El paper lo describe como una JEPA con "vistas malas", y por eso necesita mucha más escala para alinear con modelos de imagen.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Se puede usar JEPA para texto, no solo para imágenes y video?
&lt;/h3&gt;

&lt;p&gt;Sí. El propio paper de Balestriero y LeCun entrena un text JEPA de 109 millones de parámetros con vistas positivas y lo compara directamente contra modelos de lenguaje de hasta 72.000 millones de parámetros.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿JEPA sirve para generar imágenes o video nuevo?
&lt;/h3&gt;

&lt;p&gt;No directamente. Sus embeddings describen una escena, pero no están pensados para reconstruir píxeles. Generar contenido nuevo a partir de esos embeddings requiere acoplar un decodificador o un modelo generativo aparte.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://arxiv.org/abs/2610.39302" rel="noopener noreferrer"&gt;Balestriero y LeCun, "Proving and Improving the Platonic Representation Hypothesis with JEPAs" (arXiv, 2026)&lt;/a&gt;: el paper que motiva este artículo.- &lt;a href="https://arxiv.org/abs/2301.08243" rel="noopener noreferrer"&gt;Assran et al., "Self-Supervised Learning from Images with a Joint-Embedding Predictive Architecture" (arXiv, 2023)&lt;/a&gt;: el paper original de I-JEPA.- &lt;a href="https://arxiv.org/abs/2404.08471" rel="noopener noreferrer"&gt;Bardes et al., "V-JEPA: Video Joint-Embedding Predictive Architecture for Self-Supervised Visual Learning" (arXiv, 2024)&lt;/a&gt;: el paper original de V-JEPA.- &lt;a href="https://github.com/facebookresearch/ijepa" rel="noopener noreferrer"&gt;Repositorio oficial de I-JEPA en GitHub&lt;/a&gt;: código y checkpoints preentrenados.- &lt;a href="https://github.com/facebookresearch/jepa" rel="noopener noreferrer"&gt;Repositorio oficial de V-JEPA en GitHub&lt;/a&gt;: código y checkpoints preentrenados.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>technology</category>
      <category>science</category>
      <category>programming</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Cifrado de hardware en USB y discos: cómo saber si es real</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Sun, 01 Nov 2026 20:30:40 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/cifrado-de-hardware-en-usb-y-discos-como-saber-si-es-real-3p63</link>
      <guid>https://dev.to/lu1tr0n/cifrado-de-hardware-en-usb-y-discos-como-saber-si-es-real-3p63</guid>
      <description>&lt;p&gt;Lenovo vendía una memoria USB con sensor de huella digital anunciada como cifrada. Un desarmado posterior, documentado en un &lt;a href="https://www.reddit.com/r/technology/comments/1xl2pr3/lenovos_encrypted_fingerprint_usb_drive_is_just/" rel="noopener noreferrer"&gt;hilo de Reddit&lt;/a&gt;, mostró que adentro no había más que una tarjeta microSD genérica: ningún chip criptográfico, ningún motor AES, nada que cifrara un solo byte. El sensor biométrico apenas desbloqueaba una aplicación de Windows; la memoria, leída directo con cualquier lector de tarjetas, entregaba los archivos en texto plano.&lt;/p&gt;

&lt;p&gt;El caso no es un bug aislado de un fabricante. Es el síntoma de un mercado entero donde la palabra 'cifrado' aparece en la caja sin que exista una propiedad verificable detrás. Esta nota explica qué hace real al cifrado de hardware, qué estándares lo certifican y cómo comprobarlo en cualquier USB o disco externo antes de confiarle datos sensibles.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;El cifrado de hardware real exige un chip AES dedicado que cifra los datos antes de que lleguen a la memoria flash.- Un sensor de huella digital que solo desbloquea una app de Windows no cifra nada: la memoria sigue legible en cualquier lector de tarjetas.- FIPS 140-2 o FIPS 140-3 validados en el registro CMVP de NIST son la única prueba verificable de un módulo criptográfico real.- TCG Opal define cómo un SSD autocifrado protege la clave de los datos sin exponerla al sistema operativo.- Comandos como hdparm -I y sedutil-cli --scan revelan si un disco soporta y tiene activo el cifrado por hardware.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Qué es el cifrado de hardware?
&lt;/h2&gt;

&lt;p&gt;El cifrado de hardware es la técnica en la que un chip dedicado dentro del controlador de un disco o memoria USB cifra y descifra cada byte con AES antes de escribirlo o leerlo de la memoria flash, sin que el sistema operativo ni ningún programa intervengan en el proceso ni tengan acceso directo a la clave.&lt;/p&gt;

&lt;p&gt;La diferencia con el cifrado por software (BitLocker en modo estándar, VeraCrypt, LUKS) está en la ubicación de la clave y del cómputo. En el cifrado por software, el sistema operativo carga la clave en la RAM y usa el procesador principal para cifrar cada bloque. En una unidad autocifrada real, la clave vive dentro del controlador, y ni un volcado de memoria del equipo la expone.&lt;/p&gt;

&lt;p&gt;Un sensor de huella digital, por sí solo, no define nada sobre dónde ocurre el cifrado. Puede ser la llave de un cifrado legítimo, como en una unidad certificada, o puede ser apenas el gatillo de una ventana de inicio de sesión de una app, como en el caso de Lenovo. La huella identifica a la persona, pero no dice nada sobre qué le pasa a los datos después.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué importa
&lt;/h2&gt;

&lt;p&gt;El riesgo no es solo perder un archivo. Una empresa que compra 500 memorias USB 'cifradas' para su equipo de ventas y confía en esa palabra está exponiendo datos de clientes bajo una falsa sensación de cumplimiento normativo. Si el dispositivo se pierde y en realidad nunca cifró nada, cualquier marco regulatorio que exima de notificación a equipos cifrados deja de aplicar, y la empresa queda expuesta a una notificación de brecha que creía evitada.&lt;/p&gt;

&lt;p&gt;El sensor de huella no es una medida de seguridad, sino una cerradura decorativa sobre una memoria sin ninguna protección real, cuando el fabricante nunca implementó cifrado de hardware genuino.&lt;/p&gt;

&lt;p&gt;Esto no es exclusivo de pendrives baratos. En el pasado, investigaciones académicas sobre SSD comerciales que anunciaban cifrado por hardware hallaron implementaciones defectuosas que permitían evadir la clave sin conocer la contraseña, lo que llevó a Microsoft a dejar de confiar por defecto en el cifrado por hardware reportado por el propio disco para proteger volúmenes con BitLocker. El problema de fondo es siempre el mismo: una afirmación sin verificación independiente.&lt;/p&gt;

&lt;p&gt;El problema se repite fuera de los USB de bajo costo: discos externos, SSD portátiles y hasta algunos NAS domésticos usan la palabra 'cifrado' en el empaque sin publicar jamás un estándar, un algoritmo verificable o un número de certificación. La única forma de saber si hay algo real detrás es preguntar por el estándar, no por el adjetivo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo funciona por dentro
&lt;/h2&gt;

&lt;p&gt;Una unidad autocifrada (SED, por &lt;em&gt;self-encrypting drive&lt;/em&gt;) separa dos claves. La Media Encryption Key (MEK) es la que realmente cifra cada bloque de datos con AES, casi siempre en modo XTS. Esa clave se genera una sola vez, dentro del chip, y nunca sale de ahí.&lt;/p&gt;

&lt;p&gt;La segunda clave es la Key Encryption Key (KEK), derivada del PIN, la contraseña o, en dispositivos biométricos bien diseñados, de un secreto que el sensor de huella libera tras verificar la identidad. La KEK no cifra los datos: cifra a la MEK, que queda guardada en una zona reservada del disco. Sin la KEK correcta, la MEK sigue ahí, pero inutilizable.&lt;/p&gt;

&lt;p&gt;Esta separación es la que permite el borrado criptográfico instantáneo: descartar la MEK, sin tocar un solo bit de los datos reales, vuelve ilegible todo el contenido en milisegundos, porque ya no existe ninguna clave capaz de descifrarlo. Es el mecanismo detrás de funciones como 'borrado seguro' en SSD empresariales, y la razón por la que un disco de varios terabytes puede darse de baja de forma segura en segundos.&lt;br&gt;
El estándar TCG Opal, publicado por Trusted Computing Group, define cómo un SSD autocifrado gestiona su clave sin exponerla al sistema operativo.&lt;br&gt;
El estándar que define cómo deben comportarse estas piezas en un SSD o HDD es TCG Opal, publicado por el &lt;a href="https://trustedcomputinggroup.org/" rel="noopener noreferrer"&gt;Trusted Computing Group&lt;/a&gt;. Las memorias USB no siguen necesariamente Opal, pensado originalmente para SATA y NVMe, pero las serias documentan un esquema equivalente: un controlador con motor AES, una KEK derivada del PIN o la huella, y una MEK que nunca cruza el bus USB en claro.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;flowchart&lt;/span&gt; &lt;span class="nv"&gt;TD&lt;/span&gt;
    &lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Huella digital del usuario"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Que desbloquea el sensor?"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"Solo una app de Windows"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"La app muestra los archivos"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Memoria flash sin cifrar"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"Deriva la clave del controlador"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;E&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Chip AES del controlador"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;E&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Memoria flash cifrada con AES-XTS"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La memoria de Lenovo no tenía nada de esto. No había MEK, no había KEK, no había motor AES. Había una tarjeta microSD estándar, del tipo que se vende suelta en cualquier tienda, detrás de un lector de huellas conectado únicamente a la lógica de la aplicación de escritorio.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo verificar en la práctica
&lt;/h2&gt;

&lt;p&gt;Antes de confiar en la etiqueta de un USB o disco externo, hay tres comprobaciones concretas que se pueden hacer sin desarmar nada.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Revisar el feature set ATA Security con hdparm
&lt;/h3&gt;

&lt;p&gt;En Linux, instalá hdparm (&lt;code&gt;sudo apt install hdparm&lt;/code&gt; en Debian o Ubuntu, &lt;code&gt;sudo dnf install hdparm&lt;/code&gt; en Fedora) y consultá el bloque de seguridad del disco:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;hdparm &lt;span class="nt"&gt;-I&lt;/span&gt; /dev/sdb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Un disco con el feature set ATA Security activo muestra algo como esto en la salida:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Security: 
    Master password revision code = 65534
        supported
        enabled
    not locked
        frozen
    not expired: security count
        supported: enhanced erase
    2min for SECURITY ERASE UNIT.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si el bloque dice 'not supported' o directamente no aparece, el disco no implementa el feature set ATA Security. Eso es normal en la mayoría de memorias USB simples y no es, por sí solo, prueba de fraude, pero combinado con la ausencia de cualquier otra documentación técnica es la primera señal de alerta.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Confirmar TCG Opal con sedutil-cli
&lt;/h3&gt;

&lt;p&gt;Para SSD y unidades autocifradas que afirman cumplir TCG Opal, la Drive Trust Alliance mantiene sedutil-cli, una herramienta de línea de comandos que no viene empaquetada en todos los repositorios, así que lo más seguro es compilarla desde su repositorio oficial en GitHub o instalar el paquete si tu distribución lo ofrece. El escaneo básico es:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;sedutil-cli &lt;span class="nt"&gt;--scan&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El comando lista cada disco conectado junto a un indicador del nivel de soporte Opal detectado, por ejemplo 2 para Opal 2.0. Un guion en esa columna significa que el disco no implementa Opal, sin importar lo que diga el empaque.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Verificar el certificado FIPS en el CMVP de NIST
&lt;/h3&gt;

&lt;p&gt;Cuando el fabricante anuncia FIPS 140-2 o FIPS 140-3, tiene que existir un número de certificado público. Buscalo en el &lt;a href="https://csrc.nist.gov/projects/cryptographic-module-validation-program" rel="noopener noreferrer"&gt;Cryptographic Module Validation Program de NIST&lt;/a&gt;: ahí aparece el nombre del módulo, el fabricante y el nivel de seguridad validado, del 1 al 4. Si el modelo exacto no figura en esa lista, el 'FIPS' de la caja es solo marketing, aunque el algoritmo interno sea AES real.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sequenceDiagram
    participant U as Usuario
    participant H as Host
    participant C as Controlador del disco
    U-&amp;gt;&amp;gt;H: ingresa PIN o huella
    H-&amp;gt;&amp;gt;C: envia credencial de autenticacion
    C-&amp;gt;&amp;gt;C: deriva la Key Encryption Key
    C-&amp;gt;&amp;gt;C: desbloquea la Media Encryption Key
    C--&amp;gt;&amp;gt;H: datos descifrados en tiempo real
    Note over C: la clave nunca sale del chip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En Windows, &lt;code&gt;manage-bde -status C:&lt;/code&gt; muestra si BitLocker usa cifrado por hardware (eDrive) o cae a software porque el disco no lo soporta. En macOS, &lt;code&gt;diskutil info&lt;/code&gt; no distingue hardware de software en discos externos de terceros, así que para esos equipos conviene apoyarse directamente en el certificado FIPS publicado por el fabricante.&lt;/p&gt;

&lt;h2&gt;
  
  
  Casos de uso reales
&lt;/h2&gt;

&lt;p&gt;Las empresas que manejan datos regulados (salud, finanzas, gobierno, defensa) suelen exigir por contrato que cualquier memoria USB corporativa tenga FIPS 140-2 nivel 3 validado. Líneas como Apricorn Aegis Secure Key, iStorage datAshur PRO o Kingston IronKey publican su número de certificado y su nivel exacto en su documentación, precisamente porque sus clientes lo van a verificar antes de firmar la compra.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Ojo:&lt;/strong&gt; El borrado criptográfico de una unidad autocifrada destruye la clave en milisegundos y vuelve ilegibles todos los datos, pero esa garantía solo existe si el cifrado era real desde el diseño: en una memoria como la de Lenovo no hay clave que borrar.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;En el sector salud, perder un USB con historiales clínicos sin cifrado real puede disparar la obligación de notificar a cada paciente afectado. Algunos marcos regulatorios reducen esa obligación cuando el dispositivo tenía cifrado certificado, así que el certificado no es un detalle burocrático: es lo que decide si hay que mandar miles de cartas de notificación.&lt;/p&gt;

&lt;p&gt;Fuera del mundo corporativo, el caso de uso más simple es el de cualquier persona que viaja con datos sensibles (contratos, historiales médicos propios, claves de acceso) en una memoria USB. Para ese uso, una unidad autocifrada certificada justifica su sobreprecio frente a un pendrive genérico con un sticker de 'AES-256' sin respaldo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Errores comunes y buenas prácticas
&lt;/h2&gt;

&lt;p&gt;Confundir el algoritmo con la implementación es el error más común. AES-256 es un algoritmo público y gratuito: cualquiera puede escribir 'AES-256' en una caja sin que eso implique que el chip adentro lo ejecuta, ni que la clave esté protegida, ni que el sensor biométrico tenga algo que ver con el cifrado.&lt;/p&gt;

&lt;p&gt;Asumir que todo lo que trae lector de huella es más seguro que una contraseña es otro error. Un sensor biométrico barato sin motor criptográfico es, en la práctica, más débil que una contraseña larga: no hay forma de 'cambiar' una huella comprometida, y en el caso de Lenovo ni siquiera estaba protegiendo nada.&lt;/p&gt;

&lt;p&gt;El feature set ATA Security, más viejo que TCG Opal, tiene un historial conocido de contraseñas maestras de fábrica que algunos fabricantes nunca rotaron ni documentaron para rotar, lo que en ciertos modelos antiguos permitía desbloquear el disco sin el PIN del usuario legítimo. Por eso las implementaciones modernas migraron a TCG Opal, que no depende de una contraseña maestra universal del fabricante.&lt;/p&gt;

&lt;p&gt;Comunidades de reparación y desarmado, como la que destapó el caso Lenovo en Reddit, terminan siendo el control de calidad real de este mercado: revisar un video o hilo de desarmado del modelo exacto antes de comprar vale más que leer la descripción del producto.&lt;/p&gt;

&lt;p&gt;Buena práctica: pedí siempre el número de certificado FIPS antes de comprar, no después. Un fabricante serio lo tiene impreso en la hoja de datos del producto, no escondido en un correo de soporte.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparativa con alternativas
&lt;/h2&gt;

&lt;p&gt;No todo lo que se vende como 'cifrado' ocupa el mismo nivel de confianza. La tabla siguiente ordena las tres categorías reales que existen en el mercado de USB y discos externos.&lt;br&gt;
Tipo de 'cifrado'Qué protege en realidadCómo verificarloCuándo confiarApp o sensor biométrico sin chip criptográfico (caso Lenovo)Nada: solo bloquea una interfaz, la memoria flash queda legible con cualquier lectorVideo o reporte de desarmado del modelo exactoNunca, para datos sensiblesCifrado por hardware sin certificación independienteCifra los bytes en el controlador, pero sin auditoría externa de la implementaciónhdparm -I o documentación técnica del fabricanteUso personal de bajo riesgoUnidad autocifrada FIPS 140-2 o 140-3 validadaCifrado AES-XTS auditado por un laboratorio acreditado y registrado en NIST CMVPNúmero de certificado contra el buscador de CMVPEmpresas, salud, finanzas, gobiernoEl programa CMVP de NIST es el único registro público donde se valida un módulo criptográfico bajo FIPS 140-2 o FIPS 140-3.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;flowchart&lt;/span&gt; &lt;span class="nv"&gt;TD&lt;/span&gt;
    &lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Dispositivo anuncia cifrado"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Tiene numero de certificado FIPS verificable?"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"Si, aparece en CMVP"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Cifrado de hardware validado"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"No, o no lo publica"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Soporta TCG Opal o ATA Security?"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;D&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"Si, confirmado con hdparm o sedutil-cli"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;E&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Cifrado por hardware probable, sin certificar"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;D&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"No, solo una app o sensor biometrico"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Cifrado de marketing: no confiar"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La fila del medio es la más común y la más ambigua: muchos pendrives decentes de marca caen ahí. No son una estafa como el caso Lenovo, pero tampoco ofrecen la garantía auditada de un módulo FIPS. Y hay un escenario donde ni la fila de arriba conviene: si necesitás sincronizar un mismo contenedor cifrado entre Windows, macOS y Linux sin depender de un sensor físico que puede fallar o de un PIN de recuperación con intentos limitados, un contenedor de software como VeraCrypt sigue siendo más práctico que una unidad autocifrada atada a un único lector biométrico.&lt;/p&gt;

&lt;h2&gt;
  
  
  Profundizando
&lt;/h2&gt;

&lt;p&gt;AES-XTS, el modo que usan casi todas las unidades autocifradas, fue diseñado específicamente para discos: cifra cada sector de forma independiente para que un cambio de un solo bit en el texto plano no afecte a los sectores vecinos, algo necesario cuando el almacenamiento se accede en bloques fijos y no como un flujo continuo.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💭 Clave:&lt;/strong&gt; La separación entre MEK y KEK es lo que vuelve posible cambiar el PIN de una unidad autocifrada en segundos: solo se re-cifra la MEK, unos pocos bytes, nunca los datos completos, sin importar cuántos terabytes tenga el disco.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Los niveles de seguridad FIPS 140-2 y 140-3, del 1 al 4, no miden el algoritmo, sino la implementación física: resistencia a manipulación del hardware, borrado de claves ante intentos de apertura, calidad del generador de números aleatorios. Un módulo de nivel 3, el más común en memorias USB corporativas, exige evidencia física de sabotaje y mecanismos de respuesta ante intrusión.&lt;/p&gt;

&lt;p&gt;El propio Trusted Computing Group documenta Opal 2.0 con estados explícitos para la unidad: Locked, Unlocked, Frozen, y un contador de intentos (Try Limit) que, al agotarse, puede bloquear el disco hasta un reinicio o forzar un borrado criptográfico, según cómo lo configure el administrador. Nada de esto existe en un dispositivo que, como el de Lenovo, nunca implementó el estándar.&lt;/p&gt;

&lt;p&gt;Una limitación real que vale aclarar: incluso un cifrado de hardware perfectamente implementado no protege nada si el disco queda desbloqueado y conectado. El cifrado defiende contra la pérdida o el robo del dispositivo apagado, no contra alguien que lo use mientras está desbloqueado. Eso es trabajo de otras capas de seguridad, no del chip AES.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: &lt;a href="https://telegra.ph/Cifrado-de-hardware-en-USB-y-discos-c%C3%B3mo-saber-si-es-real-11-01" rel="noopener noreferrer"&gt;Ver resumen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tu próximo paso: conectá un disco externo o USB que tengas a mano, corré &lt;code&gt;sudo hdparm -I /dev/sdX&lt;/code&gt; y revisá si el bloque Security aparece como supported antes de confiar en la palabra 'cifrado' de cualquier caja.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿El cifrado de hardware de un USB es siempre real si dice AES-256 en la caja?
&lt;/h3&gt;

&lt;p&gt;No. AES-256 describe un algoritmo público, no una certificación. Lo único que confirma una implementación real y auditada es un número de certificado FIPS 140-2 o FIPS 140-3 verificable en el CMVP de NIST.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué diferencia hay entre una unidad autocifrada y el cifrado por software como VeraCrypt?
&lt;/h3&gt;

&lt;p&gt;VeraCrypt y LUKS cifran con el procesador del equipo y guardan la clave en la RAM del sistema mientras el volumen está montado. Una unidad autocifrada hace el trabajo dentro del propio controlador del disco, y la clave nunca llega a la memoria RAM del equipo anfitrión.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo compruebo si mi disco soporta TCG Opal?
&lt;/h3&gt;

&lt;p&gt;Con &lt;code&gt;sedutil-cli --scan&lt;/code&gt; desde Linux, o preguntando directamente al fabricante por el nivel de Opal soportado, por ejemplo Opal 2.0. La ausencia de una respuesta técnica suele ser la respuesta.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Un sensor de huella digital reemplaza a una contraseña fuerte?
&lt;/h3&gt;

&lt;p&gt;Solo si ese sensor efectivamente deriva o libera la Key Encryption Key del controlador. Si apenas desbloquea una aplicación, como en el caso de Lenovo, no reemplaza nada: la memoria sigue expuesta a cualquiera que la lea directo.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué significa que un módulo criptográfico tenga validación FIPS de nivel 3?
&lt;/h3&gt;

&lt;p&gt;Significa que, además del algoritmo correcto, el hardware fue evaluado por resistencia física a manipulación y por borrar sus claves ante un intento de apertura detectado. Es el nivel que suelen exigir los contratos corporativos y gubernamentales.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué pasó exactamente con el USB con huella digital de Lenovo?
&lt;/h3&gt;

&lt;p&gt;Según el desarmado documentado en Reddit, el dispositivo anunciado como cifrado resultó ser una tarjeta microSD genérica sin ningún componente criptográfico, con un lector de huella que solo controlaba el acceso a una aplicación de escritorio.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.reddit.com/r/technology/comments/1xl2pr3/lenovos_encrypted_fingerprint_usb_drive_is_just/" rel="noopener noreferrer"&gt;Reddit r/technology&lt;/a&gt;: hilo donde se documenta el desarmado del USB con huella digital de Lenovo.- &lt;a href="https://csrc.nist.gov/projects/cryptographic-module-validation-program" rel="noopener noreferrer"&gt;NIST, Cryptographic Module Validation Program (CMVP)&lt;/a&gt;: registro oficial donde se verifica un número de certificado FIPS 140-2 o 140-3.- &lt;a href="https://en.wikipedia.org/wiki/Self-encrypting_drive" rel="noopener noreferrer"&gt;Wikipedia, Self-encrypting drive&lt;/a&gt;: explicación técnica del funcionamiento de las unidades autocifradas (SED).- &lt;a href="https://trustedcomputinggroup.org/" rel="noopener noreferrer"&gt;Trusted Computing Group&lt;/a&gt;: organización que publica el estándar TCG Opal usado en discos autocifrados.- hdparm: utilidad de Linux usada para consultar las características de seguridad ATA de un disco.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>technology</category>
      <category>science</category>
      <category>programming</category>
      <category>discuss</category>
    </item>
    <item>
      <title>CVE-2026-98432: Linux parchó el UAF en TCP, Ubuntu y RHEL siguen expuestos</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Sun, 01 Nov 2026 14:31:27 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/cve-2026-98432-linux-parcho-el-uaf-en-tcp-ubuntu-y-rhel-siguen-expuestos-260o</link>
      <guid>https://dev.to/lu1tr0n/cve-2026-98432-linux-parcho-el-uaf-en-tcp-ubuntu-y-rhel-siguen-expuestos-260o</guid>
      <description>&lt;p&gt;Un atacante remoto, sin usuario ni contraseña, puede leer memoria del kernel, corromperla o tumbar el servidor con solo mandarle paquetes de conexión TCP: así describe la autoridad de numeración del propio kernel de Linux la &lt;a href="https://nvd.nist.gov/vuln/detail/CVE-2026-98432" rel="noopener noreferrer"&gt;CVE-2026-98432&lt;/a&gt;, la falla crítica de Linux que corrigió este mes con un parche de cuatro líneas.&lt;/p&gt;

&lt;p&gt;El bug vive desde la versión 4.4, lanzada en 2016, en el código que procesa el saludo TCP sobre IPv4. Red Hat subió su calificación a Critical el 30 de octubre, Ubuntu sigue marcando sus kernels como vulnerables, y Anthropic dice que su modelo Claude escribió un exploit que da acceso root remoto sin necesitar ninguna credencial.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;CVE-2026-98432: use-after-free crítico (CVSS 9.8) en TCP de Linux, explotable sin credenciales.- Anthropic reportó el bug y dice que Claude escribió un exploit root funcional para servidores con multipath TCP.- Red Hat subió la calificación a Critical el 30 de octubre y lista RHEL 8, 9 y 10 sin parche aún.- Ubuntu marca la falla como vulnerable en todas sus versiones al 31 de octubre de 2026, sin parche publicado.- El equipo de seguridad de Go advierte que sus programas abren listeners multipath TCP por defecto, ampliando el riesgo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Qué es la falla crítica de Linux
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://nvd.nist.gov/vuln/detail/CVE-2026-98432" rel="noopener noreferrer"&gt;CVE-2026-98432&lt;/a&gt; es la falla crítica de Linux que corrige un use-after-free en el código IPv4 que procesa el saludo TCP. El kernel libera la memoria que guarda las opciones IP de una solicitud de conexión y, por una condición de carrera, otra ruta del código todavía puede leerla o escribirla después de liberada.&lt;br&gt;
El parche definitivo cambia solo cuatro líneas en el subsistema de red del kernel.&lt;/p&gt;
&lt;h2&gt;
  
  
  Qué pasó
&lt;/h2&gt;

&lt;p&gt;El kernel estable de Linux publicó el parche el 11 y el 15 de octubre de 2026. Las versiones corregidas son 5.10.272, 5.15.223, 6.1.190, 6.6.159, 6.12.113, 6.18.56, 7.2.10 y 7.3. El registro se publicó en &lt;a href="https://www.cve.org/CVERecord?id=CVE-2026-98432" rel="noopener noreferrer"&gt;cve.org&lt;/a&gt; el 15 de octubre, y la autoridad de numeración del kernel le puso 9.8 sobre 10 en CVSS 3.1: la nota máxima para un fallo que no necesita usuario ni interacción.&lt;/p&gt;

&lt;p&gt;El 30 de octubre, Red Hat subió su propia calificación de Important (8.1) a Critical (9.8) y publicó un boletín con una mitigación temporal. Al día siguiente, a las 5:15 PM CDT del 31 de octubre, el rastreador de &lt;a href="https://ubuntu.com/security/CVE-2026-98432" rel="noopener noreferrer"&gt;Ubuntu&lt;/a&gt; todavía marcaba el paquete &lt;code&gt;linux&lt;/code&gt; como "Vulnerable" en cada versión soportada, sin ningún aviso de seguridad publicado. Red Hat Enterprise Linux 8, 9 y 10, junto con OpenShift Container Platform, aparecen en la misma situación: afectados, sin parche disponible.&lt;/p&gt;

&lt;p&gt;No todas las distribuciones van atrasadas. AlmaLinux tiene kernels corregidos para sus versiones 8, 9 y 10 en su repositorio de pruebas desde el 30 de octubre, un día antes que Red Hat, de quien deriva su base. Amazon Linux ya corrigió todos sus kernels. Debian, SUSE Enterprise y Oracle UEK también cuentan con versiones parchadas desde antes de que Red Hat subiera la calificación.&lt;br&gt;
DistribuciónEstado al 31 de octubre de 2026Versión corregidaUbuntuVulnerable en todas las versiones soportadasSin kernel corregido todavíaRed Hat Enterprise Linux (8, 9, 10)Afectado, calificación subida a Critical el 30 de octubreSin kernel corregido todavíaAlmaLinux (8, 9, 10)Kernel corregido en repositorio de pruebas desde el 30 de octubrekernel-4.18.0-553.180.2.el8_10 y equivalentesAmazon LinuxTodos los kernels ya corregidosDisponibleDebian / SUSE Enterprise / Oracle UEKKernels ya corregidosDisponible&lt;/p&gt;
&lt;h2&gt;
  
  
  Contexto e historia
&lt;/h2&gt;

&lt;p&gt;La vulnerabilidad del kernel de Linux la reportó Xinyang Ge, investigador de Anthropic. El commit que la corrige, titulado "ipv4: free inet_opt and ireq_opt after an RCU grace period", lo firma Eric Dumazet y lo revisó Kuniyuki Iwashima, dos de los mantenedores habituales del subsistema de red del kernel.&lt;/p&gt;

&lt;p&gt;El fallo de seguridad en el kernel arrastra siete años de historial: la primera versión afectada es la 4.4, y solo queda fuera de alcance la rama de 4.4 a 5.4 porque ya llegó a su fin de vida upstream y no recibirá parche oficial del proyecto Linux; las distribuciones que aún la mantienen deben portar el fix por su cuenta. El cambio real en el código fuente, según detalla &lt;a href="https://atlasum.net/blog/cve-2026-98432-linux-ipv4-tcp-uaf" rel="noopener noreferrer"&gt;Atlas&lt;/a&gt;, ocupa apenas cuatro líneas: mover la liberación de la memoria a después del período de gracia de RCU, el mecanismo que usa el kernel para saber cuándo ya nadie más está leyendo una estructura antes de borrarla.&lt;/p&gt;
&lt;h2&gt;
  
  
  Detalles técnicos: por qué funciona el exploit
&lt;/h2&gt;

&lt;p&gt;Cuando llega un paquete SYN con opciones IPv4 (por ejemplo, un registro de ruta), el kernel crea un "request socket" temporal y guarda esas opciones en dos punteros, &lt;code&gt;inet_opt&lt;/code&gt; e &lt;code&gt;ireq_opt&lt;/code&gt;. Si la solicitud expira o se procesa fuera de orden, una ruta del código libera esa memoria; si, casi al mismo tiempo, otra ruta sigue completando el saludo TCP con el ACK final, intenta leer la memoria que la primera ruta ya liberó.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;sequenceDiagram&lt;/span&gt;
&lt;span class="nv"&gt;participant&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="nv"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;Atacante&lt;/span&gt; &lt;span class="nv"&gt;remoto&lt;/span&gt;
&lt;span class="nv"&gt;participant&lt;/span&gt; &lt;span class="nv"&gt;K&lt;/span&gt; &lt;span class="nv"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;Kernel&lt;/span&gt; &lt;span class="nv"&gt;de&lt;/span&gt; &lt;span class="nv"&gt;Linux&lt;/span&gt;
&lt;span class="nv"&gt;participant&lt;/span&gt; &lt;span class="nv"&gt;M&lt;/span&gt; &lt;span class="nv"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;Opciones&lt;/span&gt; &lt;span class="nv"&gt;IPv4&lt;/span&gt; &lt;span class="nv"&gt;en&lt;/span&gt; &lt;span class="nv"&gt;memoria&lt;/span&gt;
&lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;K&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;env&lt;/span&gt;&lt;span class="err"&gt;í&lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;SYN&lt;/span&gt; &lt;span class="nv"&gt;con&lt;/span&gt; &lt;span class="nv"&gt;opciones&lt;/span&gt; &lt;span class="nv"&gt;IPv4&lt;/span&gt;
&lt;span class="nv"&gt;K&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;asigna&lt;/span&gt; &lt;span class="nv"&gt;ireq_opt&lt;/span&gt; &lt;span class="nv"&gt;para&lt;/span&gt; &lt;span class="nv"&gt;la&lt;/span&gt; &lt;span class="nv"&gt;solicitud&lt;/span&gt;
&lt;span class="nv"&gt;Note&lt;/span&gt; &lt;span class="nv"&gt;over&lt;/span&gt; &lt;span class="nv"&gt;K&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;el&lt;/span&gt; &lt;span class="nv"&gt;temporizador&lt;/span&gt; &lt;span class="nv"&gt;de&lt;/span&gt; &lt;span class="nv"&gt;la&lt;/span&gt; &lt;span class="nv"&gt;solicitud&lt;/span&gt; &lt;span class="nv"&gt;vence&lt;/span&gt;
&lt;span class="nv"&gt;K&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;libera&lt;/span&gt; &lt;span class="nv"&gt;ireq_opt&lt;/span&gt; &lt;span class="nv"&gt;tras&lt;/span&gt; &lt;span class="nv"&gt;el&lt;/span&gt; &lt;span class="nv"&gt;per&lt;/span&gt;&lt;span class="err"&gt;í&lt;/span&gt;&lt;span class="nv"&gt;odo&lt;/span&gt; &lt;span class="nv"&gt;de&lt;/span&gt; &lt;span class="nv"&gt;gracia&lt;/span&gt; &lt;span class="nv"&gt;RCU&lt;/span&gt;
&lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;K&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;env&lt;/span&gt;&lt;span class="err"&gt;í&lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;el&lt;/span&gt; &lt;span class="nv"&gt;ACK&lt;/span&gt; &lt;span class="nv"&gt;final&lt;/span&gt; &lt;span class="nv"&gt;del&lt;/span&gt; &lt;span class="nv"&gt;saludo&lt;/span&gt;
&lt;span class="nv"&gt;K&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;intenta&lt;/span&gt; &lt;span class="nv"&gt;leer&lt;/span&gt; &lt;span class="nv"&gt;ireq_opt&lt;/span&gt; &lt;span class="nv"&gt;ya&lt;/span&gt; &lt;span class="nv"&gt;liberado&lt;/span&gt;
&lt;span class="nv"&gt;Note&lt;/span&gt; &lt;span class="nv"&gt;over&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;after&lt;/span&gt; &lt;span class="nv"&gt;free&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;fuga&lt;/span&gt; &lt;span class="nv"&gt;o&lt;/span&gt; &lt;span class="nv"&gt;corrupci&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="nv"&gt;n&lt;/span&gt; &lt;span class="nv"&gt;de&lt;/span&gt; &lt;span class="nv"&gt;memoria&lt;/span&gt; &lt;span class="nv"&gt;del&lt;/span&gt; &lt;span class="nv"&gt;kernel&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ese es el patrón clásico de un use-after-free: dos caminos de ejecución que no se coordinan sobre quién es dueño de un bloque de memoria. Según la puntuación de la propia CNA del kernel, las consecuencias van desde exponer contenido del heap del kernel al peer remoto, hasta corromper memoria o colgar la máquina.&lt;/p&gt;

&lt;p&gt;IPv6 no está afectado por este problema en particular: el propio mensaje del commit lo aclara, porque esa pila de red no comparte el mismo camino de opciones IP. La ventana de ataque tampoco depende de ninguna aplicación en particular, porque el saludo TCP se procesa dentro del kernel antes de que la conexión llegue a cualquier programa de espacio de usuario.&lt;br&gt;
Multipath TCP combina varias rutas de red en una sola conexión, y los programas en Go lo activan por defecto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Impacto y análisis
&lt;/h2&gt;

&lt;p&gt;La vulnerabilidad del kernel de Linux alcanza a cualquier servidor, físico o virtual, que use un kernel 4.4 o posterior sin el parche, y eso incluye a los contenedores: un contenedor comparte el kernel del host, así que una imagen nueva no cambia nada si la máquina que la ejecuta sigue vulnerable.&lt;/p&gt;

&lt;p&gt;Lo que amplía el riesgo real es Multipath TCP (MPTCP), la extensión que permite combinar varias rutas de red en una sola conexión. El exploit que construyó Claude necesita, según Anthropic, "servidores Linux con un listener multipath TCP" y ninguna credencial. El equipo de seguridad de Go advierte que los programas escritos en ese lenguaje abren ese tipo de listener por defecto, así que la configuración que requiere el ataque es más común de lo que parecía al principio: no depende de que un administrador la haya activado a propósito.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Ojo:&lt;/strong&gt; si tu servidor corre un binario de Go con un listener TCP, probablemente tenga multipath TCP activado sin que lo hayas pedido. Revisalo antes de asumir que el ataque no te toca.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;El episodio también deja un dato incómodo sobre el estado de la inteligencia artificial en seguridad: la misma falla crítica de Linux que un investigador humano reportó terminó con una prueba de concepto escrita por un modelo, capaz de convertir un bug remoto en acceso root sin usuario ni contraseña. Anthropic no publicó el exploit, pero que un modelo pueda llegar a ese resultado cambia el cálculo de cuánto tiempo pasa entre que se conoce un bug y que alguien lo convierte en un arma.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué sigue
&lt;/h2&gt;

&lt;p&gt;Lo primero es revisar el rastreador de tu propia distribución, porque los números de versión no coinciden entre el kernel upstream y el que empaqueta cada distribución. Para confirmar si tu kernel ya tiene el parche, corré &lt;code&gt;uname -r&lt;/code&gt; y comparalo contra la tabla de versiones corregidas: un resultado como &lt;code&gt;6.12.113-generic&lt;/code&gt; ya incluye el fix si el número coincide o es posterior al listado arriba. En Ubuntu Pro, el comando &lt;code&gt;pro fix CVE-2026-98432 --dry-run&lt;/code&gt; indica directamente si el paquete instalado sigue expuesto.&lt;/p&gt;

&lt;p&gt;Mientras llega el parche, Red Hat propone una mitigación con &lt;code&gt;nftables&lt;/code&gt; en su boletín RHSB-2026-016, y Atlas sugiere una regla provisional: descartar los paquetes TCP que llevan opciones IPv4. Ambas opciones cortan también tráfico legítimo que use esas opciones, así que conviene aplicarlas solo mientras llega el kernel definitivo. Si no usás multipath TCP, desactivarlo reduce la superficie de ataque sin tocar el resto del tráfico; si lo usás, priorizá parchear esos hosts primero.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: &lt;a href="https://telegra.ph/CVE-2026-98432-Linux-parch%C3%B3-el-UAF-en-TCP-Ubuntu-y-RHEL-siguen-expuestos-11-01" rel="noopener noreferrer"&gt;Ver resumen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Probalo vos: revisá el estado de tu kernel contra el rastreador de tu distribución y, si corrés Ubuntu o RHEL, aplicá ya la regla de &lt;code&gt;nftables&lt;/code&gt; del boletín de Red Hat mientras llega el parche definitivo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué es CVE-2026-98432?
&lt;/h3&gt;

&lt;p&gt;Es el identificador del &lt;a href="https://nvd.nist.gov/vuln/detail/CVE-2026-98432" rel="noopener noreferrer"&gt;bug CVE-2026-98432&lt;/a&gt;, un use-after-free en el código IPv4 del kernel de Linux que un atacante remoto y sin autenticar puede explotar durante el saludo TCP.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué versiones de Linux corrigen el fallo de seguridad en el kernel?
&lt;/h3&gt;

&lt;p&gt;Las ramas estables corregidas son 5.10.272, 5.15.223, 6.1.190, 6.6.159, 6.12.113, 6.18.56, 7.2.10 y 7.3. Las versiones entre 4.4 y 5.4 llegaron a su fin de vida upstream y no reciben parche oficial del proyecto Linux.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿La vulnerabilidad del kernel de Linux afecta a contenedores?
&lt;/h3&gt;

&lt;p&gt;Sí, porque un contenedor usa el kernel del host. Si ese kernel no tiene el parche, ningún cambio dentro de la imagen del contenedor evita el problema.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué es Multipath TCP y por qué amplía el riesgo?
&lt;/h3&gt;

&lt;p&gt;Multipath TCP (MPTCP) es una extensión de TCP que combina varias rutas de red en una sola conexión. El exploit que construyó Claude necesita un servidor con un listener multipath TCP activo, y los programas en Go abren ese tipo de listener por defecto.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo mitigar el use-after-free en TCP si todavía no hay kernel corregido?
&lt;/h3&gt;

&lt;p&gt;Red Hat recomienda una regla de &lt;code&gt;nftables&lt;/code&gt; en su boletín RHSB-2026-016, y Atlas propone descartar paquetes TCP con opciones IPv4 mientras tanto. Desactivar multipath TCP, si no lo usás, también reduce la exposición.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Escribió Claude un exploit funcional para esta falla crítica de Linux?
&lt;/h3&gt;

&lt;p&gt;Según Anthropic, sí: su modelo construyó una prueba de concepto que ejecuta comandos como root en servidores con un listener multipath TCP, sin necesitar ninguna credencial. La compañía no publicó el código del exploit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://atlasum.net/blog/cve-2026-98432-linux-ipv4-tcp-uaf" rel="noopener noreferrer"&gt;Atlas&lt;/a&gt;: cobertura y seguimiento en vivo del estado de parches por distribución para CVE-2026-98432.- &lt;a href="https://nvd.nist.gov/vuln/detail/CVE-2026-98432" rel="noopener noreferrer"&gt;National Vulnerability Database&lt;/a&gt;: registro oficial de la vulnerabilidad con su puntuación CVSS.- &lt;a href="https://www.cve.org/CVERecord?id=CVE-2026-98432" rel="noopener noreferrer"&gt;CVE.org&lt;/a&gt;: ficha pública del identificador CVE-2026-98432 asignado por la CNA del kernel de Linux.- &lt;a href="https://access.redhat.com/security/cve/CVE-2026-98432" rel="noopener noreferrer"&gt;Red Hat&lt;/a&gt;: página de seguimiento de la CVE con la calificación Critical y el boletín de mitigación RHSB-2026-016.- &lt;a href="https://ubuntu.com/security/CVE-2026-98432" rel="noopener noreferrer"&gt;Ubuntu Security&lt;/a&gt;: rastreador de estado del paquete &lt;code&gt;linux&lt;/code&gt; por versión soportada.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>security</category>
      <category>cybersecurity</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Karpathy lanza HackerTube: 6.454 videos curados de Hacker News</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Sun, 01 Nov 2026 08:27:36 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/karpathy-lanza-hackertube-6454-videos-curados-de-hacker-news-444k</link>
      <guid>https://dev.to/lu1tr0n/karpathy-lanza-hackertube-6454-videos-curados-de-hacker-news-444k</guid>
      <description>&lt;p&gt;Karpathy no aguantó más el algoritmo de recomendaciones de YouTube: un viernes a las 11 de la noche encontró miniaturas exageradas y contenido repetitivo, y al día siguiente ya tenía &lt;strong&gt;HackerTube de Hacker News&lt;/strong&gt; funcionando, un clon de YouTube armado con Claude Opus 5.5 que cataloga 6.454 videos recomendados en los comentarios del foro entre 2007 y 2026.&lt;/p&gt;

&lt;p&gt;El sitio, publicado en hackertube.org, resuelve un problema puntual: ver solo los videos que la comunidad de Hacker News consideró lo bastante buenos para mencionar en un comentario. Nada de algoritmo de YouTube, nada de cuentas, nada de historial que vender a anunciantes.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Karpathy lanzó HackerTube, un clon de YouTube con 6.454 videos recomendados en HN entre 2007 y 2026.- El sitio filtró 40.000 comentarios de HN con un Workflow de Claude Code y Sonnet para descartar spam.- Los 6.454 videos cubren 150 temas y usan la miniatura al 50% del video en vez del thumbnail original.- Todo el proceso, scraping, filtrado, deploy y hardening, tomó cerca de dos horas con Claude Opus 5.5.- HackerTube no pide cuentas: guarda las recomendaciones en la sesión local del navegador del usuario.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Qué es HackerTube
&lt;/h2&gt;

&lt;p&gt;HackerTube de Hacker News es la plataforma construida por Andrej Karpathy que reúne, con una interfaz calcada de YouTube, los videos que distintos usuarios recomendaron en comentarios de Hacker News entre 2007 y 2026; agrupa 6.454 videos únicos en 150 temas y no pide registro.&lt;/p&gt;

&lt;p&gt;Karpathy es conocido en la comunidad de inteligencia artificial por su paso por OpenAI y Tesla, y por fundar después Eureka Labs, un proyecto educativo centrado en IA; en 2026 dedica buena parte de su tiempo a experimentar con &lt;a href="https://www.anthropic.com" rel="noopener noreferrer"&gt;agentes de código de Anthropic&lt;/a&gt; para construir herramientas personales. HackerTube es, según su propio relato, el resultado de un sábado de trabajo con &lt;strong&gt;Claude Opus 5.5&lt;/strong&gt; como único programador.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué pasó
&lt;/h2&gt;

&lt;p&gt;Todo arrancó un viernes a las 11 de la noche: Karpathy fue a YouTube a buscar algo para ver y se topó, según sus palabras, con un muro de contenido degradado, con miniaturas exageradas y recomendaciones repetidas de los mismos temas. Al día siguiente, sábado, decidió resolverlo con su propia herramienta en vez de ajustar configuraciones.&lt;/p&gt;

&lt;p&gt;Le dio la tarea a Claude: construir un clon de YouTube basado en los videos que la comunidad de Hacker News recomendó con el tiempo. El resultado, contado en su &lt;a href="https://karpathy.bearblog.dev/hacker-tube/" rel="noopener noreferrer"&gt;publicación original&lt;/a&gt;, fue hackertube.org.&lt;/p&gt;

&lt;p&gt;El proceso, descrito paso a paso por Karpathy, fue: descargar todos los comentarios históricos de Hacker News, filtrarlos, pasarlos por Sonnet dentro de un Workflow de Claude Code para descartar spam, y quedarse con las recomendaciones reales de video. De ahí salieron &lt;strong&gt;40.000 comentarios&lt;/strong&gt; que mencionaban un video de YouTube, reducidos a 6.454 videos distintos repartidos en 150 temas.&lt;/p&gt;

&lt;p&gt;Según el propio Karpathy, el trabajo manual se limitó a tres pasos: crear una API key en Google Cloud para consultar metadatos de YouTube, levantar un VPS y comprar el dominio. El resto (scraping, filtrado, deploy, hardening y optimización del servidor) corrió por cuenta de Claude. Todo el proceso le tomó cerca de dos horas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contexto e historia
&lt;/h2&gt;

&lt;p&gt;Hacker News existe desde 2007, cuando Paul Graham lo lanzó como foro de Y Combinator para noticias de startups y tecnología. Casi dos décadas de comentarios acumulados significan que cualquier video de YouTube mencionado alguna vez en un hilo técnico queda, en teoría, rastreable.&lt;/p&gt;

&lt;p&gt;Lo nuevo no es el dataset, es el tiempo que tomó construir algo útil con él. En 2026 ya es común ver a programadores individuales anunciar productos terminados (scraping, backend, frontend, deploy, seguridad) construidos en una sola sesión con un agente de código, sin escribir una línea a mano. Karpathy lo resume así en su publicación: &lt;em&gt;no hago nada que se parezca a ingeniería tradicional, solo hablo con Claude y dejo que haga todo&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Ese cambio de rol, de programador a director de un agente, viene discutiéndose en la comunidad desde hace meses, pero pocos ejemplos son tan concretos como este: un dataset curado, una interfaz funcional y un dominio propio en una tarde de sábado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detalles técnicos: el mecanismo detrás de HackerTube
&lt;/h2&gt;

&lt;p&gt;El cuello de botella de un proyecto así no es mostrar videos de YouTube, eso lo resuelve cualquier reproductor embebido; es separar las menciones reales de un video de todo el ruido alrededor. Con 40.000 comentarios candidatos y apenas 6.454 videos finales, el filtro descartó alrededor del 84% de las menciones iniciales: links rotos, videos repetidos y comentarios donde el link aparecía sin ser una recomendación real.&lt;/p&gt;

&lt;p&gt;Para resolverlo, Karpathy usó &lt;strong&gt;Workflows&lt;/strong&gt;, la función de &lt;a href="https://www.anthropic.com" rel="noopener noreferrer"&gt;Claude Code&lt;/a&gt; que permite orquestar varios agentes en paralelo con un rol fijo cada uno. En este caso, Sonnet corrió sobre los comentarios descargados con una sola tarea: decidir si un comentario con un link de YouTube era una recomendación genuina o ruido. Los que pasaban el filtro quedaban deduplicados por ID de video y alimentaban el catálogo final.&lt;/p&gt;

&lt;p&gt;Con el video ya identificado, el sitio pide los metadatos (título, canal, duración) a la &lt;a href="https://developers.google.com/youtube/v3" rel="noopener noreferrer"&gt;YouTube Data API&lt;/a&gt;, el único punto donde Karpathy tuvo que intervenir a mano: generar una API key en Google Cloud. El resto de la personalización, el ForYou sin cuenta de usuario, vive enteramente en la sesión del navegador: no hay base de datos de usuarios ni login, solo estado local que se pierde si se borra la caché.&lt;/p&gt;

&lt;p&gt;Ese flujo (descargar, clasificar con un modelo, deduplicar, consultar una API externa y desplegar) es replicable, pero no gratis: cada comentario filtrado por Sonnet implica una llamada al modelo, así que un lote de 40.000 comentarios supone decenas de miles de llamadas antes de llegar al catálogo final de 6.454 videos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;flowchart&lt;/span&gt; &lt;span class="nv"&gt;TD&lt;/span&gt;
    &lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Comentarios de Hacker News 2007-2026"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Filtro con Sonnet en un Workflow"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"40.000 recomendaciones de video"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"6.454 videos unicos en 150 temas"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;D&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;E&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Interfaz estilo YouTube"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;E&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"VPS asegurado y optimizado"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hacker News cumple 19 años en 2026, fundado por Paul Graham.&lt;br&gt;
Un detalle menor que Karpathy destaca: el sitio no usa la miniatura que subió el canal, sino la miniatura automática que YouTube genera a la mitad de la duración del video. Según describe en su publicación, esa miniatura suele representar mejor el contenido real que la miniatura pensada para generar clics.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;📌 Nota:&lt;/strong&gt; HackerTube no reentrena ningún modelo ni guarda datos de uso: el filtrado con Sonnet corrió una sola vez, sobre un dataset histórico, para construir el catálogo. Cada visita posterior es solo lectura.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Impacto de HackerTube de Hacker News para la comunidad dev
&lt;/h2&gt;

&lt;p&gt;El caso interesa menos por el resultado, un catálogo de videos curado, que por el costo de construirlo. Hace pocos años, armar un scraper de comentarios, un clasificador de spam, una interfaz tipo YouTube y desplegar todo en un VPS seguro era trabajo de un equipo chico durante semanas. Karpathy lo redujo a una tarde, con tres intervenciones manuales puntuales.&lt;/p&gt;

&lt;p&gt;Eso no significa que cualquiera pueda replicarlo sin fricción: HackerTube depende de la &lt;a href="https://developers.google.com/youtube/v3" rel="noopener noreferrer"&gt;YouTube Data API&lt;/a&gt;, que tiene cuotas diarias limitadas y puede frenar un proyecto si el tráfico crece. Los 6.454 videos del catálogo, además, son un recorte fijo hasta la fecha de publicación; si Hacker News sigue generando comentarios con links de YouTube, el sitio no los va a incorporar solo, porque no corre un proceso continuo de scraping.&lt;br&gt;
Opus 5.5 es el modelo que Karpathy usó para todo el proyecto.&lt;br&gt;
Tampoco hay curaduría editorial real más allá del filtro de spam: el catálogo refleja lo que la comunidad de Hacker News comentó, con su sesgo hacia temas de programación, ciencia y tecnología, y poco de entretenimiento general. Quien busque otro tipo de contenido no lo va a encontrar ahí, y eso es, en parte, el punto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué sigue
&lt;/h2&gt;

&lt;p&gt;Karpathy no anunció un plan de mantenimiento ni una fecha para sumar comentarios nuevos de Hacker News al catálogo. Lo que sí dejó disponible es la exportación completa de los datos del sitio, pensada explícitamente para que otro desarrollador, o su propio agente de código, tome el dataset y construya una versión distinta sin repetir el trabajo de scraping y filtrado desde cero.&lt;/p&gt;

&lt;p&gt;Es razonable esperar forks: la combinación de un dataset público, un pipeline documentado en una publicación pública y un patrón replicable (bajar comentarios de un foro, clasificarlos con un modelo, armar una interfaz) es exactamente el tipo de proyecto de fin de semana que prolifera cuando alguien influyente como Karpathy lo muestra funcionando.&lt;/p&gt;

&lt;p&gt;Si querés ver qué videos marcó como imprescindibles casi dos décadas de comentarios en Hacker News, hackertube.org ya está arriba ahora mismo y no pide ni correo ni contraseña.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: &lt;a href="https://telegra.ph/Karpathy-lanza-HackerTube-6454-videos-curados-de-Hacker-News-11-01" rel="noopener noreferrer"&gt;Ver resumen&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué es el sitio hackertube.org y quién lo construyó?
&lt;/h3&gt;

&lt;p&gt;Es un clon de YouTube con 6.454 videos recomendados en comentarios de Hacker News entre 2007 y 2026, construido por Andrej Karpathy con Claude Opus 5.5 en una sesión de trabajo de un sábado.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo filtra HackerTube los comentarios de spam de Hacker News?
&lt;/h3&gt;

&lt;p&gt;Un Workflow de Claude Code corrió el modelo Sonnet sobre 40.000 comentarios con links de YouTube, descartando spam, links rotos y menciones que no eran recomendaciones reales, antes de deduplicar por video.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Necesito una cuenta para usar hackertube.org?
&lt;/h3&gt;

&lt;p&gt;No. El sitio no tiene login ni base de datos de usuarios: las recomendaciones personalizadas, el ForYou, se calculan y guardan en la sesión local del navegador.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cuánto tardó Karpathy en construir el clon de YouTube de Hacker News?
&lt;/h3&gt;

&lt;p&gt;Según su propia publicación, el proceso completo (scraping, filtrado, interfaz, deploy, seguridad y optimización) tomó alrededor de dos horas, con solo tres pasos manuales: crear una API key de YouTube, levantar un VPS y comprar el dominio.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Puedo descargar los datos de HackerTube de Hacker News para hacer mi propia versión?
&lt;/h3&gt;

&lt;p&gt;Sí. El sitio ofrece exportar los datos completos del catálogo, pensado para que otro desarrollador o agente de código construya su propia versión sin repetir el proceso de scraping desde cero.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://karpathy.bearblog.dev/hacker-tube/" rel="noopener noreferrer"&gt;Karpathy, HackerTube&lt;/a&gt;: la publicación original donde Andrej Karpathy describe cómo construyó el sitio con Claude Opus 5.5.- &lt;a href="https://en.wikipedia.org/wiki/Hacker_News" rel="noopener noreferrer"&gt;Wikipedia: Hacker News&lt;/a&gt;: historia y origen del foro de Y Combinator, fundado en 2007.- &lt;a href="https://developers.google.com/youtube/v3" rel="noopener noreferrer"&gt;YouTube Data API&lt;/a&gt;: documentación oficial de la API que HackerTube usa para consultar metadatos de video.- &lt;a href="https://www.anthropic.com" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;: desarrolladora de Claude Code y los modelos Opus y Sonnet usados para construir el sitio.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>security</category>
      <category>cybersecurity</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Jepsen halla 96 fallos de corrección en ParticleDB</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Sun, 01 Nov 2026 02:36:19 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/jepsen-halla-96-fallos-de-correccion-en-particledb-25hm</link>
      <guid>https://dev.to/lu1tr0n/jepsen-halla-96-fallos-de-correccion-en-particledb-25hm</guid>
      <description>&lt;p&gt;ParticleDB prometía ser "Full ACID" con 159.000 transacciones por segundo en la portada de su sitio. Jepsen, la consultora que Kyle Kingsbury dedica a destrozar bases de datos distribuidas con pruebas de caos, encontró &lt;a href="https://jepsen.io/analyses/particledb-1.1.4" rel="noopener noreferrer"&gt;96 fallos de corrección&lt;/a&gt; entre las versiones 1.1.4 y 1.1.18.11.rc-22 de la base de datos ParticleDB. La mayoría de esos fallos aparecía con un solo servidor, un solo cliente y cero fallas de red.&lt;/p&gt;

&lt;p&gt;El reporte, publicado el 31 de octubre de 2026 y financiado por Orkes, la empresa detrás del motor, es el típico análisis Jepsen: mezcla hallazgos cómicos (filas parcialmente invisibles que no se podían borrar, tablas eliminadas que reaparecían distorsionadas) con otros serios, como pérdida de escrituras confirmadas incluso en el modo de aislamiento serializable, el más estricto que ofrece el motor.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Jepsen halló 96 fallos en la base de datos ParticleDB, de Orkes, entre las versiones 1.1.4 y 1.1.18.11.rc-22- El modo serializable, el más estricto de ParticleDB, permitió anomalías internas y Lost Update- La configuración groupsync perdía escrituras confirmadas pese a anunciar la misma durabilidad que sync- Orkes lanzó la versión 1.1.19-rc.13 y afirma haber resuelto todos los fallos restantes- Su propia portada prometía "Full ACID" aunque el texto debajo describía snapshot isolation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Qué es la base de datos ParticleDB
&lt;/h2&gt;

&lt;p&gt;La base de datos ParticleDB es un motor multimodal que Orkes construyó para cargas de inteligencia artificial: combina SQL transaccional, almacenamiento clave-valor, búsqueda vectorial y analítica en vivo mediante funciones definidas por el usuario llamadas Particles. Escrita en Rust, expone protocolos Postgres, Redis, gRPC y HTTP2 para integrarse con sistemas existentes.&lt;/p&gt;

&lt;p&gt;El objetivo declarado es reemplazar el típico mosaico de cachés, colas y almacenes separados que usan las aplicaciones de IA actuales. Orkes afirma que &lt;strong&gt;ParticleDB&lt;/strong&gt; es órdenes de magnitud más rápido que Postgres mientras conserva las mismas garantías de seguridad transaccional.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué pasó
&lt;/h2&gt;

&lt;p&gt;Orkes contrató a Jepsen para auditar las versiones refactorizadas de ParticleDB antes de un lanzamiento más amplio. El resultado fueron 96 problemas, desde los pedestres (caídas del servidor, deadlocks, pérdida de datos) hasta los más curiosos: filas parcialmente invisibles que no se podían eliminar, consultas &lt;code&gt;WHERE 4 = 5&lt;/code&gt; que igual devolvían filas, tablas borradas que reaparecían con forma distinta, columnas confundidas entre sí y strings que se convertían en enteros.&lt;/p&gt;

&lt;p&gt;La mayoría de esos 96 casos no necesitó un clúster bajo estrés: bastó un solo servidor, un solo cliente y ninguna falla de red para reproducirlos. Para la versión 1.1.18.11.rc-22, Orkes había resuelto todos los problemas menos diez. Pero entre esos diez quedaban los más graves: ParticleDB seguía perdiendo escrituras confirmadas durante operación normal con &lt;code&gt;occ&lt;/code&gt;, su modo de transacciones por defecto, y permitía anomalías internas y Lost Update incluso con &lt;code&gt;serializable&lt;/code&gt;, el ajuste más fuerte disponible.&lt;/p&gt;

&lt;p&gt;Orkes ya respondió. Según el propio reporte de Jepsen, la empresa lanzó la versión 1.1.19-rc.13 y asegura que ahí quedan resueltos todos los problemas que seguían abiertos.&lt;br&gt;
Jepsen reprodujo la mayoría de los 96 fallos con un solo servidor, un solo cliente y cero fallas de red.&lt;/p&gt;
&lt;h2&gt;
  
  
  Contexto e historia
&lt;/h2&gt;

&lt;p&gt;Orkes no construyó ParticleDB como un producto aislado. La empresa opera Conductor, una plataforma de orquestación de flujos de trabajo que originalmente guardaba su estado en &lt;a href="https://github.com/conductor-oss/conductor" rel="noopener noreferrer"&gt;Redis y Postgres&lt;/a&gt;. Para mejorar el rendimiento, Orkes decidió escribir su propia base de datos en lugar de seguir combinando dos motores distintos.&lt;/p&gt;

&lt;p&gt;La versión 1.0.0 de ParticleDB tenía un set de funciones limitado, pensado específicamente para las consultas de Conductor, y se desplegó como backend de algunos clústeres de producción. Varios clientes de Orkes siguieron el mismo camino. Antes de un lanzamiento más amplio al público, Orkes hizo un refactor mayor: agregó un protocolo de cable propio, más tipos de datos y consultas OLAP adicionales, y lanzó esas versiones de forma silenciosa en particledb.ai. Jepsen empezó a probar justamente esas versiones refactorizadas, a partir de la 1.1.4.&lt;/p&gt;

&lt;p&gt;Un detalle que el reporte deja claro: ParticleDB también ofrece un clúster replicado usando el protocolo de consenso &lt;a href="https://raft.github.io/" rel="noopener noreferrer"&gt;Raft&lt;/a&gt;, pero esa función solo está disponible en despliegues de nube empresarial. Las builds que Orkes entregó a Jepsen no soportaban replicación, así que todo lo analizado corresponde únicamente a comportamiento de un solo nodo.&lt;/p&gt;
&lt;h2&gt;
  
  
  El mecanismo detrás de los fallos
&lt;/h2&gt;

&lt;p&gt;La página de inicio de ParticleDB aseguraba estar "formalmente probada" con una especificación en TLA+. Durante la colaboración con Jepsen, sin embargo, no existía ninguna especificación TLA+ disponible, así que no queda claro qué propiedades se habrían demostrado ni si describían al ParticleDB real.&lt;/p&gt;

&lt;p&gt;La mayoría de los motores SQL controlan el nivel de aislamiento de una transacción con la instrucción &lt;code&gt;SET TRANSACTION ISOLATION LEVEL&lt;/code&gt;. ParticleDB la ignora o la rechaza. A veces le dice al usuario que use &lt;code&gt;READ COMMITTED&lt;/code&gt;, un nivel relativamente débil; otras veces acepta el pedido de otro nivel y lo ignora en silencio, sin avisar.&lt;/p&gt;

&lt;p&gt;En cambio, el aislamiento real depende de un flag de arranque, &lt;code&gt;--txn-mode&lt;/code&gt;, con cuatro modos documentados:&lt;br&gt;
ModoComportamientoCuándo usarlofastSin locks; commit al escribirCargas masivas, benchmarks de un solo escritorocc (default)Overlay más validación OCC al hacer commitOLTP general, pensado para ser seguro bajo concurrenciazero-copy-occOCC anclado a partición; transacciones de una sola partición evitan coordinación cruzadaOLTP de alto rendimiento sobre cargas afines a particióntable-2plLocks exclusivos de tabla al primer toqueSerialización más estricta, semántica simple&lt;br&gt;
El problema es que la documentación nunca explicó qué garantizaba cada modo en términos formales. ¿&lt;code&gt;fast&lt;/code&gt; equivalía a Read Atomic, a Read Uncommitted o a otra cosa? Jepsen tampoco pudo confirmarlo del todo con &lt;code&gt;occ&lt;/code&gt;, el modo que usa cualquier instalación nueva por defecto.&lt;/p&gt;

&lt;p&gt;La confusión se repite con la durabilidad del Write-Ahead Log. ParticleDB ofrece tres tácticas: &lt;code&gt;sync&lt;/code&gt; hace &lt;code&gt;fsync&lt;/code&gt; en cada commit, &lt;code&gt;groupsync&lt;/code&gt; agrupa varias transacciones en un solo &lt;code&gt;fsync&lt;/code&gt;, y &lt;code&gt;nosync&lt;/code&gt; no hace &lt;code&gt;fsync&lt;/code&gt; en absoluto. La documentación del motor de transacciones dice que &lt;code&gt;sync&lt;/code&gt; ofrece "mayor durabilidad" que &lt;code&gt;groupsync&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;particledb start &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;span class="nt"&gt;--txn-mode&lt;/span&gt; groupsync   &lt;span class="c"&gt;# "COMMIT waits for flush"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pero la ayuda de línea de comandos asegura que &lt;code&gt;groupsync&lt;/code&gt; garantiza que "COMMIT espera al flush", y la guía interna de operación de Orkes coincide: según ese documento, &lt;code&gt;groupsync&lt;/code&gt; ofrece "la misma durabilidad que &lt;code&gt;sync&lt;/code&gt;". Tres fuentes oficiales, tres versiones distintas de la misma garantía.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Ojo:&lt;/strong&gt; la portada de ParticleDB decía literalmente "Full ACID. 159K TPS." y, justo debajo, el texto describía "snapshot isolation", un nivel de aislamiento que por definición no es completamente serializable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Impacto y análisis
&lt;/h2&gt;

&lt;p&gt;Para equipos que evalúan la base de datos ParticleDB en producción, el reporte es una señal de alerta clara. No es que ParticleDB no sirva: la mayoría de los 96 fallos ya estaban resueltos para la última versión probada. El problema es que los que quedaban afectaban justo el modo por defecto (&lt;code&gt;occ&lt;/code&gt;) y el modo que, en teoría, ofrece más garantías (&lt;code&gt;serializable&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Jepsen aclara que financió el estudio la propia Orkes, siguiendo la &lt;a href="https://github.com/jepsen-io/jepsen" rel="noopener noreferrer"&gt;política de ética de Jepsen&lt;/a&gt;, que exige publicar los resultados sin filtrar hallazgos negativos. Eso le da credibilidad al informe, aunque también explica por qué Orkes respondió tan rápido con una nueva versión.&lt;/p&gt;

&lt;p&gt;La limitación más importante del estudio es que solo cubre comportamiento de un solo nodo. ParticleDB vende replicación vía Raft para sus clientes de nube empresarial, pero esa parte del sistema nunca se probó porque las builds entregadas a Jepsen no la soportaban. Cualquier equipo que piense correr un clúster replicado en producción debería pedir una auditoría separada antes de confiar en esa capa.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué sigue
&lt;/h2&gt;

&lt;p&gt;Orkes ya lanzó la versión 1.1.19-rc.13 y sostiene que resuelve todos los fallos que seguían abiertos al cierre del reporte. Jepsen no confirma de forma independiente esa afirmación en el documento publicado, así que por ahora es la palabra de Orkes contra sus propios resultados anteriores.&lt;/p&gt;

&lt;p&gt;Para cualquier equipo que ya use o esté evaluando ParticleDB, el paso práctico es elegir &lt;code&gt;--txn-mode&lt;/code&gt; con el mismo cuidado que recomienda la propia documentación del proyecto: la mejor práctica publicada advierte que el modo "cambia la corrección y el rendimiento más que el texto SQL", así que no conviene dejarlo en el valor por defecto sin entender qué cubre.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: &lt;a href="https://telegra.ph/Jepsen-halla-96-fallos-de-correcci%C3%B3n-en-ParticleDB-11-01" rel="noopener noreferrer"&gt;Ver resumen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Probalo vos: antes de poner la base de datos ParticleDB en producción, corré tu propio set de pruebas de concurrencia con el &lt;code&gt;--txn-mode&lt;/code&gt; que pensás usar y compará el resultado contra el reporte de Jepsen en jepsen.io.&lt;br&gt;
El modo serializable, el más estricto que ofrece ParticleDB, también mostró Lost Update según Jepsen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿ParticleDB cumple de verdad con ACID?
&lt;/h3&gt;

&lt;p&gt;No de forma completa en las versiones auditadas. Jepsen encontró pérdida de escrituras confirmadas en el modo por defecto y anomalías incluso en serializable, el nivel más estricto que ofrece ParticleDB.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué modo de transacción de ParticleDB es más seguro?
&lt;/h3&gt;

&lt;p&gt;Según la documentación, table-2pl ofrece la serialización más estricta con locks exclusivos de tabla, aunque el reporte de Jepsen no confirma que ningún modo esté completamente libre de fallos en todas las versiones probadas.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿ParticleDB soporta replicación?
&lt;/h3&gt;

&lt;p&gt;Sí, mediante el protocolo Raft, pero solo en despliegues de nube empresarial. Jepsen no evaluó esa capa porque las builds que usó no la incluían.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué es Orkes y por qué construyó ParticleDB?
&lt;/h3&gt;

&lt;p&gt;Orkes es la empresa detrás de Conductor, una plataforma de orquestación de flujos de trabajo. Construyó ParticleDB para reemplazar la combinación de Redis y Postgres que usaba Conductor y mejorar el rendimiento.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Ya se resolvieron los fallos que halló Jepsen en ParticleDB?
&lt;/h3&gt;

&lt;p&gt;Orkes dice que la versión 1.1.19-rc.13 resuelve todos los problemas que seguían abiertos al cierre del reporte, aunque Jepsen no lo confirma de forma independiente en el documento publicado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://jepsen.io/analyses/particledb-1.1.4" rel="noopener noreferrer"&gt;Jepsen: ParticleDB 1.1.4&lt;/a&gt;: el reporte original de Kyle Kingsbury con los 96 fallos encontrados.- &lt;a href="https://github.com/jepsen-io/jepsen" rel="noopener noreferrer"&gt;Jepsen en GitHub&lt;/a&gt;: el framework y la metodología que usa Jepsen para auditar bases de datos distribuidas.- &lt;a href="https://raft.github.io/" rel="noopener noreferrer"&gt;Raft Consensus Algorithm&lt;/a&gt;: el protocolo de replicación que ParticleDB ofrece en su nube empresarial.- &lt;a href="https://github.com/conductor-oss/conductor" rel="noopener noreferrer"&gt;Conductor OSS&lt;/a&gt;: la plataforma de orquestación de Orkes que originó el desarrollo de ParticleDB.- &lt;a href="https://en.wikipedia.org/wiki/ACID" rel="noopener noreferrer"&gt;ACID (Wikipedia)&lt;/a&gt;: definición de las propiedades de atomicidad, consistencia, aislamiento y durabilidad.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>technology</category>
      <category>science</category>
      <category>programming</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Latencia de memoria: qué es y por qué tu CPU no rinde al 100%</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Sat, 31 Oct 2026 20:29:10 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/latencia-de-memoria-que-es-y-por-que-tu-cpu-no-rinde-al-100-4ml2</link>
      <guid>https://dev.to/lu1tr0n/latencia-de-memoria-que-es-y-por-que-tu-cpu-no-rinde-al-100-4ml2</guid>
      <description>&lt;p&gt;Un monitor que marca el CPU al 100% casi nunca dice la verdad completa: ese número mide tiempo ocupado, no trabajo útil. La causa más común de la diferencia es la latencia de memoria, el tiempo que el procesador pierde esperando datos que no están en sus cachés.&lt;/p&gt;

&lt;p&gt;Para cualquiera que afina una consulta SQL, un pipeline de datos o un servicio en producción, entender esta diferencia cambia qué hay que optimizar primero. Este artículo explica cómo funciona la jerarquía de caché de la CPU, por qué un GROUP BY con millones de claves se vuelve lento y cómo medir el problema en tu propia máquina con perf stat.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;La latencia de memoria explica por qué un CPU al 100% puede rendir 400 a 800 veces menos de lo esperado- L1 responde en ~1 ns, L3 en ~10-15 ns y la RAM tarda 50-100 ns: cada salto cuesta cientos de instrucciones perdidas- Un GROUP BY con 17 millones de claves únicas convierte cada acceso a un HashMap en un viaje directo a RAM- perf stat con la métrica backend_bound_memory mide cuánto tiempo del CPU se pierde esperando datos, no calculando- Particionar los datos para que cada bloque entre en la caché L2 o L3 es la técnica central de motores como Pivot&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Qué es la latencia de memoria?
&lt;/h2&gt;

&lt;p&gt;La latencia de memoria es el tiempo que tarda un procesador en obtener un dato que no está disponible en sus cachés internas y debe pedirlo a la memoria RAM. Se mide en nanosegundos, suele rondar entre 50 y 100 ns en hardware moderno y determina cuántas instrucciones quedan congeladas esperando esa respuesta.&lt;/p&gt;

&lt;p&gt;Esa espera no es un detalle menor: en un CPU moderno capaz de ejecutar entre 4 y 8 instrucciones por nanosegundo, cada viaje a RAM equivale a dejar pasar entre 400 y 800 instrucciones que el procesador podría haber ejecutado. Es la razón de fondo detrás del dato citado en el &lt;a href="https://pivotlake.io/blog/its-the-memory-latency-stupid/" rel="noopener noreferrer"&gt;blog de Pivot&lt;/a&gt;: un CPU puede aparecer ocupado en el monitor del sistema operativo mientras en realidad pasa buena parte del tiempo detenido, esperando.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué importa para quien programa
&lt;/h2&gt;

&lt;p&gt;El sistema operativo considera un CPU ocupado si hay alguna tarea (un task, en términos de Linux) asignada a ese núcleo, sin importar si esa tarea está progresando o solo esperando una respuesta de memoria. Por eso dos procesos que muestran 100% de uso de CPU pueden estar haciendo cantidades de trabajo completamente distintas.&lt;/p&gt;

&lt;p&gt;Esto afecta decisiones de ingeniería cotidianas: elegir una estructura de datos, decidir cuántos hilos lanzar, o diagnosticar por qué una consulta SQL tarda más de lo esperado aunque el servidor no aparezca saturado según las métricas habituales. Ignorar la jerarquía de caché de la CPU lleva a optimizar lo que no importa, como agregar más núcleos a un problema que en realidad está limitado por cuántas veces el procesador tiene que ir hasta la RAM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo funciona la jerarquía de caché de la CPU
&lt;/h2&gt;

&lt;p&gt;Para evitar pagar el costo completo de cada acceso a RAM, los procesadores modernos intercalan varios niveles de memoria cada vez más rápidos y más chicos, soldados dentro del propio chip. El nivel más cercano al núcleo, la caché L1, responde en apenas 1 nanosegundo, pero tiene un tamaño minúsculo (unos 64 KB). Los niveles siguientes, L2 y L3, son más grandes pero también más lentos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;flowchart&lt;/span&gt; &lt;span class="nv"&gt;TD&lt;/span&gt;
    &lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Nucleo de CPU"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Cache L1 ~1 ns, ~64 KB"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Cache L2 ~3-4 ns, ~1 MB"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Cache L3 ~10-15 ns, cientos de MB"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;D&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;E&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"DRAM ~50-100 ns, GBs"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La tabla siguiente resume los cuatro niveles con los valores que el propio equipo de Pivot usa para razonar sobre el rendimiento de su motor:&lt;br&gt;
NivelLatencia aproximadaTamaño típicoInstrucciones de CPU perdidas por accesoL1~1 ns~64 KB~4-8L2~3-4 ns~1 MB~15-30L3~10-15 nscientos de MB~50-100DRAM~50-100 nsGBs~400-800&lt;br&gt;
La consecuencia práctica es clara: un programa que trabaja con estructuras de datos pequeñas y accede a ellas de forma predecible puede quedarse casi todo el tiempo dentro de L1 o L2. Un programa que salta de forma errática por un espacio de memoria mucho más grande que L3 va a terminar pagando el costo completo de la &lt;a href="https://en.wikipedia.org/wiki/CPU_cache" rel="noopener noreferrer"&gt;jerarquía de caché&lt;/a&gt; en cada acceso.&lt;/p&gt;
&lt;h2&gt;
  
  
  Ejemplos prácticos: de un diccionario a un acceso aleatorio en C
&lt;/h2&gt;

&lt;p&gt;El ejemplo más simple de un GROUP BY es un diccionario que acumula totales por clave. En Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;defaultdict&lt;/span&gt;

&lt;span class="n"&gt;ventas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ana&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;luis&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ana&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;luis&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ana&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="n"&gt;totales&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;usuario&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;monto&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ventas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;totales&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;usuario&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;monto&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;totales&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este código agrupa ventas por usuario y suma los montos, exactamente lo que hace &lt;code&gt;SELECT SUM(monto) FROM ventas GROUP BY usuario&lt;/code&gt; en SQL. La salida es determinística:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ana&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;155&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;luis&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con cinco filas y dos claves, todo el diccionario vive cómodamente en la caché L1. El problema aparece cuando la cardinalidad crece: con millones de claves únicas, ese mismo &lt;code&gt;defaultdict&lt;/code&gt; deja de caber en cualquier caché y cada &lt;code&gt;totales[usuario] += monto&lt;/code&gt; se convierte en un posible salto a RAM.&lt;/p&gt;

&lt;p&gt;Para ver el efecto de forma controlada, este programa en C suma 50 millones de enteros de dos maneras: accediendo a ellos en orden y accediendo a ellos siguiendo un salto fijo que visita las mismas posiciones pero en un orden disperso.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include 
#include 
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50000000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;datos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;La&lt;/span&gt; &lt;span class="n"&gt;cach&lt;/span&gt;&lt;span class="err"&gt;é&lt;/span&gt; &lt;span class="n"&gt;L1&lt;/span&gt; &lt;span class="n"&gt;responde&lt;/span&gt; &lt;span class="n"&gt;en&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;la&lt;/span&gt; &lt;span class="n"&gt;RAM&lt;/span&gt; &lt;span class="n"&gt;tarda&lt;/span&gt; &lt;span class="n"&gt;entre&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seg&lt;/span&gt;&lt;span class="err"&gt;ú&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;cifras&lt;/span&gt; &lt;span class="n"&gt;citadas&lt;/span&gt; &lt;span class="n"&gt;por&lt;/span&gt; &lt;span class="n"&gt;Pivot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="cp"&gt;### El caso real: un GROUP BY sobre 99 millones de filas
&lt;/span&gt;
&lt;span class="n"&gt;El&lt;/span&gt; &lt;span class="n"&gt;equipo&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Pivot&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//pivotlake.io/blog/its-the-memory-latency-stupid/) llevó este mismo problema a producción. Tomaron el dataset público "hits" de ClickBench (99 millones de filas) y corrieron esta consulta con una implementación naive de GROUP BY, un HashMap que crece sin ninguna optimización de localidad:&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SELECT count(*), UserID FROM hits GROUP BY UserID&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Con 17 millones de valores únicos de `UserID`, la consulta tardó 3.9 segundos en la primera corrida y 3.6 segundos en la segunda, ya con todos los datos en la caché de página del sistema operativo. Para entender por qué, corrieron `perf stat` fijando el proceso a un núcleo específico con `taskset` y midiendo qué porcentaje de los slots de ejecución del CPU se perdían esperando memoria:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Performance counter stats for 'CPU(s) 3':&lt;/p&gt;

&lt;p&gt;8364109137 ex_no_retire.load_not_complete    # 50.1 % backend_bound_memory&lt;br&gt;
 38233214040 de_no_dispatch_per_slot.backend_stalls&lt;br&gt;
 8977647849 ex_no_retire.not_complete&lt;br&gt;
 11861387798 ls_not_halted_cyc&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
El 50,1% de `backend_bound_memory` significa que, durante la mitad del tiempo de ejecución, el CPU tenía trabajo asignado (y el monitor de recursos lo mostraba ocupado) pero no estaba completando ninguna instrucción: estaba parado, esperando que la RAM le devolviera el siguiente valor de `UserID`. Con 17 millones de claves dispersas en un HashMap, casi ningún acceso cae dentro de L1, L2 o L3.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;sequenceDiagram&lt;br&gt;
    participant CPU as CPU&lt;br&gt;
    participant L1 as Cache L1&lt;br&gt;
    participant L2 as Cache L2&lt;br&gt;
    participant L3 as Cache L3&lt;br&gt;
    participant RAM as DRAM&lt;br&gt;
    CPU-&amp;gt;&amp;gt;L1: pide UserID en direccion X&lt;br&gt;
    L1--&amp;gt;&amp;gt;CPU: miss&lt;br&gt;
    CPU-&amp;gt;&amp;gt;L2: pide direccion X&lt;br&gt;
    L2--&amp;gt;&amp;gt;CPU: miss&lt;br&gt;
    CPU-&amp;gt;&amp;gt;L3: pide direccion X&lt;br&gt;
    L3--&amp;gt;&amp;gt;CPU: miss&lt;br&gt;
    CPU-&amp;gt;&amp;gt;RAM: pide direccion X&lt;br&gt;
    RAM--&amp;gt;&amp;gt;CPU: dato, 50-100 ns despues&lt;br&gt;
    Note over CPU,RAM: el dato se copia a L1, L2 y L3 al volver&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;
&lt;span class="gu"&gt;## Cómo empezar: medir la latencia de memoria con perf en Linux&lt;/span&gt;

Dependencias en Ubuntu o Debian: el paquete &lt;span class="sb"&gt;`linux-tools-common`&lt;/span&gt; y la versión específica del kernel, &lt;span class="sb"&gt;`linux-tools-$(uname -r)`&lt;/span&gt;. En Arch Linux o Fedora el paquete se llama simplemente &lt;span class="sb"&gt;`perf`&lt;/span&gt;. En macOS la herramienta equivalente es Instruments (incluida en Xcode); en Windows, Windows Performance Recorder (WPR).

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;sudo apt install linux-tools-common linux-tools-$(uname -r)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Guardá el programa de la sección anterior como `latencia.c`, compilalo con optimizaciones (sin `-O2` el compilador puede comportarse distinto) y corré `perf stat` sobre el binario:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;gcc -O2 -o latencia latencia.c&lt;br&gt;
perf stat -M backend_bound_memory,retiring -- ./latencia&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;
Vas a ver dos números: &lt;span class="sb"&gt;`backend_bound_memory`&lt;/span&gt; (porcentaje de slots esperando memoria) y &lt;span class="sb"&gt;`retiring`&lt;/span&gt; (porcentaje de slots que efectivamente completaron una instrucción). Si tu kernel bloquea el acceso a los contadores de hardware sin privilegios, vas a necesitar &lt;span class="sb"&gt;`sudo`&lt;/span&gt; o ajustar temporalmente &lt;span class="sb"&gt;`/proc/sys/kernel/perf_event_paranoid`&lt;/span&gt; a &lt;span class="sb"&gt;`-1`&lt;/span&gt;.
&lt;span class="gt"&gt;
&amp;gt; **💡 Tip:** No hay un número universal bueno de backend_bound_memory: lo que importa es comparar el mismo programa en dos versiones, como el bucle secuencial contra el disperso del ejemplo anterior. Si tu versión optimizada no bajó ese porcentaje, no solucionaste el problema de memoria, solo lo escondiste.&lt;/span&gt;

&lt;span class="gu"&gt;## Casos de uso reales en motores de bases de datos&lt;/span&gt;

Los motores columnares como &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;ClickHouse&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://clickhouse.com/docs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; o DuckDB no usan un único HashMap gigante para un GROUP BY. En cambio, dividen el trabajo en dos fases: una agregación local por lotes, vectorizada con instrucciones SIMD y que cabe entera en L1 o L2, y una fusión global al final, cuando ya hay muchos menos valores que combinar. Esa es, en esencia, la técnica que describe Pivot para evitar el escenario del 50,1% de &lt;span class="sb"&gt;`backend_bound_memory`&lt;/span&gt;: particionar las claves por hash en N baldes, de forma que cada balde entre en una caché de nivel 2 o 3 en vez de dispersarse por toda la RAM.

El mismo principio aparece en sistemas muy distintos: un índice ordenado tipo árbol B+ agrupa físicamente las claves cercanas para que una búsqueda toque pocas páginas de memoria, y un motor de videojuegos que itera un "array de estructuras" en vez de una "estructura de arrays" paga el mismo costo de fallos de caché que el HashMap naive de este artículo. La jerarquía de caché de la CPU no es un detalle de bases de datos: es una restricción física que atraviesa cualquier programa que mueva suficientes datos.

&lt;span class="gu"&gt;## Errores comunes y buenas prácticas&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="gs"&gt;**Confundir CPU al 100% con CPU saturado de trabajo útil**&lt;/span&gt;: el sistema operativo marca ocupado cualquier núcleo con una tarea asignada, sin importar si esa tarea avanza o está detenida esperando RAM.- &lt;span class="gs"&gt;**Medir solo con un reloj de pared**&lt;/span&gt;: un cronómetro dice que algo tardó más, pero no dice por qué. Sin &lt;span class="sb"&gt;`perf stat`&lt;/span&gt; es imposible distinguir un cuello de botella de memoria de uno de CPU puro.- &lt;span class="gs"&gt;**Elegir una estructura de datos sin pensar en la cardinalidad**&lt;/span&gt;: un HashMap es perfecto con miles de claves y un desastre con decenas de millones, no por el algoritmo en sí, sino porque deja de caber en cualquier caché.- &lt;span class="gs"&gt;**Ignorar el false sharing en código multihilo**&lt;/span&gt;: dos hilos que escriben en variables distintas pero ubicadas en la misma línea de caché de 64 bytes se invalidan la caché mutuamente en cada escritura, aunque lógicamente no compartan ningún dato.- &lt;span class="gs"&gt;**No alinear structs críticas**&lt;/span&gt;: dejar que el padding del compilador fragmente una estructura usada en un bucle caliente puede hacer que ocupe dos líneas de caché en vez de una, duplicando los accesos a memoria necesarios.

&lt;span class="gu"&gt;## Comparativa de estrategias de agregación&lt;/span&gt;
EstrategiaCuándo usarlaVentajaLimitaciónHashMap simple (naive)Pocas claves únicas (miles)Simple de implementar y de razonarCache misses constantes con millones de clavesPartición por hash (radix)Datasets grandes con muchas claves únicasCada partición cabe en L2 o L3Requiere una pasada extra para particionarAgregación vectorizada por lotesMotores columnares (ClickHouse, DuckDB)Aprovecha SIMD y mantiene todo en L1Mucho más compleja de implementar desde ceroEstructuras aproximadas (HyperLogLog)Solo necesitás un conteo aproximado de distintosMemoria constante, muy rápidaNo da el valor exacto ni el desglose por grupo
&lt;span class="gu"&gt;## Profundizando: qué hay detrás de backend_bound_memory&lt;/span&gt;

Los procesadores modernos no ejecutan instrucciones estrictamente en el orden del código fuente: usan ejecución fuera de orden, adelantando instrucciones que no dependen del resultado que todavía está esperando memoria. Cuando ese margen de instrucciones independientes se agota y el núcleo literalmente no tiene nada más para hacer mientras espera, ahí aparece el &lt;span class="sb"&gt;`backend_bound_memory`&lt;/span&gt; que midió Pivot: el porcentaje de slots de ejecución que quedaron vacíos por falta de datos, no por falta de trabajo.

Otro factor que agrava el problema en servidores multisocket es &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;NUMA&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://en.wikipedia.org/wiki/Non-uniform_memory_access&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;, el acceso no uniforme a memoria: si el dato que falta está en el banco de RAM conectado al otro socket, la latencia sube por encima de los 50-100 ns de un acceso local, porque el pedido tiene que cruzar la interconexión entre sockets. Fijar procesos a un núcleo cercano a su memoria, lo que hace &lt;span class="sb"&gt;`taskset`&lt;/span&gt; en el ejemplo de Pivot, es una forma simple de evitar ese costo extra.

La decisión de cuántos bits de hash usar para particionar también importa: con muy pocas particiones, cada una sigue siendo más grande que L3; con demasiadas, el overhead de manejarlas (metadata, branching) supera el ahorro. El objetivo práctico es que el conjunto de trabajo de cada partición, las claves y contadores que se tocan repetidamente, quepa en L2 (del orden de 1 MB) para que la mayoría de los accesos del bucle caliente resuelvan ahí y no en L3 ni en RAM.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;flowchart TD&lt;br&gt;
    subgraph Naive["Agregacion naive"]&lt;br&gt;
    A1["Fila nueva"] --&amp;gt; A2["Hash disperso en todo el HashMap"]&lt;br&gt;
    A2 --&amp;gt; A3["Acceso a RAM en casi cada fila"]&lt;br&gt;
    end&lt;br&gt;
    subgraph Particionada["Agregacion particionada"]&lt;br&gt;
    B1["Fila nueva"] --&amp;gt; B2["Hash mod N particiones"]&lt;br&gt;
    B2 --&amp;gt; B3["Particion cabe en L2 o L3"]&lt;br&gt;
    B3 --&amp;gt; B4["Acceso mayormente dentro de cache"]&lt;br&gt;
    end&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Un acceso a RAM cruzando sockets en NUMA puede superar ampliamente los 50-100 ns de un acceso local.
&amp;gt; **⚠️ Ojo:** Particionar de más tiene un costo real: cada partición extra suma metadata y ramas condicionales. Si tu dataset ya cabe en L3 sin particionar, agregar particiones solo suma complejidad sin ninguna ganancia medible.

📖 Resumen en Telegram: [Ver resumen](https://telegra.ph/Latencia-de-memoria-qué-es-y-por-qué-tu-CPU-no-rinde-al-100-10-31)

Tu próximo paso: compilá el programa `latencia.c` de este artículo, corré `perf stat -M backend_bound_memory,retiring -- ./latencia` dos veces (bucle secuencial y disperso) y compará ambos porcentajes en tu propia máquina.

## Preguntas frecuentes

### ¿Por qué un CPU al 100% no refleja el tiempo de acceso a RAM real?

Porque el sistema operativo mide ocupación, no progreso: un núcleo con una tarea asignada aparece como 100% aunque esa tarea esté detenida esperando una respuesta de memoria. Solo herramientas como `perf stat` distinguen entre ciclos que completan trabajo y ciclos que esperan.

### ¿Qué diferencia hay entre la jerarquía de caché de la CPU y la memoria RAM?

La jerarquía de caché son varios niveles de memoria pequeños y rápidos (L1, L2, L3) soldados dentro del propio chip del procesador; la RAM es memoria externa, mucho más grande pero entre 50 y 100 veces más lenta de acceder que la caché L1.

### ¿Cómo mido la velocidad de acceso a memoria en Linux?

Con `perf stat`, usando grupos de métricas como `backend_bound_memory` y `retiring`, que muestran qué porcentaje de los slots de ejecución del CPU se perdió esperando memoria frente a los que completaron una instrucción.

### ¿Qué significa backend_bound_memory en perf stat?

Es el porcentaje de slots de ejecución donde el CPU tenía una instrucción pendiente de completar pero no pudo avanzar porque estaba esperando un dato de memoria. Un valor alto, como el 50,1% que midió Pivot en su GROUP BY naive, indica que el cuello de botella es memoria, no cómputo.

### ¿Los ciclos de espera por memoria afectan igual a todas las bases de datos?

No a todas por igual: los motores columnares como ClickHouse o DuckDB mitigan el problema con agregación vectorizada y particionada, mientras que una implementación naive de GROUP BY sobre un HashMap sin particionar sufre el costo completo con datasets de millones de claves únicas.

### ¿Se pueden eliminar del todo los ciclos de espera por memoria?

No del todo: la física de la DRAM impone un piso de 50-100 ns por acceso que ningún software puede evitar. Lo que sí se puede hacer es reducir cuántas veces el programa necesita ese viaje, manteniendo el conjunto de trabajo dentro de L1, L2 o L3 el mayor tiempo posible.

## Referencias

- [Pivot blog](https://pivotlake.io/blog/its-the-memory-latency-stupid/): benchmark original de GROUP BY naive sobre el dataset "hits" de ClickBench, con los contadores de perf stat citados en este artículo.- [Wikipedia: CPU cache](https://en.wikipedia.org/wiki/CPU_cache): explicación general de los niveles de caché L1, L2 y L3 y su rol en la jerarquía de memoria.- [Perf Wiki (kernel.org)](https://perf.wiki.kernel.org/index.php/Main_Page): documentación oficial de la herramienta perf y sus eventos de hardware.- [ClickHouse Docs](https://clickhouse.com/docs): documentación del motor columnar que usa agregación vectorizada y particionada para GROUP BY.

📱 **¿Te gusta este contenido?** Únete a nuestro canal de Telegram [@programacion](https://t.me/programacion) donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>networking</category>
      <category>devops</category>
      <category>linux</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>ChatGPT: un link bastaba para tomar control casi total de la cuenta</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Sat, 31 Oct 2026 14:36:31 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/chatgpt-un-link-bastaba-para-tomar-control-casi-total-de-la-cuenta-3pnj</link>
      <guid>https://dev.to/lu1tr0n/chatgpt-un-link-bastaba-para-tomar-control-casi-total-de-la-cuenta-3pnj</guid>
      <description>&lt;p&gt;Bastaba con abrir un enlace de ChatGPT compartido por otra persona para que un atacante explotara una vulnerabilidad en ChatGPT y tomara el control total de la cuenta de la víctima. No hacía falta instalar una app, unirse a un proyecto ni abrir las herramientas de desarrollador: solo clickear el link.&lt;/p&gt;

&lt;p&gt;La firma de seguridad Parameter reportó el fallo el 26 de octubre de 2026 y OpenAI lo corrigió ese mismo día, clasificándolo como severidad P1, la más alta de su programa de recompensas. El equipo publicó el análisis técnico completo dos días después, el 28 de octubre.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Abrir un enlace de ChatGPT compartido bastaba para que un atacante tomara control total de la cuenta.- La cadena combinó un gráfico, la librería MathLive y el modo Preview para saltar el sandbox de ChatGPT.- El ataque usó un JSONP de YouTube para esquivar la Content Security Policy de chatgpt.com.- OpenAI corrigió el fallo el 26 de octubre de 2026 y lo marcó como severidad P1.- Parameter publicó el hallazgo completo el 28 de octubre de 2026 con el detalle técnico del exploit.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Qué es ChatGPT
&lt;/h2&gt;

&lt;p&gt;ChatGPT es el chatbot de inteligencia artificial de OpenAI, basado en modelos de lenguaje grande, que permite conversar, generar código y compartir conversaciones públicamente mediante un enlace. Esa función de compartir, junto con el modo Preview para ejecutar HTML, fue el origen de la vulnerabilidad en ChatGPT que Parameter reportó en octubre de 2026.&lt;/p&gt;

&lt;p&gt;El fallo vivía en la combinación de dos funciones que conviven en la misma página: el Preview, que ejecuta HTML dentro de un marco aislado con una dirección web distinta, y un gráfico interactivo que carga una librería externa de matemáticas llamada MathLive. Cada función por separado funcionaba como estaba pensada.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué pasó
&lt;/h2&gt;

&lt;p&gt;El ataque arrancó con una conversación normal de ChatGPT que el atacante publicó usando la función de compartir, la misma que cualquier usuario emplea para enviarle un chat a un colega. Dentro de esa conversación había un gráfico matemático interactivo y un bloque de código HTML que ChatGPT convierte en una pequeña página mediante Preview.&lt;/p&gt;

&lt;p&gt;Cuando la víctima abría el enlace, el gráfico cargaba MathLive en la página principal de chatgpt.com y, sin que nadie lo pidiera, instalaba un listener para mensajes &lt;code&gt;postMessage&lt;/code&gt; relacionados con su teclado virtual en pantalla. El Preview, en cambio, corría en un origen distinto y no podía leer directamente el documento de la página principal, porque la separación de orígenes del navegador se lo impedía.&lt;/p&gt;

&lt;p&gt;Pero el Preview sí podía enviar un mensaje a través de &lt;code&gt;postMessage&lt;/code&gt;, el mecanismo que dos ventanas usan para comunicarse incluso cuando el navegador les impide leerse mutuamente. El listener de MathLive, instalado minutos antes por el gráfico, se convirtió en el buzón donde el Preview depositó su carga.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contexto e historia
&lt;/h2&gt;

&lt;p&gt;ChatGPT permite compartir conversaciones públicamente desde 2023, y el modo Preview, que convierte un bloque de código en una página funcional, se sumó después para que los usuarios probaran el código generado sin salir del chat. Cada función pasó sus propias revisiones de seguridad por separado.&lt;/p&gt;

&lt;p&gt;El problema apareció en la intersección de ambas, un patrón frecuente en aplicaciones web complejas: dos equipos distintos construyen piezas razonablemente seguras, pero nadie revisa qué pasa cuando esas piezas conviven en la misma pestaña del navegador. MathLive es una librería de código abierto para edición de fórmulas matemáticas, usada por ChatGPT para renderizar ecuaciones.&lt;/p&gt;

&lt;p&gt;Parameter es una firma de investigación que audita productos de inteligencia artificial. OpenAI mantiene un programa público de recompensas por vulnerabilidades y clasificó este hallazgo como P1, la categoría más grave, reservada para fallos que permiten comprometer cuentas de usuarios sin que estos hagan nada fuera de lo normal.&lt;br&gt;
El Preview de ChatGPT ejecuta HTML en un origen aislado, separado de chatgpt.com.&lt;/p&gt;
&lt;h2&gt;
  
  
  Detalles técnicos: cómo funciona la vulnerabilidad en ChatGPT paso a paso
&lt;/h2&gt;

&lt;p&gt;El fallo no fue un descuido aislado, sino una política de origen demasiado permisiva en el controlador de MathLive. Cuando el Preview mandaba un mensaje &lt;code&gt;postMessage&lt;/code&gt;, el controlador de nivel superior de MathLive aceptaba el mensaje sin comprobar quién lo había enviado, porque su configuración de origen estaba fijada en &lt;code&gt;none&lt;/code&gt;: la opción que acepta remitentes de cualquier dirección web.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mathlive#virtual-keyboard-message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;update-setting&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;layouts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Compatibility&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;compatibility&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;markup&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;
  &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mathlive#virtual-keyboard-message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;show&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El primer mensaje reemplazaba el diseño del teclado virtual con HTML a elección del atacante. El segundo le ordenaba a MathLive mostrar ese teclado, lo que forzaba a la librería a insertar el HTML en el documento real de chatgpt.com. Una función llamada &lt;code&gt;createHTML&lt;/code&gt; debía sanitizar esa cadena, pero solo la marcaba como confiable y la dejaba pasar intacta hacia &lt;code&gt;innerHTML&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Insertar HTML con &lt;code&gt;innerHTML&lt;/code&gt; no ejecuta scripts por sí solo: el navegador los ignora por diseño. Para saltar esa barrera, el HTML inyectado incluía un &lt;code&gt;iframe&lt;/code&gt; con el atributo &lt;code&gt;srcdoc&lt;/code&gt;, que permite empotrar una página completa dentro de otra usando una cadena de texto. MathLive insertó ese iframe sin el atributo &lt;code&gt;sandbox&lt;/code&gt;, así que el navegador le asignó la identidad de &lt;code&gt;https://chatgpt.com&lt;/code&gt; y le dio acceso a la página que lo contenía.&lt;/p&gt;

&lt;p&gt;Quedaba un obstáculo más. La Content Security Policy de ChatGPT bloquea JavaScript en línea y restringe qué dominios pueden servir scripts, pero el equipo de Parameter encontró que la política permitía cargar scripts desde dominios de YouTube. Aprovecharon un endpoint JSONP (una respuesta JSON envuelta en una función de JavaScript) para que el navegador ejecutara código arbitrario camuflado como una llamada legítima a YouTube.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Ojo:&lt;/strong&gt; Un endpoint JSONP en un dominio permitido por la Content Security Policy equivale a una lista blanca con un agujero: cualquier script que esa URL pueda devolver corre con los privilegios del sitio que lo permitió.&lt;br&gt;
Pieza de la cadenaRol en el ataquePor qué fallóGráfico interactivoCarga MathLive dentro de la página principalInstala un listener de postMessage sin que el usuario lo noteChatGPT PreviewEjecuta HTML y JavaScript en un origen aisladoEl aislamiento bloquea lectura directa del DOM, no postMessageMathLive virtual-keyboard-messageRecibe el mensaje y lo inserta en el DOM realPolítica de origen en none: acepta mensajes de cualquier remitentecreateHTML / innerHTMLPasa el HTML a la página sin filtrarloMarca el string como confiable sin sanitizarloiframe srcdoc sin sandboxEjecuta JavaScript con la identidad de chatgpt.comNo lleva el atributo sandbox que limitaría sus permisosJSONP de YouTubeEsquiva la Content Security PolicyEl dominio de YouTube estaba permitido en script-src&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;flowchart&lt;/span&gt; &lt;span class="nv"&gt;TD&lt;/span&gt;
&lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Atacante publica una conversacion de ChatGPT"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Victima abre el enlace compartido"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Preview carga MathLive y ejecuta postMessage"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"MathLive inserta HTML sin sanitizar en el DOM real"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;D&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;E&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"iframe srcdoc sin sandbox ejecuta JavaScript como chatgpt.com"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;E&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"El script bypassea la CSP con JSONP de YouTube"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;F&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;G&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"El atacante lee chats privados y llama a las APIs autenticadas"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con el script corriendo dentro del origen de chatgpt.com, el atacante ya no necesitaba manipular la pantalla ni engañar a la víctima con un clic adicional. El código podía llamar a las mismas APIs internas que usa la interfaz de ChatGPT para listar conversaciones, leer su contenido y enviar los datos a un servidor externo, todo con la sesión autenticada de la víctima.&lt;br&gt;
Parameter clasificó el hallazgo como severidad P1, la categoría más alta del programa de OpenAI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Impacto y análisis
&lt;/h2&gt;

&lt;p&gt;La vulnerabilidad en ChatGPT no se limitaba a mostrar una alerta o cambiar el aspecto de la página: el script podía ejecutar cualquier acción que la propia víctima pudiera hacer dentro de su cuenta. Parameter confirmó que podía enumerar la lista completa de conversaciones, incluidas las que nunca se habían compartido, y extraer su contenido.&lt;/p&gt;

&lt;p&gt;Lo que convierte este hallazgo en algo más serio que un XSS tradicional es el vector de entrada. La víctima no visitó un sitio sospechoso ni pegó código en ninguna consola: abrió un enlace de ChatGPT, publicado desde la función de compartir que el propio producto promueve para que los usuarios intercambien conversaciones útiles.&lt;/p&gt;

&lt;p&gt;El riesgo escala con la cantidad de enlaces que circulan a diario, porque la función de compartir se usa para tutoriales, demos y soporte técnico. Cualquiera de esos enlaces podía convertirse, durante la ventana de exposición, en una trampa silenciosa para quien lo abriera.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué sigue
&lt;/h2&gt;

&lt;p&gt;OpenAI desplegó la corrección el mismo 26 de octubre de 2026, antes de que Parameter publicara el detalle técnico. La reparación probablemente endureció al menos tres puntos: la política de origen de MathLive, el atributo sandbox del iframe generado y la lista de dominios permitidos en la Content Security Policy para scripts de YouTube.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Tip:&lt;/strong&gt; Si tu aplicación usa postMessage entre ventanas o iframes, validá siempre &lt;code&gt;event.origin&lt;/code&gt; contra una lista explícita de dominios confiables antes de procesar el mensaje. Nunca aceptes el valor por defecto que permite cualquier origen.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;El caso deja una lección para cualquier equipo que integre librerías de terceros dentro de una aplicación con sesión autenticada: aunque cada pieza pase su propia revisión de seguridad, la combinación de piezas necesita su propia auditoría. Parameter construyó la cadena completa probando, uno por uno, qué podía alcanzar el código dentro del Preview.&lt;/p&gt;

&lt;p&gt;No hay, por ahora, evidencia pública de que la falla P1 se explotara contra usuarios reales antes del parche. OpenAI y Parameter coordinaron la divulgación de forma responsable, con el aviso técnico publicado solo después de confirmar la corrección en producción.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: &lt;a href="https://telegra.ph/ChatGPT-un-link-bastaba-para-tomar-control-casi-total-de-la-cuenta-10-31" rel="noopener noreferrer"&gt;Ver resumen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si desarrollás con iframes, postMessage o librerías de terceros dentro de una app con sesión activa, revisá hoy mismo cada listener de mensajes y confirmá que valide el origen antes de leer su contenido.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué es MathLive y qué rol tuvo en el fallo de ChatGPT?
&lt;/h3&gt;

&lt;p&gt;MathLive es una librería de código abierto que ChatGPT usa para renderizar y editar fórmulas matemáticas con un teclado virtual. Su listener de mensajes sin validar origen fue la puerta que un atacante usó para inyectar HTML en la página real de ChatGPT.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué tenía que hacer la víctima para quedar expuesta en ChatGPT?
&lt;/h3&gt;

&lt;p&gt;Solo abrir el enlace de la conversación compartida por el atacante. No se requería instalar nada, iniciar sesión de nuevo ni interactuar con ningún elemento adicional de la página.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué datos de ChatGPT podía robar un atacante con esta falla P1?
&lt;/h3&gt;

&lt;p&gt;El código podía enumerar la lista de conversaciones de la víctima, leer el contenido de chats privados nunca compartidos y enviarlo a un servidor externo, además de llamar a las APIs autenticadas de la cuenta.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Sigue activa la vulnerabilidad en ChatGPT hoy?
&lt;/h3&gt;

&lt;p&gt;No. OpenAI corrigió el fallo el 26 de octubre de 2026, el mismo día en que Parameter lo reportó, antes de que se publicara el análisis técnico completo.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿En qué se diferencia este ataque a ChatGPT de un XSS clásico?
&lt;/h3&gt;

&lt;p&gt;No dependió de inyectar un script directamente, sino de encadenar un bypass de postMessage, un fallo de sanitización en una librería y un bypass de la Content Security Policy vía JSONP para lograr ejecución de código con la identidad del sitio.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo evitar un bypass como el de MathLive en tu propia aplicación?
&lt;/h3&gt;

&lt;p&gt;Validar siempre el origen de cada mensaje postMessage recibido, sanitizar cualquier HTML antes de asignarlo a innerHTML, agregar el atributo sandbox a los iframes con srcdoc y revisar qué dominios de terceros habilita tu Content Security Policy en script-src.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.parameter.ai/labs/we-found-a-gap-at-openai" rel="noopener noreferrer"&gt;Parameter&lt;/a&gt;: informe técnico completo de la vulnerabilidad, "Do the Math: How We Took Over ChatGPT Accounts".- &lt;a href="https://github.com/arnog/mathlive" rel="noopener noreferrer"&gt;MathLive en GitHub&lt;/a&gt;: repositorio oficial de la librería de edición de fórmulas matemáticas usada por ChatGPT.- &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy" rel="noopener noreferrer"&gt;MDN Web Docs&lt;/a&gt;: documentación de referencia sobre Content Security Policy y la directiva script-src.- OpenAI: sitio oficial de la empresa responsable de ChatGPT.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Binance pierde $6.300 millones, la mayoría en un hackeo de 20 minutos</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Sat, 31 Oct 2026 02:31:01 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/binance-pierde-6300-millones-la-mayoria-en-un-hackeo-de-20-minutos-4d5d</link>
      <guid>https://dev.to/lu1tr0n/binance-pierde-6300-millones-la-mayoria-en-un-hackeo-de-20-minutos-4d5d</guid>
      <description>&lt;p&gt;Binance perdió $6.300 millones en criptomonedas en apenas 20 minutos la tarde del 29 de octubre de 2026, en lo que firmas de rastreo cripto ya califican como el mayor robo de la historia del sector. El hackeo a Binance drenó billeteras calientes en al menos diez blockchains distintas antes de que el exchange lograra reaccionar.&lt;/p&gt;

&lt;p&gt;De inmediato, Binance suspendió depósitos y retiros mientras investigaba, y dice haber congelado junto a otras empresas cerca de la mitad de los fondos. Tres firmas de inteligencia blockchain apuntan a un mismo sospechoso: hackers vinculados a Corea del Norte.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Hackers robaron $6.300 millones de Binance el 29 de octubre de 2026 en apenas 20 minutos.- El ataque drenó billeteras calientes en al menos diez blockchains, entre ellas Ethereum y Bitcoin.- TRM Labs, Chainalysis y Elliptic vinculan el robo al grupo norcoreano TraderTraitor.- Firmas cripto lograron congelar cerca de $2.800 millones, un 44% del total robado.- Un ingeniero con laptop comprometido habría sido el punto de entrada inicial, según Binance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Qué es Binance
&lt;/h2&gt;

&lt;p&gt;Binance es el mayor exchange de criptomonedas del mundo por volumen de operaciones, fundado en 2017 por Changpeng Zhao, y la plataforma afectada por el hackeo a Binance del 29 de octubre de 2026. Opera billeteras calientes conectadas a internet en más de diez blockchains, entre ellas Ethereum, Bitcoin, Tron y Solana.&lt;/p&gt;

&lt;p&gt;El exchange mueve a diario miles de operaciones en cientos de criptomonedas y sostiene esas billeteras calientes para dar liquidez inmediata a los retiros de sus usuarios. Esa misma conexión permanente a internet fue la que convirtió a esas billeteras en el blanco del ataque.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué pasó en el hackeo a Binance
&lt;/h2&gt;

&lt;p&gt;El 29 de octubre de 2026, alrededor de las 4 de la tarde hora del este de Estados Unidos, atacantes comenzaron a vaciar billeteras calientes de Binance en al menos diez blockchains distintas, entre ellas Ethereum, Bitcoin, Tron y Solana. Según el análisis de &lt;a href="https://www.trmlabs.com" rel="noopener noreferrer"&gt;TRM Labs&lt;/a&gt;, la mayor parte de los $6.300 millones salió en una ventana de apenas 20 minutos, repartida en múltiples direcciones controladas por un mismo atacante.&lt;/p&gt;

&lt;p&gt;Casi de inmediato, Binance suspendió todos los depósitos y retiros de la plataforma mientras investigaba el incidente, y confirmó en un comunicado que trabaja junto a las autoridades para identificar a los responsables. La empresa dijo que, junto a otras firmas del sector, logró congelar alrededor de la mitad de los fondos robados antes de que los atacantes pudieran moverlos o intentar cambiarlos por dinero fiat.&lt;/p&gt;

&lt;p&gt;En un comunicado posterior, Binance explicó que su investigación inicial apuntaba a una laptop comprometida de un ingeniero de la compañía, aunque aclaró que encontró puntos de brecha adicionales a medida que avanzaba el análisis forense. "Este fue un ataque complejo, y estamos haciendo todo lo posible en coordinación con las autoridades para resolverlo", señaló la empresa en su comunicado.&lt;br&gt;
Las billeteras calientes conectan fondos de un exchange a internet para procesar retiros al instante.&lt;/p&gt;
&lt;h2&gt;
  
  
  Contexto: la escalada de robos cripto de Corea del Norte
&lt;/h2&gt;

&lt;p&gt;El hackeo no surgió de la nada. Durante años, distintos grupos de hackers norcoreanos atacaron exchanges y protocolos de finanzas descentralizadas para financiar al régimen, que opera bajo sanciones internacionales severas. Dentro de ese ecosistema, un subgrupo conocido como TraderTraitor se especializó en golpes poco frecuentes pero de altísimo perfil.&lt;/p&gt;

&lt;p&gt;El antecedente más citado es el robo de $1.500 millones al exchange Bybit en 2025, que el FBI atribuyó públicamente a TraderTraitor. El grupo también quedó vinculado al robo del exchange Bitget el mes pasado, en septiembre de 2026, según Chainalysis. Ese patrón, atacar, lavar los fondos y reaparecer meses después contra un blanco más grande, es consistente con lo ocurrido en Binance.&lt;/p&gt;

&lt;p&gt;"Creemos que Corea del Norte es probablemente responsable", dijo Tom Robinson, cofundador y científico jefe de Elliptic, a la revista Wired. "Si Corea del Norte está detrás de esto, este robo casi duplicaría todo lo que el régimen ha robado en cripto hasta la fecha."&lt;/p&gt;
&lt;h2&gt;
  
  
  Detalles técnicos: cómo operó el ciberataque al exchange
&lt;/h2&gt;

&lt;p&gt;Lo que distingue a este incidente no es solo el monto, sino la preparación. Según TRM Labs, el atacante empezó a preparar el golpe al menos 36 horas antes del robo. Una de sus billeteras recibió tres retiros pequeños durante un periodo de prueba, antes de que la operación se expandiera.&lt;/p&gt;

&lt;p&gt;La mañana del 29 de octubre, según la misma firma, el atacante desplegó una primera versión del código del ataque y la probó contra dos billeteras. Más tarde ese mismo día, ensayó la versión final contra una tercera billetera y devolvió esos fondos de prueba a su propia cuenta. Cuatro horas después de ese ensayo, instaló el mismo código en una billetera caliente real de Binance, y el drenaje quedó en marcha.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sequenceDiagram
participant A as Atacante
participant W1 as Billetera de prueba
participant W3 as Billetera de ensayo final
participant H as Billetera caliente de Binance
A-&amp;gt;&amp;gt;W1: retiros pequeños de prueba
A-&amp;gt;&amp;gt;W3: ensaya el código final
W3--&amp;gt;&amp;gt;A: devuelve los fondos de prueba
Note over A,H: cuatro horas después del ensayo
A-&amp;gt;&amp;gt;H: instala el código en producción
H--&amp;gt;&amp;gt;A: drena fondos en 20 minutos
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Las tácticas descritas coinciden con el historial de TraderTraitor, que según el investigador de amenazas de Sophos Rafe Pilling suele apuntar a organizaciones grandes de finanzas descentralizadas. "Esta gente es, en cierto modo, artista a la hora de entrar en estas organizaciones de finanzas distribuidas", dijo Pilling a Wired. "En el pasado, desarrollaron sus propias aplicaciones falsas y las usaron para entrar."&lt;/p&gt;

&lt;p&gt;Elliptic agregó un detalle sobre el financiamiento previo del ataque: el atacante habría fondeado su billetera inicial a través de Tornado Cash, el mezclador de criptomonedas sancionado por el Tesoro de Estados Unidos, y habría ensayado el golpe con antelación, el mismo patrón que se vio en el caso Bybit.&lt;/p&gt;

&lt;p&gt;No hay forma directa de verificar desde afuera las cifras exactas de fondos congelados en cada momento: los números cambian a medida que avanza la investigación y provienen de los paneles públicos que cada firma de rastreo, TRM Labs, Chainalysis y Elliptic, actualiza de forma independiente.&lt;br&gt;
FirmaQué reportóAtribuciónTRM LabsPreparación de al menos 36 horas y ensayo en tres billeteras antes del roboIndicios consistentes con TraderTraitorChainalysisFondos mezclándose en tiempo real con el botín del hackeo a Bitget de septiembreVinculación directa a TraderTraitorEllipticCerca de 44% ($2.800 millones) congelado; billetera inicial fondeada vía Tornado CashSolapamientos con TraderTraitor, sin confirmación oficial&lt;/p&gt;

&lt;h2&gt;
  
  
  Impacto y análisis tras el robo a Binance
&lt;/h2&gt;

&lt;p&gt;Binance afirmó públicamente que cubrirá todas las pérdidas derivadas del incidente, algo que ninguna ley obliga a un exchange a hacer, pero que la compañía ya había hecho en incidentes previos menores para sostener la confianza de sus usuarios.&lt;/p&gt;

&lt;p&gt;El dato más duro, sin embargo, es cuánto de lo robado resulta irrecuperable. Solo los activos emitidos por empresas centralizadas, como las stablecoins, se pueden congelar a pedido de las firmas emisoras. Las criptomonedas nativas de una blockchain pública, una vez que llegan a una billetera que el atacante controla, no tienen un botón de reversión: nadie puede revertir una transacción confirmada en Ethereum o Bitcoin sin el consentimiento de toda la red.&lt;/p&gt;

&lt;p&gt;Chainalysis describió además patrones de lavado de dinero "que no habíamos visto antes", con miles de transacciones procesadas en minutos, lo que sugiere el uso de automatización para dificultar el rastreo de los fondos restantes, buena parte de los cuales todavía circula sin congelar.&lt;br&gt;
Las stablecoins representan casi la totalidad de los fondos que sí pudieron congelarse.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Ojo:&lt;/strong&gt; que una firma de rastreo señale a un grupo no equivale a una atribución oficial. Ni Binance ni las autoridades estadounidenses confirmaron públicamente un vínculo con Corea del Norte al momento de escribir este artículo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Qué sigue
&lt;/h2&gt;

&lt;p&gt;Binance sigue con los depósitos y retiros suspendidos mientras cierra su revisión forense, y todavía no publicó un cronograma para restablecer el servicio por completo. La compañía tampoco respondió públicamente si considera que hackers norcoreanos están detrás del ataque, y se limitó a remitir a su comunicado oficial.&lt;/p&gt;

&lt;p&gt;Para el resto de la industria, el caso vuelve a poner el foco en las billeteras calientes como el punto más débil de cualquier exchange grande. A diferencia del almacenamiento en frío, desconectado de internet, una billetera caliente necesita estar en línea para operar, y eso la expone todo el tiempo. Es previsible que otros exchanges revisen sus propios controles de acceso a esas billeteras tras ver el tamaño de este golpe.&lt;/p&gt;

&lt;p&gt;También queda pendiente si Estados Unidos u otro país formaliza una atribución oficial, algo que en el caso Bybit tardó semanas después del robo inicial.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: &lt;a href="https://telegra.ph/Binance-pierde-6300-millones-la-mayor%C3%ADa-en-un-hackeo-de-20-minutos-10-31" rel="noopener noreferrer"&gt;Ver resumen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Probalo vos: revisá el comunicado oficial de Binance antes de mover fondos en la plataforma y confirmá ahí cuándo se reactivan los depósitos y retiros por completo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué fue el hackeo a Binance de octubre de 2026?
&lt;/h3&gt;

&lt;p&gt;Fue el robo de $6.300 millones en criptomonedas desde billeteras calientes de Binance, ejecutado en una ventana de 20 minutos el 29 de octubre de 2026, con fondos repartidos en al menos diez blockchains distintas.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Quién está detrás del robo a Binance?
&lt;/h3&gt;

&lt;p&gt;Tres firmas de rastreo, TRM Labs, Chainalysis y Elliptic, apuntan con distintos grados de confianza a TraderTraitor, un grupo de hackers vinculado a Corea del Norte. Ni Binance ni las autoridades confirmaron oficialmente esa atribución.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cuánto dinero se recuperó tras el ciberataque al exchange?
&lt;/h3&gt;

&lt;p&gt;Según Elliptic, se congeló cerca del 44% del total, unos $2.800 millones, casi todo en forma de stablecoins. El resto está en criptomonedas nativas que, una vez movidas, son muy difíciles de recuperar.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Binance va a cubrir las pérdidas de sus usuarios?
&lt;/h3&gt;

&lt;p&gt;Sí. Binance declaró públicamente que asumirá todas las pérdidas derivadas del incidente, aunque no detalló un cronograma de pagos ni el mecanismo exacto de compensación.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué es TraderTraitor?
&lt;/h3&gt;

&lt;p&gt;TraderTraitor es un subgrupo dentro del aparato de hackers de Corea del Norte, especializado en ataques poco frecuentes pero de muy alto monto contra exchanges y plataformas de finanzas descentralizadas, como el robo de $1.500 millones a Bybit en 2025.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Se puede confiar en las billeteras calientes de un exchange como Binance?
&lt;/h3&gt;

&lt;p&gt;Las billeteras calientes son necesarias para procesar retiros al instante, pero su conexión permanente a internet las hace más vulnerables que el almacenamiento en frío. La mayoría de los exchanges grandes combina ambos esquemas para repartir el riesgo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.wired.com/story/the-dollar63-billion-binance-hack-was-pulled-off-in-just-20-minutes/" rel="noopener noreferrer"&gt;Wired&lt;/a&gt;: reporte original sobre el hackeo a Binance y las firmas de rastreo que lo analizaron.- &lt;a href="https://www.trmlabs.com" rel="noopener noreferrer"&gt;TRM Labs&lt;/a&gt;: análisis on-chain del robo, la ventana de 20 minutos y la preparación previa del ataque.- &lt;a href="https://www.elliptic.co" rel="noopener noreferrer"&gt;Elliptic&lt;/a&gt;: estimación del porcentaje de fondos congelados y la posible vinculación con Tornado Cash.- &lt;a href="https://www.chainalysis.com" rel="noopener noreferrer"&gt;Chainalysis&lt;/a&gt;: patrones de lavado de dinero detectados y vínculo con el hackeo a Bitget de septiembre de 2026.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>security</category>
      <category>cybersecurity</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Northflank: brecha de seguridad obliga a rotar claves</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Fri, 30 Oct 2026 20:25:49 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/northflank-brecha-de-seguridad-obliga-a-rotar-claves-4560</link>
      <guid>https://dev.to/lu1tr0n/northflank-brecha-de-seguridad-obliga-a-rotar-claves-4560</guid>
      <description>&lt;p&gt;Northflank le dijo a todos sus clientes algo que ningún proveedor de nube quiere admitir en público: asuman que les robaron las claves. La brecha de Northflank, confirmada el 30 de octubre de 2026, obligó a la plataforma a pedir la rotación inmediata de cada variable de entorno, cada secreto y cada credencial almacenada en su infraestructura.&lt;/p&gt;

&lt;p&gt;El aviso llegó en cuatro actualizaciones consecutivas de la &lt;a href="https://status.northflank.com" rel="noopener noreferrer"&gt;página de estado&lt;/a&gt; de la empresa, con un detalle que agrava todo: varios usuarios ya confirmaron que sus claves de API de inteligencia artificial fueron usadas por terceros.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Northflank confirma brecha el 30 de octubre de 2026: rotá ya todas tus variables de entorno y credenciales.- Wiz alertó el acceso a las 11:43 UTC; Northflank parchó su red a las 12:02 y 12:50 UTC.- Varios clientes confirman que sus claves de API de IA ya fueron usadas por atacantes.- Red, certificados, servicios, addons, jobs, builds y logs quedaron en outage mayor a la vez.- La plataforma activó rotación automática de secretos en addons de Postgres y MongoDB.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Qué es Northflank
&lt;/h2&gt;

&lt;p&gt;Northflank es una &lt;a href="https://northflank.com" rel="noopener noreferrer"&gt;plataforma como servicio (PaaS)&lt;/a&gt; que permite desplegar aplicaciones, bases de datos y jobs en contenedores sobre su propia nube o la de terceros, sin que el equipo de desarrollo tenga que administrar Kubernetes a mano. La brecha de Northflank del 30 de octubre afectó justamente esa capa de infraestructura compartida.&lt;/p&gt;

&lt;p&gt;Startups, equipos internos de empresas medianas y desarrolladores independientes usan Northflank para desplegar APIs, workers y bases de datos administradas (Postgres, MongoDB, Redis) sin pagar los precios de AWS o GCP directamente ni mantener un clúster propio.&lt;br&gt;
Wiz detectó la actividad anómala que disparó la respuesta de Northflank a las 11:43 UTC.&lt;/p&gt;
&lt;h2&gt;
  
  
  Qué pasó
&lt;/h2&gt;

&lt;p&gt;Todo arrancó con una alerta automática. A las 11:43 UTC del 30 de octubre, la firma de seguridad en la nube &lt;a href="https://www.wiz.io" rel="noopener noreferrer"&gt;Wiz&lt;/a&gt; notificó actividad anómala en la infraestructura de Northflank. Un minuto después, a las 11:44 UTC, los ingenieros de la plataforma ya estaban revisando la alerta, según el &lt;a href="https://status.northflank.com" rel="noopener noreferrer"&gt;registro público del incidente&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;La respuesta técnica fue rápida, pero no alcanzó para contener el acceso. Northflank aplicó un primer &lt;strong&gt;parche de política de red&lt;/strong&gt; a las 12:02 UTC, uno adicional a las 12:50 UTC y dos más a las 13:05 UTC. A las 13:00 UTC pidió soporte al equipo de respuesta a incidentes (CIRT) de Wiz, señal de que el alcance superaba lo que su propio equipo podía contener solo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sequenceDiagram
participant W as Wiz
participant N as Northflank
participant C as Clientes
W-&amp;gt;&amp;gt;N: alerta de amenaza (11:43 UTC)
N-&amp;gt;&amp;gt;N: parches de red (12:02 y 12:50 UTC)
N-&amp;gt;&amp;gt;W: solicita soporte CIRT (13:00 UTC)
N-&amp;gt;&amp;gt;C: aviso de rotar variables de entorno (13:40 UTC)
Note over N,C: rotacion forzada en Postgres y MongoDB (15:12 UTC)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A las 13:40 UTC, Northflank publicó su primera instrucción pública: rotar las variables de entorno de inmediato. Dieciocho minutos después, a las 13:58 UTC, subió el nivel de alarma: había que asumir que todas las variables de entorno estaban descifradas y desactivar o rotar cada clave. La recomendación pasó de precaución a obligación en menos de media hora.&lt;/p&gt;

&lt;p&gt;La actualización de las 15:12 UTC confirmó lo peor. Northflank activó rotación forzada de secretos en los addons de Postgres y MongoDB para todos los usuarios, sin dejarlo opcional, y recomendó desactivar el acceso público de esos addons. La misma nota reveló que varios clientes ya habían confirmado el uso indebido de sus claves de API de proveedores de inteligencia artificial, lo que sugiere que el atacante no solo copió datos, también los usó.&lt;/p&gt;

&lt;p&gt;A las 19:28 UTC, siete horas y 45 minutos después de la alerta inicial, la investigación seguía abierta. Northflank repitió la instrucción de asumir comprometidas todas las variables de entorno, extendió la advertencia a secret groups y global secrets, y pidió desactivar el acceso público a los addons donde estuviera habilitado. A esa hora no había, en público, una causa raíz confirmada.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contexto e historia
&lt;/h2&gt;

&lt;p&gt;Northflank compite en el segmento de plataformas que prometen simplificar lo que Kubernetes hace complicado: desplegar contenedores, bases de datos administradas y jobs programados detrás de una sola interfaz y una sola API. Railway, Render y Fly.io atacan el mismo problema desde ángulos distintos, pero los tres cargan con el mismo dilema de diseño: para administrar secretos de miles de cuentas, en algún punto del sistema esos secretos tienen que existir en texto plano, aunque sea por microsegundos.&lt;/p&gt;

&lt;p&gt;Ese dilema no es nuevo ni exclusivo de Northflank. A lo largo de 2026, tanto Railway como Vercel atravesaron incidentes de seguridad propios que terminaron en el mismo consejo: rotar credenciales. La diferencia acá es la escala de la respuesta: Northflank no aisló el aviso a un componente puntual, sino que pidió asumir comprometida toda variable de entorno de la plataforma, sin excepción de plan ni de región.&lt;br&gt;
Siete de los once componentes de Northflank seguían en outage mayor horas después del hallazgo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detalles técnicos: el mecanismo detrás de la brecha de Northflank
&lt;/h2&gt;

&lt;p&gt;La pregunta que más repiten los clientes es por qué Northflank no dio una lista acotada de cuentas afectadas. La respuesta tiene que ver con cómo funciona el almacenamiento de secretos en una plataforma multi-tenant: las variables de entorno de cada servicio se guardan cifradas en una base compartida, pero se descifran en memoria cada vez que un workload arranca o se reconstruye. Si un atacante compromete la capa que hace ese descifrado, en teoría puede ver cualquier secreto que pase por ahí, no solo el de una cuenta.&lt;/p&gt;

&lt;p&gt;Eso explica el salto de tono entre las 13:40 UTC (\"rotá por si acaso\") y las 13:58 UTC (\"asumí que ya está descifrado\"). Northflank no tenía, a esa hora, forma de acotar el radio de impacto a un subconjunto de usuarios: la alerta de Wiz apuntaba a la capa de red y de políticas que comparten todos los workloads, según el propio reporte de la página de estado, no a un servicio aislado.&lt;/p&gt;

&lt;p&gt;No hay forma directa de verificar desde afuera si una cuenta puntual fue accedida: Northflank no publicó logs de acceso por cliente ni una herramienta de autodiagnóstico en su panel. La única señal disponible para un usuario es comparar la fecha de creación de sus claves actuales contra el 30 de octubre de 2026; si no las rotó después de esa fecha, debe asumir que están expuestas.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Ojo:&lt;/strong&gt; la recomendación de Northflank cubre tres capas distintas: secretos de workloads, secret groups y global secrets. Rotar solo la primera deja expuestas las otras dos.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Impacto y análisis
&lt;/h2&gt;

&lt;p&gt;El outage no fue cosmético. Siete de los once componentes listados en el &lt;a href="https://status.northflank.com" rel="noopener noreferrer"&gt;tablero de estado&lt;/a&gt; de Northflank (red, certificados, servicios, addons, jobs, builds y logs) cayeron en estado de outage mayor al mismo tiempo. Solo el panel web, la API pública, el sitio de marketing y la documentación siguieron operativos, lo que le permitió a Northflank seguir comunicando el incidente mientras el resto de la plataforma quedaba, en la práctica, inutilizable para desplegar nada nuevo.&lt;br&gt;
ComponenteEstado durante el incidenteQué significa para el usuarioRed (Networking)Outage mayorRutas y balanceo de tráfico entre servicios fallabanCertificadosOutage mayorEmisión y renovación de TLS detenidaServiciosOutage mayorDespliegues de apps no arrancaban con normalidadAddons (bases de datos)Outage mayorPostgres y MongoDB con rotación forzada de secretosJobsOutage mayorTareas programadas y cron jobs sin ejecutarBuildsOutage mayorCompilaciones de imágenes bloqueadasLogs y métricasOutage mayorSin visibilidad para diagnosticar el propio incidenteApp, API, sitio y docsOperativoEl panel y la documentación seguían accesibles&lt;br&gt;
La brecha de Northflank golpeó justo donde más duele para una plataforma de despliegue: si Builds y Services están caídos, un cliente no puede ni sacar una corrección de emergencia. Y si Logs and Metrics también falla, ese mismo cliente queda además a ciegas para entender qué le está pasando a su propia aplicación.&lt;/p&gt;

&lt;p&gt;La plataforma mantiene, según su propio &lt;a href="https://status.northflank.com" rel="noopener noreferrer"&gt;historial de 90 días&lt;/a&gt;, un 99,65% de uptime agregado. Un incidente de esta magnitud puede consumir buena parte de ese margen: siete componentes en outage mayor durante varias horas representan, en la práctica, una caída de disponibilidad considerable para los clientes activos ese día.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué sigue
&lt;/h2&gt;

&lt;p&gt;Northflank no publicó, hasta la actualización de las 19:28 UTC, una causa raíz confirmada. La empresa dijo que \"la investigación sigue en curso\" y que no tenía \"hallazgos confirmados adicionales para compartir en este momento\", la fórmula habitual antes de un post-mortem técnico completo.&lt;/p&gt;

&lt;p&gt;Lo que sí queda claro es la lista de tareas para cualquier cliente de Northflank: rotar secretos de workloads, secret groups y global secrets; desactivar el acceso público de los addons donde esté habilitado; y revisar si alguna clave de proveedor de IA fue usada desde una IP que el cliente no reconoce. Varios usuarios ya confirmaron, en el propio canal de estado, cargos o uso indebido de esas claves.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: &lt;a href="https://telegra.ph/Northflank-brecha-de-seguridad-obliga-a-rotar-claves-10-30" rel="noopener noreferrer"&gt;Ver resumen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Probalo vos: entrá hoy mismo al panel de Northflank, abrí Secret Groups y Global Secrets, y rotá cualquier clave que no hayas tocado desde antes del 30 de octubre de 2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué es Northflank y para qué se usa?
&lt;/h3&gt;

&lt;p&gt;Northflank es una plataforma como servicio que permite desplegar aplicaciones, bases de datos administradas y jobs en contenedores, pensada para equipos que no quieren operar Kubernetes directamente.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué tipo de datos quedaron expuestos en el incidente de ciberseguridad de Northflank?
&lt;/h3&gt;

&lt;p&gt;La propia empresa pidió asumir comprometidas todas las variables de entorno: credenciales de bases de datos, tokens de APIs externas y claves de proveedores de inteligencia artificial almacenadas en workloads, secret groups y global secrets.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo se rotan las claves afectadas por la filtración de credenciales de Northflank?
&lt;/h3&gt;

&lt;p&gt;Desde el panel de Northflank, en las secciones de secretos de cada workload, en Secret Groups y en Global Secrets; además, hay que desactivar el acceso público de los addons donde esté habilitado.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Northflank confirmó quién atacó la plataforma de despliegue en la nube?
&lt;/h3&gt;

&lt;p&gt;No. Hasta la actualización de las 19:28 UTC del 30 de octubre de 2026, la empresa solo confirmó que la investigación seguía abierta, sin atribuir el ataque a un grupo ni publicar una causa raíz.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué componentes de Northflank seguían caídos tras el hallazgo del proveedor PaaS?
&lt;/h3&gt;

&lt;p&gt;Red, certificados, servicios, addons, jobs, builds y logs y métricas quedaron en outage mayor a la vez, mientras el panel web, la API pública, el sitio de marketing y la documentación siguieron operativos.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Debo preocuparme si uso addons de Postgres o MongoDB en Northflank?
&lt;/h3&gt;

&lt;p&gt;Sí: Northflank forzó la rotación de secretos en esos addons para todos los usuarios y recomendó explícitamente desactivar el acceso público donde estuviera habilitado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://status.northflank.com" rel="noopener noreferrer"&gt;Northflank Status&lt;/a&gt;: página oficial de estado con el registro completo del incidente, sus actualizaciones y los componentes afectados.- &lt;a href="https://northflank.com" rel="noopener noreferrer"&gt;Northflank&lt;/a&gt;: sitio oficial de la plataforma como servicio afectada por la brecha.- &lt;a href="https://www.wiz.io" rel="noopener noreferrer"&gt;Wiz&lt;/a&gt;: la firma de seguridad en la nube cuya alerta disparó la respuesta de Northflank al incidente.- &lt;a href="https://es.wikipedia.org/wiki/Plataforma_como_servicio" rel="noopener noreferrer"&gt;Plataforma como servicio (Wikipedia)&lt;/a&gt;: contexto general sobre el modelo PaaS en el que opera Northflank.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>security</category>
      <category>cybersecurity</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Memoria virtual: qué es y cómo simula más RAM de la que hay</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Fri, 30 Oct 2026 16:17:26 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/memoria-virtual-que-es-y-como-simula-mas-ram-de-la-que-hay-36b5</link>
      <guid>https://dev.to/lu1tr0n/memoria-virtual-que-es-y-como-simula-mas-ram-de-la-que-hay-36b5</guid>
      <description>&lt;p&gt;Ahora mismo, el navegador, el editor de código y la terminal que tenés abiertos creen tener acceso a toda la memoria RAM del equipo, aunque sumados pidan mucho más de la que existe físicamente instalada. Eso no es un error de cálculo: es &lt;strong&gt;memoria virtual&lt;/strong&gt;, el mecanismo que sostiene esa ilusión sin que un programa choque con otro.&lt;/p&gt;

&lt;p&gt;La traducción ocurre en hardware, miles de veces por segundo, con una caché especial que la acelera. Esa pieza, el TLB, es la que determina si tu programa corre rápido o se arrastra.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;El espacio de direcciones virtual traduce direcciones lógicas a físicas mediante tablas de páginas.- TLB cachea esas traducciones para evitar consultar la tabla de páginas en cada acceso a memoria.- Un fallo de página ocurre cuando el dato no está en RAM y el kernel debe traerlo del disco.- &lt;code&gt;vmstat&lt;/code&gt; y &lt;code&gt;/proc/
/smaps&lt;/code&gt; muestran en vivo cómo Linux reparte páginas de memoria.- Cada proceso tiene su propio espacio de direcciones virtual, aislado del resto por diseño.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Qué es la memoria virtual?
&lt;/h2&gt;

&lt;p&gt;La memoria virtual es una técnica de gestión de memoria que asigna a cada proceso un espacio de direcciones propio, separado de la RAM física real. El sistema operativo y la MMU traducen esas direcciones a direcciones físicas mediante tablas de páginas, lo que aísla procesos entre sí.&lt;/p&gt;

&lt;p&gt;La unidad básica de esta traducción es la página: un bloque de tamaño fijo, típicamente 4 KB en x86-64, que el sistema mueve, protege y reemplaza como un todo. Cada entrada de la tabla de páginas mapea una página virtual a un marco físico concreto, o marca que esa página no está presente en RAM todavía.&lt;br&gt;
Los procesadores x86-64 actuales direccionan hasta 48 bits de espacio virtual por proceso.&lt;/p&gt;
&lt;h2&gt;
  
  
  Por qué importa la paginación
&lt;/h2&gt;

&lt;p&gt;Sin este esquema, cada programa tendría que conocer en qué dirección física exacta de la RAM va a correr, y dos procesos jamás podrían usar el mismo rango de direcciones sin pisarse. La paginación resuelve eso dándole a cada proceso la ilusión de un espacio de direcciones propio que empieza en cero.&lt;/p&gt;

&lt;p&gt;También habilita el aislamiento de seguridad: un proceso no puede leer ni escribir la memoria de otro porque, simplemente, no tiene entradas en su tabla de páginas que apunten ahí. Y permite algo contraintuitivo, el overcommit, donde el sistema promete más memoria de la que existe físicamente, apostando a que no todos los procesos la van a usar al mismo tiempo.&lt;/p&gt;
&lt;h2&gt;
  
  
  Cómo funciona la paginación, paso a paso
&lt;/h2&gt;

&lt;p&gt;Cuando un proceso accede a una dirección, la CPU primero consulta el TLB (Translation Lookaside Buffer), una caché pequeña y muy rápida de traducciones recientes. Si la traducción está ahí (TLB hit), la dirección física sale casi gratis. Si no está (TLB miss), el hardware recorre la tabla de páginas completa, un proceso llamado page table walk que puede costar cientos de ciclos de reloj.&lt;/p&gt;

&lt;p&gt;Si la tabla de páginas indica que la página no está en RAM, ocurre un fallo de página (page fault). Hay dos tipos: el fallo menor, donde el kernel solo necesita asignar un marco físico libre y actualizar la tabla (por ejemplo en la primera escritura tras un &lt;code&gt;malloc&lt;/code&gt;), y el fallo mayor, donde además hay que traer el contenido desde disco o desde el área de swap, mucho más lento.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;flowchart&lt;/span&gt; &lt;span class="nv"&gt;TD&lt;/span&gt;
    &lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Direccion virtual del proceso"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"MMU consulta el TLB"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"Hit"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Direccion fisica en RAM"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"Miss"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Camina la tabla de paginas"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;D&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;E&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Pagina presente?"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;E&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"Si"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;
    &lt;span class="nv"&gt;E&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"No"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Fallo de pagina: interviene el kernel"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;F&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;G&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Carga la pagina desde disco o swap"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;G&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cuando el fallo es mayor, el kernel suspende al proceso, pide la página al dispositivo de almacenamiento y lo reanuda cuando el dato está listo. Esa secuencia es la que convierte un simple acceso a memoria en una operación de entrada/salida completa.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sequenceDiagram
    participant P as Proceso
    participant M as MMU
    participant K as Kernel
    participant D as DiscoSwap
    P-&amp;gt;&amp;gt;M: accede a direccion virtual
    M-&amp;gt;&amp;gt;M: busca en TLB y tabla de paginas
    M--&amp;gt;&amp;gt;K: pagina ausente, genera fallo de pagina
    K-&amp;gt;&amp;gt;D: solicita la pagina faltante
    D--&amp;gt;&amp;gt;K: devuelve el contenido de la pagina
    K--&amp;gt;&amp;gt;P: actualiza la tabla y reanuda
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Ejemplos prácticos y cómo empezar
&lt;/h2&gt;

&lt;p&gt;Para probar esto en vivo necesitás una máquina Linux con &lt;code&gt;gcc&lt;/code&gt; instalado (&lt;code&gt;sudo apt install build-essential&lt;/code&gt;) y el paquete &lt;code&gt;time&lt;/code&gt; de GNU para medir fallos de página (&lt;code&gt;sudo apt install time&lt;/code&gt;), distinto del builtin de bash.&lt;/p&gt;

&lt;p&gt;Primero, un vistazo general con &lt;code&gt;free&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ free -h
               total        used        free      shared  buff/cache   available
Mem:            15Gi       4.2Gi       1.1Gi       412Mi        10Gi        10Gi
Swap:          2.0Gi          0B       2.0Gi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La columna &lt;code&gt;available&lt;/code&gt; es la que importa: es cuánta memoria el kernel puede entregar a un proceso nuevo sin empezar a usar swap. Con &lt;code&gt;vmstat&lt;/code&gt; se ve el movimiento en tiempo real:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ vmstat 1 3
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0      0 1123456  98234 9876543    0    0     3    12  410  620  8  2 89  1  0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Las columnas &lt;code&gt;si&lt;/code&gt; y &lt;code&gt;so&lt;/code&gt; (swap in / swap out) en cero son buena señal: el sistema no está intercambiando páginas con el disco. Ahora, un programa que fuerza fallos de página a propósito:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include 
#include 
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 100 MB&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;Un&lt;/span&gt; &lt;span class="n"&gt;TLB&lt;/span&gt; &lt;span class="n"&gt;miss&lt;/span&gt; &lt;span class="n"&gt;puede&lt;/span&gt; &lt;span class="n"&gt;costar&lt;/span&gt; &lt;span class="n"&gt;cientos&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;ciclos&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;reloj&lt;/span&gt; &lt;span class="n"&gt;frente&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;los&lt;/span&gt; &lt;span class="n"&gt;pocos&lt;/span&gt; &lt;span class="n"&gt;que&lt;/span&gt; &lt;span class="n"&gt;toma&lt;/span&gt; &lt;span class="n"&gt;un&lt;/span&gt; &lt;span class="n"&gt;TLB&lt;/span&gt; &lt;span class="n"&gt;hit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="cp"&gt;## Casos de uso reales
&lt;/span&gt;
&lt;span class="n"&gt;Los&lt;/span&gt; &lt;span class="n"&gt;contenedores&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Docker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;containerd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;crean&lt;/span&gt; &lt;span class="n"&gt;una&lt;/span&gt; &lt;span class="n"&gt;copia&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="err"&gt;í&lt;/span&gt;&lt;span class="n"&gt;sica&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;la&lt;/span&gt; &lt;span class="n"&gt;RAM&lt;/span&gt; &lt;span class="n"&gt;del&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;usan&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;cgroups&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt; &lt;span class="n"&gt;para&lt;/span&gt; &lt;span class="n"&gt;poner&lt;/span&gt; &lt;span class="n"&gt;un&lt;/span&gt; &lt;span class="n"&gt;tope&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;cu&lt;/span&gt;&lt;span class="err"&gt;á&lt;/span&gt;&lt;span class="n"&gt;ntas&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="err"&gt;á&lt;/span&gt;&lt;span class="n"&gt;ginas&lt;/span&gt; &lt;span class="n"&gt;puede&lt;/span&gt; &lt;span class="n"&gt;retener&lt;/span&gt; &lt;span class="n"&gt;un&lt;/span&gt; &lt;span class="n"&gt;grupo&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;procesos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mientras&lt;/span&gt; &lt;span class="n"&gt;el&lt;/span&gt; &lt;span class="n"&gt;espacio&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;direcciones&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;cada&lt;/span&gt; &lt;span class="n"&gt;proceso&lt;/span&gt; &lt;span class="n"&gt;sigue&lt;/span&gt; &lt;span class="n"&gt;siendo&lt;/span&gt; &lt;span class="n"&gt;gestionado&lt;/span&gt; &lt;span class="n"&gt;por&lt;/span&gt; &lt;span class="n"&gt;el&lt;/span&gt; &lt;span class="n"&gt;kernel&lt;/span&gt; &lt;span class="n"&gt;compartido&lt;/span&gt; &lt;span class="n"&gt;del&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;Las&lt;/span&gt; &lt;span class="n"&gt;bases&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;datos&lt;/span&gt; &lt;span class="n"&gt;como&lt;/span&gt; &lt;span class="n"&gt;PostgreSQL&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="n"&gt;SQLite&lt;/span&gt; &lt;span class="n"&gt;usan&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;mmap&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt; &lt;span class="n"&gt;para&lt;/span&gt; &lt;span class="n"&gt;mapear&lt;/span&gt; &lt;span class="n"&gt;archivos&lt;/span&gt; &lt;span class="n"&gt;completos&lt;/span&gt; &lt;span class="n"&gt;al&lt;/span&gt; &lt;span class="n"&gt;espacio&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;direcciones&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="n"&gt;del&lt;/span&gt; &lt;span class="n"&gt;proceso&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dejando&lt;/span&gt; &lt;span class="n"&gt;que&lt;/span&gt; &lt;span class="n"&gt;el&lt;/span&gt; &lt;span class="n"&gt;propio&lt;/span&gt; &lt;span class="n"&gt;mecanismo&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;paginaci&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;del&lt;/span&gt; &lt;span class="n"&gt;sistema&lt;/span&gt; &lt;span class="n"&gt;operativo&lt;/span&gt; &lt;span class="n"&gt;decida&lt;/span&gt; &lt;span class="n"&gt;qu&lt;/span&gt;&lt;span class="err"&gt;é&lt;/span&gt; &lt;span class="n"&gt;bloques&lt;/span&gt; &lt;span class="n"&gt;del&lt;/span&gt; &lt;span class="n"&gt;archivo&lt;/span&gt; &lt;span class="n"&gt;mantener&lt;/span&gt; &lt;span class="n"&gt;en&lt;/span&gt; &lt;span class="n"&gt;RAM&lt;/span&gt; &lt;span class="n"&gt;en&lt;/span&gt; &lt;span class="n"&gt;cada&lt;/span&gt; &lt;span class="n"&gt;momento&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;en&lt;/span&gt; &lt;span class="n"&gt;lugar&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;reinventar&lt;/span&gt; &lt;span class="n"&gt;ese&lt;/span&gt; &lt;span class="n"&gt;cacheo&lt;/span&gt; &lt;span class="n"&gt;en&lt;/span&gt; &lt;span class="n"&gt;la&lt;/span&gt; &lt;span class="n"&gt;aplicaci&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;En&lt;/span&gt; &lt;span class="n"&gt;la&lt;/span&gt; &lt;span class="n"&gt;nube&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instancias&lt;/span&gt; &lt;span class="n"&gt;peque&lt;/span&gt;&lt;span class="err"&gt;ñ&lt;/span&gt;&lt;span class="n"&gt;as&lt;/span&gt; &lt;span class="n"&gt;con&lt;/span&gt; &lt;span class="n"&gt;poca&lt;/span&gt; &lt;span class="n"&gt;RAM&lt;/span&gt; &lt;span class="n"&gt;suelen&lt;/span&gt; &lt;span class="n"&gt;usar&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;zram&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;swap&lt;/span&gt; &lt;span class="n"&gt;comprimido&lt;/span&gt; &lt;span class="n"&gt;en&lt;/span&gt; &lt;span class="n"&gt;memoria&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;en&lt;/span&gt; &lt;span class="n"&gt;lugar&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;swap&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;disco&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;porque&lt;/span&gt; &lt;span class="n"&gt;comprimir&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="n"&gt;descomprimir&lt;/span&gt; &lt;span class="n"&gt;en&lt;/span&gt; &lt;span class="n"&gt;CPU&lt;/span&gt; &lt;span class="n"&gt;resulta&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="err"&gt;á&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="err"&gt;á&lt;/span&gt;&lt;span class="n"&gt;pido&lt;/span&gt; &lt;span class="n"&gt;que&lt;/span&gt; &lt;span class="n"&gt;esperar&lt;/span&gt; &lt;span class="n"&gt;una&lt;/span&gt; &lt;span class="n"&gt;lectura&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;un&lt;/span&gt; &lt;span class="n"&gt;disco&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;red&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="cp"&gt;## Errores comunes y buenas prácticas
&lt;/span&gt;
&lt;span class="n"&gt;Un&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;frecuente&lt;/span&gt; &lt;span class="n"&gt;es&lt;/span&gt; &lt;span class="n"&gt;confundir&lt;/span&gt; &lt;span class="n"&gt;memoria&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="n"&gt;con&lt;/span&gt; &lt;span class="n"&gt;swap&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;el&lt;/span&gt; &lt;span class="n"&gt;swap&lt;/span&gt; &lt;span class="n"&gt;es&lt;/span&gt; &lt;span class="n"&gt;solo&lt;/span&gt; &lt;span class="n"&gt;uno&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;los&lt;/span&gt; &lt;span class="n"&gt;destinos&lt;/span&gt; &lt;span class="n"&gt;posibles&lt;/span&gt; &lt;span class="n"&gt;para&lt;/span&gt; &lt;span class="n"&gt;una&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="err"&gt;á&lt;/span&gt;&lt;span class="n"&gt;gina&lt;/span&gt; &lt;span class="n"&gt;que&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;cabe&lt;/span&gt; &lt;span class="n"&gt;en&lt;/span&gt; &lt;span class="n"&gt;RAM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pero&lt;/span&gt; &lt;span class="n"&gt;el&lt;/span&gt; &lt;span class="n"&gt;mecanismo&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;paginaci&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;existe&lt;/span&gt; &lt;span class="n"&gt;aunque&lt;/span&gt; &lt;span class="n"&gt;el&lt;/span&gt; &lt;span class="n"&gt;swap&lt;/span&gt; &lt;span class="n"&gt;est&lt;/span&gt;&lt;span class="err"&gt;é&lt;/span&gt; &lt;span class="n"&gt;desactivado&lt;/span&gt; &lt;span class="n"&gt;por&lt;/span&gt; &lt;span class="n"&gt;completo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;Otro&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;es&lt;/span&gt; &lt;span class="n"&gt;asumir&lt;/span&gt; &lt;span class="n"&gt;que&lt;/span&gt; &lt;span class="n"&gt;reservar&lt;/span&gt; &lt;span class="n"&gt;memoria&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;un&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;malloc&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt; &lt;span class="n"&gt;grande&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;consume&lt;/span&gt; &lt;span class="n"&gt;RAM&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;inmediato&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;En&lt;/span&gt; &lt;span class="n"&gt;Linux&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;es&lt;/span&gt; &lt;span class="n"&gt;as&lt;/span&gt;&lt;span class="err"&gt;í&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;el&lt;/span&gt; &lt;span class="n"&gt;consumo&lt;/span&gt; &lt;span class="n"&gt;real&lt;/span&gt; &lt;span class="n"&gt;aparece&lt;/span&gt; &lt;span class="n"&gt;reci&lt;/span&gt;&lt;span class="err"&gt;é&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;cuando&lt;/span&gt; &lt;span class="n"&gt;se&lt;/span&gt; &lt;span class="n"&gt;escribe&lt;/span&gt; &lt;span class="n"&gt;en&lt;/span&gt; &lt;span class="n"&gt;esas&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="err"&gt;á&lt;/span&gt;&lt;span class="n"&gt;ginas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;por&lt;/span&gt; &lt;span class="n"&gt;eso&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;VmSize&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;VmRSS&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt; &lt;span class="n"&gt;en&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;proc&lt;/span&gt;&lt;span class="o"&gt;/&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;/&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt; &lt;span class="n"&gt;pueden&lt;/span&gt; &lt;span class="n"&gt;diferir&lt;/span&gt; &lt;span class="n"&gt;en&lt;/span&gt; &lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;rdenes&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;magnitud&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="err"&gt;💡&lt;/span&gt; &lt;span class="n"&gt;Tip&lt;/span&gt;&lt;span class="o"&gt;:**&lt;/span&gt; &lt;span class="n"&gt;si&lt;/span&gt; &lt;span class="n"&gt;tu&lt;/span&gt; &lt;span class="n"&gt;programa&lt;/span&gt; &lt;span class="n"&gt;tiene&lt;/span&gt; &lt;span class="n"&gt;patrones&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;acceso&lt;/span&gt; &lt;span class="n"&gt;muy&lt;/span&gt; &lt;span class="n"&gt;dispersos&lt;/span&gt; &lt;span class="n"&gt;en&lt;/span&gt; &lt;span class="n"&gt;memoria&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="n"&gt;te&lt;/span&gt; &lt;span class="n"&gt;preocupa&lt;/span&gt; &lt;span class="n"&gt;la&lt;/span&gt; &lt;span class="n"&gt;latencia&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;med&lt;/span&gt;&lt;span class="err"&gt;í&lt;/span&gt; &lt;span class="n"&gt;primero&lt;/span&gt; &lt;span class="n"&gt;con&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;perf&lt;/span&gt; &lt;span class="n"&gt;stat&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;dTLB&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;misses&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt; &lt;span class="n"&gt;antes&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;asumir&lt;/span&gt; &lt;span class="n"&gt;que&lt;/span&gt; &lt;span class="n"&gt;el&lt;/span&gt; &lt;span class="n"&gt;cuello&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;botella&lt;/span&gt; &lt;span class="n"&gt;est&lt;/span&gt;&lt;span class="err"&gt;á&lt;/span&gt; &lt;span class="n"&gt;en&lt;/span&gt; &lt;span class="n"&gt;el&lt;/span&gt; &lt;span class="n"&gt;algoritmo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="err"&gt;⚠️&lt;/span&gt; &lt;span class="n"&gt;Ojo&lt;/span&gt;&lt;span class="o"&gt;:**&lt;/span&gt; &lt;span class="n"&gt;el&lt;/span&gt; &lt;span class="n"&gt;overcommit&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;Linux&lt;/span&gt; &lt;span class="n"&gt;permite&lt;/span&gt; &lt;span class="n"&gt;reservar&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="err"&gt;á&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;memoria&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;la&lt;/span&gt; &lt;span class="n"&gt;que&lt;/span&gt; &lt;span class="n"&gt;existe&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="err"&gt;í&lt;/span&gt;&lt;span class="n"&gt;sicamente&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;si&lt;/span&gt; &lt;span class="n"&gt;varios&lt;/span&gt; &lt;span class="n"&gt;procesos&lt;/span&gt; &lt;span class="n"&gt;la&lt;/span&gt; &lt;span class="n"&gt;reclaman&lt;/span&gt; &lt;span class="n"&gt;toda&lt;/span&gt; &lt;span class="n"&gt;al&lt;/span&gt; &lt;span class="n"&gt;mismo&lt;/span&gt; &lt;span class="n"&gt;tiempo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;el&lt;/span&gt; &lt;span class="n"&gt;OOM&lt;/span&gt; &lt;span class="n"&gt;killer&lt;/span&gt; &lt;span class="n"&gt;empieza&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;matar&lt;/span&gt; &lt;span class="n"&gt;procesos&lt;/span&gt; &lt;span class="n"&gt;sin&lt;/span&gt; &lt;span class="n"&gt;previo&lt;/span&gt; &lt;span class="n"&gt;aviso&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="cp"&gt;## Comparativa con alternativas de gestión de memoria
&lt;/span&gt;&lt;span class="n"&gt;EstrategiaCu&lt;/span&gt;&lt;span class="err"&gt;á&lt;/span&gt;&lt;span class="n"&gt;ndo&lt;/span&gt; &lt;span class="n"&gt;se&lt;/span&gt; &lt;span class="n"&gt;usaVentajaLimitaci&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;nPaginaci&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;por&lt;/span&gt; &lt;span class="n"&gt;demandaLinux&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Windows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;macOS&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;prop&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;sito&lt;/span&gt; &lt;span class="n"&gt;generalSolo&lt;/span&gt; &lt;span class="n"&gt;carga&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="n"&gt;que&lt;/span&gt; &lt;span class="n"&gt;se&lt;/span&gt; &lt;span class="n"&gt;usa&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;permite&lt;/span&gt; &lt;span class="n"&gt;overcommitThrashing&lt;/span&gt; &lt;span class="n"&gt;si&lt;/span&gt; &lt;span class="n"&gt;la&lt;/span&gt; &lt;span class="n"&gt;RAM&lt;/span&gt; &lt;span class="n"&gt;se&lt;/span&gt; &lt;span class="n"&gt;queda&lt;/span&gt; &lt;span class="n"&gt;cortaSegmentaci&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;nSistemas&lt;/span&gt; &lt;span class="n"&gt;x86&lt;/span&gt; &lt;span class="n"&gt;heredados&lt;/span&gt; &lt;span class="n"&gt;en&lt;/span&gt; &lt;span class="n"&gt;modo&lt;/span&gt; &lt;span class="n"&gt;real&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;protegidoMapea&lt;/span&gt; &lt;span class="n"&gt;unidades&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;gicas&lt;/span&gt; &lt;span class="n"&gt;completas&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;digo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;datos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pila&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;Fragmentaci&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;externa&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;casi&lt;/span&gt; &lt;span class="n"&gt;abandonadaMemoria&lt;/span&gt; &lt;span class="n"&gt;plana&lt;/span&gt; &lt;span class="n"&gt;sin&lt;/span&gt; &lt;span class="n"&gt;paginarMicrocontroladores&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="n"&gt;RTOS&lt;/span&gt; &lt;span class="n"&gt;embebidosSin&lt;/span&gt; &lt;span class="n"&gt;overhead&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;traducci&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;latencia&lt;/span&gt; &lt;span class="n"&gt;predecibleSin&lt;/span&gt; &lt;span class="n"&gt;aislamiento&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;un&lt;/span&gt; &lt;span class="n"&gt;bug&lt;/span&gt; &lt;span class="n"&gt;corrompe&lt;/span&gt; &lt;span class="n"&gt;todoHuge&lt;/span&gt; &lt;span class="n"&gt;pages&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;THPBases&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;datos&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="n"&gt;VMs&lt;/span&gt; &lt;span class="n"&gt;con&lt;/span&gt; &lt;span class="n"&gt;heaps&lt;/span&gt; &lt;span class="n"&gt;grandesMenos&lt;/span&gt; &lt;span class="n"&gt;entradas&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;TLB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;menos&lt;/span&gt; &lt;span class="n"&gt;TLB&lt;/span&gt; &lt;span class="n"&gt;missesPuede&lt;/span&gt; &lt;span class="n"&gt;reservar&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="err"&gt;á&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;RAM&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;la&lt;/span&gt; &lt;span class="n"&gt;necesaria&lt;/span&gt;
&lt;span class="cp"&gt;## Profundizando: dentro del kernel
&lt;/span&gt;
&lt;span class="n"&gt;En&lt;/span&gt; &lt;span class="n"&gt;x86&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;la&lt;/span&gt; &lt;span class="n"&gt;tabla&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="err"&gt;á&lt;/span&gt;&lt;span class="n"&gt;ginas&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;es&lt;/span&gt; &lt;span class="n"&gt;una&lt;/span&gt; &lt;span class="n"&gt;sola&lt;/span&gt; &lt;span class="n"&gt;estructura&lt;/span&gt; &lt;span class="n"&gt;plana&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;es&lt;/span&gt; &lt;span class="n"&gt;una&lt;/span&gt; &lt;span class="n"&gt;jerarqu&lt;/span&gt;&lt;span class="err"&gt;í&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;hasta&lt;/span&gt; &lt;span class="n"&gt;cuatro&lt;/span&gt; &lt;span class="n"&gt;niveles&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PGD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PUD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PMD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PTE&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;donde&lt;/span&gt; &lt;span class="n"&gt;cada&lt;/span&gt; &lt;span class="n"&gt;nivel&lt;/span&gt; &lt;span class="n"&gt;reduce&lt;/span&gt; &lt;span class="n"&gt;el&lt;/span&gt; &lt;span class="n"&gt;espacio&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="err"&gt;ú&lt;/span&gt;&lt;span class="n"&gt;squeda&lt;/span&gt; &lt;span class="n"&gt;antes&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;llegar&lt;/span&gt; &lt;span class="n"&gt;al&lt;/span&gt; &lt;span class="n"&gt;marco&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="err"&gt;í&lt;/span&gt;&lt;span class="n"&gt;sico&lt;/span&gt; &lt;span class="n"&gt;final&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;El&lt;/span&gt; &lt;span class="n"&gt;registro&lt;/span&gt; &lt;span class="n"&gt;CR3&lt;/span&gt; &lt;span class="n"&gt;apunta&lt;/span&gt; &lt;span class="n"&gt;siempre&lt;/span&gt; &lt;span class="n"&gt;al&lt;/span&gt; &lt;span class="n"&gt;primer&lt;/span&gt; &lt;span class="n"&gt;nivel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;flowchart TD&lt;br&gt;
    A["CR3: tabla de nivel superior PGD"] --&amp;gt; B["PUD"]&lt;br&gt;
    B --&amp;gt; C["PMD"]&lt;br&gt;
    C --&amp;gt; D["PTE"]&lt;br&gt;
    D --&amp;gt; E["Marco de pagina fisico"]&lt;br&gt;
    subgraph "Traduccion x86-64 de 4 niveles"&lt;br&gt;
    A&lt;br&gt;
    B&lt;br&gt;
    C&lt;br&gt;
    D&lt;br&gt;
    end&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
En sistemas multinúcleo, cuando el kernel cambia una entrada de la tabla de páginas tiene que invalidar la entrada correspondiente en el TLB de cada núcleo, una operación llamada TLB shootdown. Es cara porque interrumpe a los otros núcleos, así que el kernel la agrupa en lotes cuando puede.

Las huge pages (de 2 MB o 1 GB en lugar de 4 KB) reducen cuántas entradas necesita el TLB para cubrir la misma cantidad de RAM, a costa de desperdiciar memoria si una página grande queda medio vacía. Para confirmar si las Transparent Huge Pages están activas en tu sistema:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;$ cat /sys/kernel/mm/transparent_hugepage/enabled&lt;br&gt;
[always] madvise never&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


El valor entre corchetes indica el modo activo; `always` entre corchetes significa que el kernel intenta usar huge pages de forma automática para cualquier asignación grande.

El otro mecanismo que vale la pena entender es copy-on-write: cuando un proceso hace `fork()`, el hijo no copia la RAM del padre, solo copia las tablas de páginas y las marca como solo lectura. La copia real de una página ocurre, página por página, solo si alguno de los dos la modifica después.

📖 Resumen en Telegram: [Ver resumen](https://telegra.ph/Memoria-virtual-qué-es-y-cómo-simula-más-RAM-de-la-que-hay-10-30)

Tu próximo paso: compilá el programa de ejemplo de este artículo, corré `/usr/bin/time -v` sobre él y compará los fallos de página menores que reporta contra el tamaño del buffer dividido entre 4 KB.

## Preguntas frecuentes

### ¿La memoria virtual hace más lenta la computadora?

No por sí misma. La memoria virtual agrega una traducción de direcciones, pero el TLB la vuelve casi gratuita en el caso común. La lentitud aparece cuando no hay páginas libres y el kernel empieza a intercambiar con el disco, un escenario llamado thrashing.

### ¿Qué diferencia hay entre paginación y memoria swap?

La paginación es el mecanismo de traducción de direcciones; el swap es solo un destino posible para páginas que no caben en RAM. Un sistema puede paginar sin tener nada de swap configurado: simplemente no podrá liberar páginas hacia el disco cuando falte memoria física.

### ¿Cómo veo cuánta memoria virtual usa un proceso en Linux?

Con `cat /proc/&amp;lt;pid&amp;gt;/status` y mirando el campo `VmSize` para la memoria reservada o `VmRSS` para la que realmente ocupa páginas físicas. La diferencia entre ambos suele ser enorme, porque reservar espacio de direcciones virtual no consume RAM hasta que se escribe en él.

### ¿Qué es un TLB miss y por qué importa?

Es cuando la MMU no encuentra la traducción en su caché y debe recorrer la tabla de páginas completa, algo que puede tardar cientos de ciclos de reloj. Programas con patrones de acceso muy dispersos en memoria sufren más TLB misses que los que acceden de forma secuencial.

### ¿Los sistemas embebidos usan paginación por demanda?

La mayoría no. Un microcontrolador con RTOS suele trabajar con memoria física plana porque su RAM es pequeña, fija y conocida de antemano, así que el overhead de traducir direcciones no se justifica. Linux embebido, por ejemplo en routers, sí mantiene paginación completa.

### ¿Qué pasa si se agota la memoria disponible en Linux?

Si el overcommit permitió reservar más de lo que existe y la demanda real supera la RAM y el swap disponibles, el kernel activa el OOM killer, que elige y mata procesos según una puntuación (`oom_score`) hasta liberar memoria.

## Referencias

- [docs.kernel.org](https://docs.kernel.org/admin-guide/mm/concepts.html): documentación oficial del kernel Linux sobre los conceptos de gestión de memoria.- [man7.org](https://man7.org/linux/man-pages/man5/proc.5.html): referencia completa de los campos de /proc/[pid]/status y /proc/[pid]/smaps.- [en.wikipedia.org](https://en.wikipedia.org/wiki/Virtual_memory): historia y fundamentos de la memoria virtual desde los sistemas de los años 60.- [pages.cs.wisc.edu](https://pages.cs.wisc.edu/~remzi/OSTEP/): Operating Systems Three Easy Pieces, capítulos de paginación y tablas multinivel.

📱 **¿Te gusta este contenido?** Únete a nuestro canal de Telegram [@programacion](https://t.me/programacion) donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Extensiones de código: qué revisar antes de instalar</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Fri, 30 Oct 2026 14:32:45 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/extensiones-de-codigo-que-revisar-antes-de-instalar-1eca</link>
      <guid>https://dev.to/lu1tr0n/extensiones-de-codigo-que-revisar-antes-de-instalar-1eca</guid>
      <description>&lt;p&gt;Kevin Beaumont, el investigador que rastreó WannaCry y publica como @GossiTheDog, escribió en &lt;a href="https://cyberplace.social/@GossiTheDog/117528831681803563" rel="noopener noreferrer"&gt;Mastodon&lt;/a&gt; que la extensión de Claude Code habría sido comprometida. Anthropic no confirmó el reporte y la publicación no aporta indicadores técnicos verificables.&lt;/p&gt;

&lt;p&gt;Da igual que esa denuncia puntual se confirme o no: el mismo patrón, código oficial que termina filtrando credenciales, explica por qué cada vez más equipos tratan cada extensión, plugin o paquete como código no confiable hasta probar lo contrario. Y ese patrón ya tiene un caso confirmado este año: LiteLLM 1.107.0 en PyPI.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Revisar permisos, red y dependencias antes de instalar detecta backdoors como el de LiteLLM 1.107.0 en PyPI.- Un postinstall script en npm o un hook de importación en pip puede exfiltrar credenciales sin mostrar ningún error.- La bandera --ignore-scripts de npm y pip-audit detectan o bloquean código de instalación sin revisar.- osv-scanner cruza tu lockfile contra la base pública de OSV.dev antes de que el ataque llegue a producción.- Una extensión marcada como oficial no garantiza ausencia de telemetría oculta ni de dependencias comprometidas.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Qué es auditar extensiones de código?
&lt;/h2&gt;

&lt;p&gt;Auditar extensiones de código es el proceso de revisar permisos, llamadas de red y dependencias de un plugin o paquete antes de instalarlo, aunque venga de un marketplace oficial. Busca detectar robo de credenciales, telemetría oculta o código inyectado antes de que se ejecute en tu máquina o en un pipeline de CI/CD.&lt;/p&gt;

&lt;p&gt;El término "oficial" genera una falsa sensación de seguridad. Un marketplace de extensiones, un registro de paquetes como npm o PyPI, o la cuenta verificada de un proyecto open source certifican la identidad de quien publica, no la ausencia de código malicioso en cada versión. La auditoría llena exactamente ese espacio: la distancia entre "lo publicó quien dice ser" y "el código que publicó es seguro".&lt;br&gt;
LiteLLM 1.107.0, publicado en PyPI, incluía un robacredenciales y una puerta trasera.&lt;/p&gt;
&lt;h2&gt;
  
  
  Por qué importa: de una denuncia en Mastodon a un backdoor confirmado en LiteLLM
&lt;/h2&gt;

&lt;p&gt;La publicación de Beaumont no incluye hashes ni un análisis técnico público. Es la afirmación de un investigador reconocido, no una auditoría publicada ni una confirmación de Anthropic. Tratarla como hecho consumado repetiría el mismo error que cualquier guía de seguridad critica: aceptar una fuente sin corroborarla.&lt;/p&gt;

&lt;p&gt;El riesgo real no depende de si esa denuncia puntual se confirma. Ya existe un caso documentado con el mismo patrón: &lt;strong&gt;LiteLLM&lt;/strong&gt;, el proxy open source para unificar APIs de modelos de lenguaje, publicó en PyPI la versión 1.107.0 con un robacredenciales y una puerta trasera incluidos en el paquete. Quien instaló esa versión con un simple &lt;code&gt;pip install litellm==1.107.0&lt;/code&gt; ejecutó ese código con los mismos permisos que su propia aplicación.&lt;/p&gt;

&lt;p&gt;La lección no es "no uses LiteLLM" ni "no confíes en Anthropic": es que ninguna plataforma (PyPI, npm, un marketplace de extensiones) revisa línea por línea cada publicación antes de distribuirla. El control de calidad recae, en la práctica, en quien instala.&lt;/p&gt;
&lt;h2&gt;
  
  
  Cómo funciona una extensión maliciosa por dentro
&lt;/h2&gt;

&lt;p&gt;La mayoría de los ataques por este canal no explotan una vulnerabilidad de memoria ni un exploit sofisticado. Abusan de un mecanismo legítimo que casi todos los gestores de paquetes ofrecen: ejecutar código automáticamente durante la instalación.&lt;/p&gt;
&lt;h3&gt;
  
  
  Scripts de instalación automática
&lt;/h3&gt;

&lt;p&gt;En npm, el campo &lt;code&gt;scripts.postinstall&lt;/code&gt; de un &lt;code&gt;package.json&lt;/code&gt; corre apenas termina de descargarse el paquete, sin que el usuario lo apruebe explícitamente. En pip, el equivalente clásico es un &lt;code&gt;setup.py&lt;/code&gt; con código a nivel de módulo, fuera de cualquier función, que Python ejecuta durante el build. Ambos mecanismos existen por razones legítimas, como compilar una dependencia nativa, pero son indistinguibles a simple vista de un script que exfiltra variables de entorno.&lt;/p&gt;
&lt;h3&gt;
  
  
  Telemetría no declarada
&lt;/h3&gt;

&lt;p&gt;Una extensión de editor (VS Code, JetBrains) puede declarar permisos amplios, como acceso a archivos o a red, que el marketplace aprueba porque son parte del modelo de negocio del propio editor. Nada impide que, además de la función anunciada, la extensión envíe eventos a un dominio de analítica propio sin romper ninguna regla formal del marketplace.&lt;/p&gt;
&lt;h3&gt;
  
  
  Dependencias transitivas comprometidas
&lt;/h3&gt;

&lt;p&gt;El paquete que instalás a propósito casi nunca es el problema. El problema suele estar dos o tres niveles abajo, en una dependencia de una dependencia que nadie en tu equipo revisó nunca. Un &lt;code&gt;npm ls --all&lt;/code&gt; en un proyecto mediano fácilmente devuelve varios cientos de paquetes transitivos.&lt;/p&gt;
&lt;h3&gt;
  
  
  Permisos amplios en extensiones de asistentes de código
&lt;/h3&gt;

&lt;p&gt;Las extensiones de asistentes de IA para programar, como Claude Code, GitHub Copilot o Cursor, son un caso particular porque su función misma requiere acceso amplio: leer el repositorio completo, ejecutar comandos de shell y, en muchos flujos, leer variables de entorno donde suelen vivir tokens de API y credenciales de nube. Ese nivel de acceso no es un error de diseño, es necesario para que la herramienta funcione, pero convierte a cualquier extensión de este tipo en un objetivo de alto valor: comprometerla una sola vez da acceso a todo lo que el desarrollador podría tocar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sequenceDiagram
    participant Dev as Desarrollador
    participant Reg as Registro de paquetes
    participant Script as Script de instalación
    participant C2 as Servidor del atacante
    Dev-&amp;gt;&amp;gt;Reg: pip install litellm 1.107.0
    Reg--&amp;gt;&amp;gt;Dev: entrega el paquete
    Dev-&amp;gt;&amp;gt;Script: ejecuta instalación
    Script-&amp;gt;&amp;gt;C2: envía variables de entorno
    Note over Dev,C2: la exfiltración ocurre antes del primer uso del paquete
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Ojo:&lt;/strong&gt; el flag &lt;code&gt;--ignore-scripts&lt;/code&gt; de npm bloquea los scripts de instalación de TODAS las dependencias, no solo las sospechosas. Puede romper paquetes legítimos que compilan binarios nativos durante el install.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Cómo empezar: auditar una extensión paso a paso
&lt;/h2&gt;

&lt;p&gt;Esta checklist asume que ya tenés Node.js y npm instalados, cualquier versión reciente de Node incluye npm. Si trabajás en Python, los comandos equivalentes usan &lt;code&gt;pip&lt;/code&gt; y se indican entre paréntesis.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checklist para auditar extensiones de código antes de instalar
&lt;/h3&gt;

&lt;p&gt;Antes de correr &lt;code&gt;npm install&lt;/code&gt; o agregar una extensión desde un marketplace, cuatro pasos reducen la mayoría del riesgo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Leer el manifiesto sin instalar.&lt;/strong&gt; &lt;code&gt;npm view express scripts --json&lt;/code&gt; muestra los scripts declarados sin descargar ni ejecutar nada. Salida esperada para un paquete sin scripts de instalación: &lt;code&gt;{}&lt;/code&gt;. Si aparece una clave &lt;code&gt;postinstall&lt;/code&gt; o &lt;code&gt;preinstall&lt;/code&gt;, revisá ese script antes de seguir.- &lt;strong&gt;Revisar el árbol de dependencias.&lt;/strong&gt; &lt;code&gt;npm ls --all&lt;/code&gt; (o &lt;code&gt;pip show -f &amp;lt;paquete&amp;gt;&lt;/code&gt; en Python) lista cada dependencia transitiva. Un paquete chico con cientos de líneas de dependencias es una señal de que auditarlo a mano no es viable y conviene apoyarse en una herramienta automatizada.- &lt;strong&gt;Escanear contra vulnerabilidades conocidas.&lt;/strong&gt; &lt;a href="https://github.com/google/osv-scanner" rel="noopener noreferrer"&gt;osv-scanner&lt;/a&gt;, de Google, cruza tu &lt;code&gt;package-lock.json&lt;/code&gt; o &lt;code&gt;requirements.txt&lt;/code&gt; contra la base pública de OSV.dev: &lt;code&gt;osv-scanner scan source --lockfile=package-lock.json&lt;/code&gt;. Si no hay coincidencias, el comando termina sin listar vulnerabilidades y devuelve código de salida 0.- &lt;strong&gt;Observar el tráfico de red en una instalación aislada.&lt;/strong&gt; Corré la instalación dentro de un contenedor o una VM descartable y capturá las conexiones salientes con &lt;code&gt;strace -f -e trace=network -o salida.log npm install&lt;/code&gt;. Un paquete que solo contacta &lt;code&gt;registry.npmjs.org&lt;/code&gt; es lo esperado; una conexión a un dominio desconocido en ese log es la señal de alarma que justifica no seguir.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Para extensiones de editor (VS Code, JetBrains)
&lt;/h3&gt;

&lt;p&gt;El mismo principio aplica a extensiones de editor, con una diferencia práctica: la mayoría no expone un manifiesto tan legible como &lt;code&gt;package.json&lt;/code&gt;. &lt;code&gt;code --list-extensions --show-versions&lt;/code&gt; lista lo que ya tenés instalado; antes de agregar una nueva, revisar su página en el marketplace por los permisos declarados y, sobre todo, por quién la publica (la cuenta del propio proyecto frente a un fork de un tercero) evita la mayoría de los casos de suplantación.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;flowchart&lt;/span&gt; &lt;span class="nv"&gt;TD&lt;/span&gt;
    &lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Extensión nueva a instalar"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Publicador verificado?"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"No"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;X&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Rechazar"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"Si"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Scripts de instalación declarados?"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"Si"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Revisar el script línea por línea"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"No"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;E&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Dependencias transitivas excesivas?"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;D&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;E&lt;/span&gt;
    &lt;span class="nv"&gt;E&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"Si"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Escanear con osv-scanner"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;E&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"No"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;G&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Instalar y monitorear tráfico de red"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;F&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;G&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Corea del Norte comprometió 1.700 paquetes en npm, PyPI, Go y Rust con malware, según reportes de seguridad de 2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué hacer si ya instalaste una extensión sospechosa
&lt;/h2&gt;

&lt;p&gt;Si la auditoría llega tarde y la extensión ya está instalada y en uso, el orden de las acciones importa más que la velocidad de cada una.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rotar credenciales primero, investigar después.&lt;/strong&gt; Cualquier token de API, clave de nube o contraseña accesible desde el entorno donde corrió la extensión se considera comprometido. Rotarlas no espera a confirmar si hubo exfiltración real.- &lt;strong&gt;Revisar logs de red salientes.&lt;/strong&gt; Si tenés un firewall de salida o un proxy corporativo, buscá conexiones hacia dominios que no correspondan a los registros oficiales del paquete (registry.npmjs.org, pypi.org, el dominio propio del proyecto) en la ventana en que la extensión estuvo activa.- &lt;strong&gt;Buscar persistencia.&lt;/strong&gt; Un backdoor que solo roba credenciales una vez es grave pero acotado; uno que instala una tarea programada, un hook de git o un servicio que sobrevive a la desinstalación es un incidente de otra escala. Revisar &lt;code&gt;crontab -l&lt;/code&gt;, hooks en &lt;code&gt;.git/hooks/&lt;/code&gt; y servicios nuevos del sistema cubre los vectores de persistencia más comunes.- &lt;strong&gt;Documentar la cadena completa.&lt;/strong&gt; Versión exacta instalada, fecha y qué credenciales estaban accesibles en ese momento. Esa información es la que necesita cualquier reporte posterior al equipo de seguridad o al propio proyecto afectado.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;flowchart&lt;/span&gt; &lt;span class="nv"&gt;LR&lt;/span&gt;
    &lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Extensión sospechosa detectada"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Rotar credenciales"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Revisar logs de red"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Buscar persistencia"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;D&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;E&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Documentar el incidente"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;📌 Nota:&lt;/strong&gt; una extensión de IA para programar suele pedir acceso de lectura y escritura a todo el repositorio y a las variables de entorno del shell donde corre. Ese nivel de acceso es exactamente lo que vuelve atractivo a este vector de ataque.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Casos de uso reales: más allá de LiteLLM
&lt;/h2&gt;

&lt;p&gt;El patrón no es exclusivo de un ecosistema. En 2026, investigadores documentaron una campaña atribuida a actores de Corea del Norte que infectó más de 1.700 paquetes distribuidos entre npm, PyPI, Go y Rust con malware, aprovechando el mismo mecanismo: un script de instalación o un hook de importación que corre sin revisión humana. La escala cambia, el vector es el mismo.&lt;/p&gt;

&lt;p&gt;El caso de Claude Code que denuncia Beaumont, confirmado o no, encaja en esa misma categoría de riesgo: una extensión con acceso directo al entorno de desarrollo (variables de entorno, tokens de API, archivos del proyecto) es un objetivo de alto valor precisamente porque corre con los mismos permisos que el desarrollador que la instaló.&lt;/p&gt;

&lt;p&gt;Para equipos en LATAM que integran agentes de IA en su flujo de trabajo sobre repositorios con información de clientes, el costo de una credencial filtrada no es solo técnico: puede implicar una notificación obligatoria a usuarios según la legislación local de protección de datos. La auditoría previa, en ese contexto, es tanto parte del cumplimiento como de la seguridad.&lt;/p&gt;

&lt;h2&gt;
  
  
  Errores comunes y buenas prácticas
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Confiar en el badge de "verificado" sin revisar el contenido.&lt;/strong&gt; Un marketplace certifica identidad del publicador, no la ausencia de código malicioso en cada actualización.- &lt;strong&gt;No fijar versiones exactas.&lt;/strong&gt; Un rango como &lt;code&gt;^1.107.0&lt;/code&gt; en vez de &lt;code&gt;1.107.0&lt;/code&gt; exacto en el lockfile permite que una actualización comprometida se instale sola en el próximo &lt;code&gt;npm install&lt;/code&gt;.- &lt;strong&gt;Ignorar los scripts de instalación por costumbre.&lt;/strong&gt; La mayoría de los desarrolladores nunca leyó un &lt;code&gt;postinstall&lt;/code&gt; de una dependencia que usa todos los días.- &lt;strong&gt;No monitorear tráfico de salida.&lt;/strong&gt; Sin un registro de qué dominios contacta una herramienta, una exfiltración de credenciales puede pasar meses sin detectarse.- &lt;strong&gt;Auditar una sola vez y olvidarse.&lt;/strong&gt; Una extensión limpia hoy puede recibir una actualización comprometida la semana próxima; la auditoría es un proceso continuo, no un trámite único.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Comparativa de herramientas de auditoría
&lt;/h2&gt;

&lt;p&gt;HerramientaQué detectaCuándo usarlaLimitaciónnpm auditVulnerabilidades conocidas en dependencias de Node.jsAntes de cada release, integrado en CISolo cubre el ecosistema npm y vulnerabilidades ya reportadaspip-auditVulnerabilidades conocidas en paquetes de PythonEn el pipeline de CI de proyectos PythonNo analiza comportamiento en tiempo de ejecuciónosv-scannerCruza lockfiles contra la base OSV.dev multi-ecosistemaAuditorías periódicas en repos con varios lenguajesDepende de que la vulnerabilidad ya esté reportada en OSVSandbox de red (strace, mitmproxy)Conexiones salientes no documentadas durante la instalaciónAntes de aprobar una dependencia nueva, una sola vezRequiere montar el aislamiento manualmente, no es automático&lt;/p&gt;

&lt;h2&gt;
  
  
  Profundizando: procedencia, SBOM y firmas criptográficas
&lt;/h2&gt;

&lt;p&gt;Para equipos que gestionan cientos de dependencias, revisar manifiestos a mano no escala. La industria converge en varios mecanismos complementarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  Software Bill of Materials (SBOM)
&lt;/h3&gt;

&lt;p&gt;Un SBOM es un inventario formal, en formato SPDX o CycloneDX, de cada componente que compone un artefacto de software, con su versión exacta y su licencia. Herramientas como &lt;code&gt;syft&lt;/code&gt; generan un SBOM a partir de una imagen de contenedor o un repositorio, lo que permite responder en segundos a "¿usamos en algún lado la versión comprometida de este paquete?" en vez de revisar proyecto por proyecto.&lt;/p&gt;

&lt;h3&gt;
  
  
  Procedencia verificable con SLSA
&lt;/h3&gt;

&lt;p&gt;El marco &lt;a href="https://slsa.dev" rel="noopener noreferrer"&gt;SLSA&lt;/a&gt; (Supply-chain Levels for Software Artifacts) define niveles de garantía sobre cómo se construyó un artefacto, desde "el build corrió en algún lado" hasta "el build corrió en un sistema aislado, con el código fuente y los pasos de build firmados criptográficamente y verificables por un tercero". Un paquete con procedencia SLSA de nivel alto reduce, aunque no elimina, la posibilidad de que alguien inserte código entre el repositorio y el registro de distribución.&lt;/p&gt;

&lt;h3&gt;
  
  
  Firmas con Sigstore
&lt;/h3&gt;

&lt;p&gt;Sigstore permite firmar un artefacto sin gestionar una clave privada permanente: usa certificados de corta duración ligados a una identidad, como una cuenta de GitHub, y registra la firma en un log público e inmutable. Verificar esa firma contra una imagen confirma esa cadena. Sin esto, comprobar que un binario publicado corresponde exactamente al código fuente público depende de la buena fe del mantenedor.&lt;/p&gt;

&lt;h3&gt;
  
  
  Builds reproducibles
&lt;/h3&gt;

&lt;p&gt;Un build reproducible permite que cualquiera, compilando el mismo código fuente con las mismas herramientas, obtenga exactamente el mismo binario, byte a byte, que el que publicó el mantenedor. Si dos partes independientes reproducen el mismo resultado, la posibilidad de que el binario publicado contenga algo que no está en el código fuente público baja drásticamente. Debian y el proyecto Tor son dos de los ejemplos más antiguos de este enfoque aplicado en producción.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: &lt;a href="https://telegra.ph/Extensiones-de-c%C3%B3digo-qu%C3%A9-revisar-antes-de-instalar-10-30" rel="noopener noreferrer"&gt;Ver resumen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tu próximo paso: correr &lt;code&gt;npm view &amp;lt;paquete&amp;gt; scripts --json&lt;/code&gt; sobre una dependencia que ya uses todos los días y confirmar que no declara ningún &lt;code&gt;postinstall&lt;/code&gt; que no hayas revisado antes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Cómo hacer control de dependencias de software sin pagar herramientas comerciales?
&lt;/h3&gt;

&lt;p&gt;Con herramientas gratuitas alcanza para la mayoría de los casos: &lt;code&gt;npm audit&lt;/code&gt; y &lt;code&gt;pip-audit&lt;/code&gt; son gratuitos, osv-scanner es open source, y revisar manifiestos con &lt;code&gt;npm view&lt;/code&gt; no cuesta nada. El gasto de herramientas comerciales como Socket.dev o Snyk está en el monitoreo continuo automatizado, no en la capacidad básica de detección.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿La denuncia de Kevin Beaumont sobre Claude Code se confirmó?
&lt;/h3&gt;

&lt;p&gt;No, al momento de escribir este artículo Anthropic no publicó una confirmación ni un desmentido público de la publicación en Mastodon. Tratala como una alerta a seguir, no como un hecho establecido.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué diferencia hay entre un backdoor y telemetría excesiva en una extensión?
&lt;/h3&gt;

&lt;p&gt;Un backdoor ejecuta código con la intención explícita de dar acceso no autorizado o robar datos, como el caso de LiteLLM. La telemetría excesiva suele estar declarada en algún lugar de los términos de uso, aunque sea poco visible; sigue siendo un problema de privacidad, pero no es, técnicamente, un ataque.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Alcanza con revisar el código fuente en GitHub antes de instalar un paquete?
&lt;/h3&gt;

&lt;p&gt;No siempre. El código publicado en el registro (npm, PyPI) no siempre coincide con el del repositorio público; sin procedencia verificable, como SLSA o Sigstore, no hay garantía automática de que ambos sean idénticos. Por eso conviene auditar el paquete que efectivamente se instala, no solo el repositorio.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Con qué frecuencia hay que repetir la verificación de paquetes de terceros?
&lt;/h3&gt;

&lt;p&gt;Como mínimo, en cada actualización de versión mayor o menor de una dependencia crítica, y de forma automatizada, con osv-scanner u otra herramienta similar, en cada build de CI. Una revisión hecha una sola vez pierde valor en cuanto aparece la próxima actualización.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://cyberplace.social/@GossiTheDog/117528831681803563" rel="noopener noreferrer"&gt;Mastodon (@GossiTheDog)&lt;/a&gt;: la publicación de Kevin Beaumont que denuncia, sin confirmación pública, el presunto compromiso de la extensión de Claude Code.- &lt;a href="https://github.com/BerriAI/litellm" rel="noopener noreferrer"&gt;Repositorio de LiteLLM en GitHub&lt;/a&gt;: proyecto open source afectado por el paquete comprometido publicado en PyPI.- &lt;a href="https://github.com/google/osv-scanner" rel="noopener noreferrer"&gt;osv-scanner&lt;/a&gt;: escáner de Google que cruza lockfiles contra la base de datos pública de vulnerabilidades OSV.dev.- &lt;a href="https://docs.npmjs.com/cli/v10/using-npm/scripts" rel="noopener noreferrer"&gt;Documentación oficial de npm sobre scripts&lt;/a&gt;: referencia de cómo y cuándo corren los scripts de instalación como postinstall.- &lt;a href="https://slsa.dev" rel="noopener noreferrer"&gt;SLSA (Supply-chain Levels for Software Artifacts)&lt;/a&gt;: marco de niveles de procedencia verificable para artefactos de software.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>security</category>
      <category>cybersecurity</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
