La auditoría confirmó que el generador existía. Existía — y nunca se llamaba
Durante cinco años Coldcard tomó la aleatoriedad del generador equivocado. La revisión comprobaba que el código estuviera, no que se ejecutara.
Desde el 30 de julio se han vaciado unos 2000 BTC — cerca de 130 millones de dólares al precio actual — de carteras físicas Coldcard. Sin phishing, sin malware, sin portátiles robados. Estos dispositivos nunca se conectan a internet, y nadie los tocó. Los atacantes simplemente dedujeron las claves privadas.
Un solo barrido se llevó 70 millones en 41 minutos. Galaxy Research confirma 1596 BTC desde unas 7300 direcciones en tres oleadas, más catorce incidentes menores; con una cuarta oleada sospechada el total llega a unos 2055 BTC. El fabricante cuenta al menos quince atacantes independientes: una vez conocido el agujero, entraron todos.
Lo que sigue no es la crónica del robo, sino el análisis de por qué las revisiones no lo vieron. Porque no se les escapó por descuido, sino exactamente como están construidas las revisiones hoy.
Una directiva de preprocesador
En marzo de 2021 Coinkite migró la criptografía de Coldcard a libsecp256k1, la
misma biblioteca que usa Bitcoin Core. La decisión era sensata: la criptografía
propia es peor que la compartida. Lo que se rompió fue la integración.
La migración desvió en silencio la generación de la semilla desde el generador de números aleatorios por hardware hacia el respaldo por software de MicroPython — un algoritmo llamado Yasmarang que existe para dispositivos que no tienen chip de aleatoriedad. Coldcard sí tiene ese chip. Simplemente dejaron de preguntarle.
La causa cabe en un solo token. La guarda de compilación estaba escrita con
#ifndef, y esa directiva comprueba si un ajuste está definido, no si está
activado. Coinkite lo había definido como cero, es decir «apagado». Cero sigue
siendo un valor definido, así que la comprobación pasó y la compilación se completó.
Ambas versiones de la función tenían firmas idénticas, de modo que a ojo humano
tampoco había nada roto.
El resultado: el espacio de búsqueda de la clave se desplomó de 128 bits a unos cuarenta en los modelos antiguos. Cuarenta bits se recorren por fuerza bruta sin conexión, sin una sola petición a la red. De ahí los 70 millones en 41 minutos.
Por qué nadie lo vio en cinco años
Coldcard pasó revisiones. Las revisiones confirmaban que el generador por hardware real estaba en el código y funcionaba correctamente. Y era cierto. Esto es textual del propio análisis de Coinkite:
El grueso de la aleatoriedad en la COLDCARD venía de un PRNG que yo no sabía que estuviera en la base de código. Al mismo tiempo el código TRNG que escribí con cuidado sí se usaba, pero por casualidad y solo para cosas menos importantes.
El generador correcto existía, era correcto e incluso se llamaba. Solo que no donde importaba.
Nick Percoco, director de seguridad de Kraken, formuló la brecha con precisión: se le pide al comprador que confíe en la implementación que hace el fabricante de la función más crítica del sistema, y no existe verificación independiente de que la ruta de entropía aprobada sea la que realmente se ejecuta.
No es una abstracción. En el resto de la industria esa comprobación es estándar: NIST SP 800-90B en Estados Unidos y BSI AIS-31 en Alemania especifican cómo se diseñan, prueban y validan los generadores físicos de números aleatorios. Las carteras físicas no tienen equivalente. Hay Common Criteria sobre elementos seguros, algunas certificaciones y auditorías pagadas por el propio fabricante, y ninguna obliga sistemáticamente a demostrar qué código se ejecuta de verdad en el dispositivo que tienes en la mano.
Ya escribimos sobre cómo preparar un contrato inteligente para una auditoría y sobre por qué «nos auditaron» y «no tenemos agujeros» son afirmaciones distintas. Coldcard es esa idea en su forma más pura: una auditoría puede ser rigurosa, minuciosa y aun así estar respondiendo a la pregunta equivocada.
«¿Existe el componente?» y «¿se ejecuta?» son dos preguntas distintas. La primera se responde leyendo código. La segunda solo observando el firmware compilado.
Los cuidadosos cayeron primero
La parte más incómoda apareció al revisar quién había perdido monedas antes de 2026.
Coldcard permite mezclar tu propia aleatoriedad con tiradas de un dado físico. El consejo es razonable y lleva años circulando. El problema es la aritmética: cada tirada de un dado de seis caras aporta unos 2,585 bits. Para llegar a los 128 bits que la propia Coinkite considera el mínimo hacen falta al menos 50 tiradas; para 256 bits, 99. El dispositivo no impone ese suelo: su documentación dice que no limita el número de tiradas, aunque avisa si aplicas demasiado pocas.
Avisa, y te deja pasar.
La investigadora de seguridad Taylor Monahan, que estudió las pérdidas anteriores de usuarios de Coldcard, señala que casi en todos los casos las víctimas eran quienes tiraban los dados. Un ritual hecho a medias dejaba una semilla con tan poca entropía que romperla era trivial — mucho antes de que se supiera que el firmware tenía un defecto.
El matiz es que hay dos caminos. En el flujo normal las tiradas se combinan por hash con la aleatoriedad del propio dispositivo, así que las tiradas de más solo añaden protección sobre el generador defectuoso. Pero Coldcard ofrece también una semilla solo de dados donde, según la descripción de Coinkite, la secuencia de tiradas se hashea directamente y el generador del dispositivo no interviene. Si eliges ese camino, tiras veinte veces y paras, toda la seguridad de la semilla descansa en esas veinte tiradas.
Una protección aplicada a medias resultó más peligrosa que ninguna. Y eso vale mucho más allá de las carteras: un mecanismo que avisa pero no detiene le pasa la aritmética al usuario, y el usuario no va a hacer la aritmética.
Qué cambió en 2026
Cinco años de pasar desapercibido era un precio que se podía pagar. Ya no, y los números lo demuestran.
Mientras ocurría este robo, dieciséis desarrolladores formaron un equipo rojo voluntario y apuntaron modelos de IA a carteras de bitcoin, bibliotecas criptográficas e infraestructura. En veinticuatro horas: 4962 hallazgos en 390 proyectos, de los cuales 85 críticos y 635 de severidad alta. Eso equivale a aproximadamente un fallo crítico por persona y hora, con un gasto del orden de diez mil dólares diarios en cómputo.
Lo que dicen los participantes importa más que los totales. La mayoría de los hallazgos críticos fueron confirmados rápido por los responsables de cada proyecto, porque verificarlos ahora cuesta casi nada con las mismas herramientas. El cuello de botella se ha desplazado: lo difícil ya no es encontrar el agujero, sino hacerlo llegar al mantenedor correcto. Y hay un motivo declarado para publicar rápido: quienes no están en el equipo llegarán igualmente a los mismos hallazgos.
Por eso la discusión sobre si el fallo de Coldcard lo encontró una persona o una máquina es secundaria. Ya contamos cómo la IA debilitó una firma post-cuántica en 60 horas que los humanos llevaban años estudiando. Esto es el mismo giro visto desde el otro lado: la ventaja de cinco años con la que contaba en silencio cualquier código sin tocar se acabó.
Qué hacer con esto
Si guardas claves en un Coldcard, el procedimiento es conocido: comprueba modelo y versión de firmware contra el aviso del fabricante, genera una semilla nueva con el firmware corregido y mueve los fondos. El defecto afecta a configuraciones de clave única; el multifirma no está tocado. Un detalle para quien esté siendo barrido justo ahora: en la última oleada los atacantes activaron replace-by-fee, así que la transacción se puede superar — si ves tu dirección en la mempool, paga una comisión más alta y mueve tus monedas primero. La ventana es de minutos.
Pero las conclusiones van más allá de las carteras, y tienen que ver con cómo verificas tu propio código.
- Verifica la ruta que se ejecuta, no la presencia del código. «La función existe y es correcta» no significa «es la que se llama». Para rutas críticas, escribe la prueba que falla cuando se sustituye la fuente: no «el TRNG funciona» sino «la semilla salió del TRNG».
- Desconfía de las guardas que comprueban si algo está definido.
#ifndef,defined(),if (config.FLAG): cero, la cadena vacía yfalseestán definidos. Comprueba el valor, no la declaración. - Dos implementaciones con firmas idénticas invitan a la sustitución silenciosa. Si el camino de respaldo y el principal comparten interfaz, el compilador calla y la revisión también. Ponles nombres distintos para que el cambio se vea en el diff.
- Un mecanismo que avisa pero no prohíbe no es un mecanismo. Un umbral que el usuario puede saltarse es un umbral que el usuario se saltará.
- Revisa qué estableció realmente tu última auditoría. Si fue sobre presencia y corrección y no sobre ejecución, sus conclusiones han envejecido — no porque los auditores se equivocaran, sino porque encontrar cosas se ha abaratado un orden de magnitud.
Ese último punto es práctico, no retórico. Código que llevaba cinco años considerándose revisado se está desmontando ahora en horas por diez mil dólares al día. Si tienes contratos o firmware en producción, sale más barato apuntar tú mismo esas herramientas contra ellos que esperar a que lo haga otro. Nosotros hacemos seguridad y análisis de productos web3, pero esto puedes hacerlo sin nosotros. Lo que importa es hacerlo antes.
Sigue leyendo
Qué hacer en las dos semanas previas a una auditoría de contratos
Los auditores facturan tiempo, y casi todo se va en cosas que podrías entregar antes. Cómo preparar el código para que encuentren fallos, no contexto.
Una IA rompió una firma post-cuántica en 60 horas. El problema no es la firma
HAWK sobrevivió a dos años de revisión experta y no sobrevivió a un fin de semana con el modelo de Anthropic. Qué supuesto rompe eso en tu arquitectura.
Infra Graveyard Weekly #02: LayerZero corta 20 redes y en Taiko 30 836 titulares se reparten 12 376 dólares
LayerZero deja de dar soporte a 20 redes y Stargate sale de cinco. Los RPC públicos de Polygon ya no existen y el plazo de Porto para sacar fondos ya pasó.