⏱️ Lectura: 11 min

Un auditor de inteligencia artificial encontró en 2026 lo que meses de escaneos automatizados no habían visto: una falla crítica de soundness en la librería openvm-pairing del zkVM OpenVM, catalogada como CVE-2026-46669. El bug permitía a un prover malicioso forjar cualquier igualdad de pairing, algo que rompe la seguridad de facto de cualquier sistema construido sobre Groth16, PLONK con KZG o firmas BLS que dependiera de esa librería.

📑 En este artículo
  1. TL;DR
  2. Introducción
  3. Qué pasó
  4. Contexto e historia
  5. Detalles técnicos y rendimiento
  6. Cómo empezar/probarlo
  7. Impacto y análisis
  8. Qué sigue
  9. Preguntas frecuentes
    1. ¿Qué es un zkVM y por qué importa este bug?
    2. ¿Qué es CVE-2026-46669 y qué versión lo corrige?
    3. ¿El bug afecta al sistema de pruebas de OpenVM en general?
    4. ¿Cómo pudo un prover malicioso explotar la falla?
    5. ¿Cómo participó la IA en encontrar el bug?
    6. ¿Qué proyectos están afectados?
  10. Referencias
    1. 📚 Artículos relacionados

El hallazgo lo produjo zkao, el auditor de IA de la firma zkSecurity, después de más de nueve horas y media de escaneo continuo sobre el código de OpenVM. El equipo humano validó la explotabilidad, armó un PoC mínimo, coordinó la divulgación con los mantenedores y el fallo quedó corregido en OpenVM 1.6.0.

TL;DR

  • zkao, el auditor de IA de zkSecurity, halló un bug crítico de soundness en openvm-pairing tras 9,5 horas de escaneo.
  • El fallo es CVE-2026-46669 y se corrigió en OpenVM 1.6.0, commit a720e2c.
  • Permitía a un prover malicioso forjar cualquier igualdad de pairing, rompiendo Groth16, KZG y BLS.
  • La causa: falta un chequeo de subcampo sobre el factor de escalado en la verificación de pairing.
  • Meses antes, escaneos con Opus 4.6, Codex 5.3, Opus 4.7 y Codex 5.4 no hallaron un bug real explotable.
  • El bug no afecta al sistema de pruebas del zkVM en sí, solo a proyectos que usan openvm-pairing.
  • zkSecurity confirmó la explotabilidad, armó un PoC mínimo y coordinó la divulgación con OpenVM.
  • Todos los partners conocidos de OpenVM ya actualizaron a la versión 1.6.0, según zkSecurity.

Introducción

Este hallazgo es el segundo de una serie que zkSecurity viene publicando sobre auditorías de código asistidas por IA. El primer caso fue la librería criptográfica CIRCL de Cloudflare; en esta entrada el objetivo fue algo mucho más complejo: un zkVM completo, es decir, una máquina virtual que genera pruebas de conocimiento cero de la ejecución de un programa arbitrario.

OpenVM es un framework para construir zkVMs modulares en Rust, pensado para que distintos proyectos ensamblen su propia máquina virtual con los componentes criptográficos que necesiten. Uno de esos componentes es openvm-pairing, la librería guest encargada de las operaciones de pairing sobre curvas elípticas. Es justo ahí, y no en el núcleo del sistema de pruebas, donde apareció el bug.

Qué pasó

Cuatro meses antes de este hallazgo, zkSecurity había escaneado OpenVM con el mismo procedimiento que aplica a cualquier proyecto nuevo: un LLM simple con un prompt genérico y, después, ese mismo LLM apoyado en las skills expertas del equipo. Corrieron primero Opus 4.6 y Codex 5.3, y en cuanto salieron Opus 4.7 y Codex 5.4 repitieron el escaneo con esos modelos.

Los resultados de esas cuatro corridas fueron observaciones válidas pero no explotables. Los modelos etiquetaron varios hallazgos como Critical o High con total confianza, y ninguno resistió una revisión manual seria.

La hipótesis del equipo era que un zkVM es demasiado complejo para que un LLM sin más ayuda lo entienda con 300.000 o incluso un millón de tokens de contexto: las dependencias entre módulos son mucho más densas que en una librería criptográfica típica, donde alcanza con repartir cada primitiva a un subagente distinto que lea una carpeta acotada.

Ilustración de código y candados representando una auditoría de seguridad con IA
zkao escaneó OpenVM durante más de nueve horas antes de hallar el bug. Foto de Brecht Corbeel en Unsplash

Por eso el equipo decidió correr zkao, su auditor de IA con context engineering propio, incluso rompiendo su propia regla de usarlo solo después de que un LLM simple encontrara ya un bug real. Tras más de nueve horas y media de escaneo, zkao devolvió muchos hallazgos; entre ellos, uno saltó de inmediato: un bug crítico de soundness en la verificación de pairing de una librería guest.

📌 Nota: zkao produjo un hallazgo candidato, no un reporte final. El equipo humano de zkSecurity validó el bug, confirmó que era explotable y armó el PoC mínimo antes de reportarlo a OpenVM.

Contexto e historia

Los pairings son el motor detrás de Groth16, de PLONK cuando usa compromisos KZG y de las firmas BLS. En los tres casos, quien verifica no evalúa un solo pairing: evalúa si un producto de varios pairings es igual a uno. De esa única respuesta binaria depende que una prueba SNARK sea válida, que una apertura KZG sea correcta o que una firma se verifique.

Formalmente, un pairing es un mapa bilineal e: G1 × G2 → GT, donde G1 y G2 son grupos de una curva elíptica y GT es un subgrupo multiplicativo de un cuerpo de extensión, en este caso F(p¹²). Calcular un pairing tiene dos etapas: primero el Miller loop, que evalúa una función de Miller y produce un elemento de F(p¹²); después la exponenciación final, que reduce ese elemento al subgrupo correcto de GT.

Cuando hay que verificar un producto de varios pairings, el circuito puede correr todos los Miller loops por separado y multiplicar sus salidas antes de aplicar una sola exponenciación final. Esa optimización, muy común en implementaciones eficientes, es la que abre la puerta al bug: si la verificación de que el resultado intermedio pertenece realmente al subcampo correcto no es estricta, un atacante puede fabricar un valor que pase el chequeo final sin ser el producto de pairing legítimo.

Detalles técnicos y rendimiento

Bug Severidad IA Severidad OpenVM Commit del fix Hallado por
openvm-pairing: falta chequeo de subcampo en el factor de escalado Crítica Crítica a720e2c zkao

Es la primera vez en esta serie de experimentos de zkSecurity en que la severidad asignada por la IA coincide exactamente con la que confirmó el equipo mantenedor: ambas partes lo calificaron como Crítico.

flowchart TD
A["Miller loop por cada par (Pi, Qi)"] --> B["Producto de las salidas f"]
B --> C{"Chequeo de subcampo del factor de escalado"}
C -- "sin chequeo: bug" --> D["Exponenciación final acepta cualquier f"]
C -- "con chequeo: fix 1.6.0" --> E["Exponenciación final solo sobre valores válidos"]
D --> F["Prover malicioso forja la igualdad"]
E --> G["Verificación sound"]

En pseudocódigo, la verificación vulnerable se veía más o menos así:

// Verificacion de pairing SIN el chequeo de subcampo (vulnerable)
fn verify_pairing_product(f: Fp12) -> bool {
    let result = f.final_exponentiation();
    result == Fp12::one()
}

El problema es que final_exponentiation() por sí sola no garantiza que f haya salido realmente de un producto de Miller loops válido. La corrección agrega el chequeo que faltaba antes de aceptar el resultado:

// Verificacion corregida en OpenVM 1.6.0: valida que el
// factor de escalado pertenece al subcampo correcto
fn verify_pairing_product(f: Fp12, scaling_factor: Fp12) -> bool {
    if !scaling_factor.is_in_correct_subfield() {
        return false;
    }
    let result = f.final_exponentiation();
    result == Fp12::one()
}
Diagrama abstracto de circuitos criptográficos y curvas elípticas
La falla vivía en el chequeo de subcampo del factor de escalado del pairing. Foto de Brecht Corbeel en Unsplash

Cómo empezar/probarlo

Si tu proyecto depende de openvm-pairing, lo primero es confirmar la versión que estás usando y fijarla explícitamente en tu manifiesto de Rust:

[dependencies]
openvm-pairing = "1.6.0"

Después, actualizá la dependencia y verificá el árbol de versiones. El comando es idéntico en Linux, macOS y Windows porque corre sobre Cargo, no sobre el sistema operativo:

# Linux / macOS / Windows (PowerShell o terminal)
cargo update -p openvm-pairing --precise 1.6.0
cargo tree -p openvm-pairing

Para confirmar que estás sobre la versión parcheada, revisá que la salida de cargo tree muestre openvm-pairing v1.6.0 o superior. Si tu Cargo.lock todavía apunta a una versión previa al commit a720e2c, tu build sigue expuesto.

Impacto y análisis

El bug en sí es puntual, pero el proceso que lo encontró deja una lección más amplia para quien audita código criptográfico complejo. Repartir un zkVM en carpetas y auditar cada primitiva de forma aislada no alcanza, porque la seguridad no siempre se compone.

💭 Clave: podés tener un módulo A demostrablemente seguro y un módulo B demostrablemente seguro cuya composición A+B deje de ser segura. Por eso auditar cada primitiva por separado no detecta este tipo de bugs en un zkVM.

Según zkSecurity, lo que un subagente debería producir al revisar un módulo denso no es una lista de bugs, sino conocimiento reutilizable: qué asume ese módulo, qué le delega a quien lo llama y qué invariante da por hecho sin verificarlo. Representar bien ese conocimiento es lo difícil: muy corto, se pierde el detalle de implementación donde vive el bug; muy largo, satura el contexto del agente principal antes de poder combinarlo con el resto.

Qué sigue

zkSecurity planea seguir esta serie con más objetivos complejos, ahora que la hipótesis de que un zkVM requiere herramientas con context engineering dedicado, y no solo un LLM con más tokens de contexto, quedó validada con un bug real.

⚠️ Ojo: si mantenés una librería que hace pairing checks, revisá explícitamente que el chequeo de subgrupo o subcampo se aplique a cada elemento intermedio, no solo al resultado final de la exponenciación.

Para el ecosistema zkVM en general, el episodio funciona como aviso: cualquier librería guest que agregue pairings, KZG o firmas BLS sobre un framework modular como OpenVM debería sumar este chequeo a su checklist de auditoría estándar, y no asumir que la seguridad del framework base cubre a las librerías que corren sobre él.

📖 Resumen en Telegram: Ver resumen

Probalo vos: cloná el repositorio de OpenVM, fijá openvm-pairing = "1.6.0" en tu Cargo.toml y corré cargo tree -p openvm-pairing para confirmar que ya estás sobre la versión parcheada.

Preguntas frecuentes

¿Qué es un zkVM y por qué importa este bug?

Un zkVM es una máquina virtual que genera una prueba de conocimiento cero de que ejecutó correctamente un programa, sin revelar los datos de entrada. OpenVM es un framework para ensamblar zkVMs modulares en Rust; el bug no está en el núcleo del sistema de pruebas, sino en openvm-pairing, una librería guest que cualquier proyecto puede usar para operaciones de pairing.

¿Qué es CVE-2026-46669 y qué versión lo corrige?

CVE-2026-46669 identifica el fallo de soundness en el chequeo de pairing de openvm-pairing. Se corrigió en el commit a720e2c, incluido en OpenVM 1.6.0.

¿El bug afecta al sistema de pruebas de OpenVM en general?

No. Según zkSecurity, no es un bug de soundness en el sistema de pruebas del zkVM en sí. Solo afecta al código de proyectos que usan la librería openvm-pairing para verificar pairings, por ejemplo en Groth16, KZG o BLS.

¿Cómo pudo un prover malicioso explotar la falla?

Al faltar el chequeo de que el factor de escalado pertenece al subcampo correcto, un atacante podía construir un valor que superara la exponenciación final sin ser el producto real de los Miller loops, logrando que la verificación aceptara una igualdad de pairing falsa.

¿Cómo participó la IA en encontrar el bug?

zkao, el auditor de IA de zkSecurity, escaneó el código de OpenVM durante más de nueve horas y media y devolvió el hallazgo como candidato. Meses antes, escaneos con LLMs simples como Opus 4.6, Codex 5.3, Opus 4.7 y Codex 5.4 no habían detectado un bug explotable real.

¿Qué proyectos están afectados?

Según zkSecurity, todos los partners conocidos que construyen sobre OpenVM ya habían actualizado a la versión 1.6.0 al momento de publicarse el hallazgo.

Referencias

📱 ¿Te gusta este contenido? Únete a nuestro canal de Telegram @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.

Imagen destacada: Foto de Jake Walker en Unsplash


Clara Vásquez

Analista de ciberseguridad enfocada en vulnerabilidades críticas, zero-days y amenazas emergentes. Cubre CVEs de alto impacto, análisis de malware, incidentes de ransomware y tendencias de seguridad para LATAM.

0 Comentarios

Deja un comentario

Marcador de posición del avatar

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.