
Analizador estático sin dependencias para errores de solidez en circuitos zk en o1js/Mina zkApps y circuitos Noir
Paquete de la comunidad:
o1js-scanestá listado en el directorio oficial de Paquetes de la Comunidad de o1js.
Última versión: 0.22.0 — un servidor MCP local permite que Claude Code, Cursor y otros asistentes de codificación con IA ejecuten el escáner mientras escribes una zkApp:
pip install 'o1js-scan[mcp]'. Se ejecuta en tu máquina a través de stdio y no sube nada. Un escaneo que no analizó ningún archivo es un error, no un resultado limpio, y un resultado sin hallazgos indica que no es una garantía de seguridad. El escáner principal sigue sin tener dependencias. Consulta el CHANGELOG.
Un analizador estático rápido y sin dependencias para bugs de solidez en circuitos zk en:
.ts / .js) — circuitos Kimchi a partir de cuerpos @method.nr) — el DSL ZK de Aztec similar a Rust (incluyendo patrones con forma de aztec-nr)Los bugs críticos para la seguridad normalmente no están en el sistema de prueba — están en las
restricciones propias de la aplicación: testigos que el probador controla pero que el circuito
nunca vincula. o1js-scan es el escáner de señales sub-restringidas para los primos de Circom en los ecosistemas de Mina y Noir.
Ver también: gnark-safety (circuitos gnark), vk-guard (regresión de clave de verificación).
pip install o1js-scan
# or: pipx install o1js-scan
# or: npm install -D o1js-scan
o1js-scan path/to/zkapp # o1js + Noir (auto)
noir-scan path/to/circuits # same binary — Noir-friendly alias
noir-scan . --lang noir --fail-on high --sarif noir.sarif
Dado un vault cuyo monto de withdraw es un testigo controlado por el probador que
nunca está vinculado al estado on-chain:
$ o1js-scan examples/vulnerable_vault.ts --include-examples
LOW O1JS_UNCONSTRAINED_RECIPIENT vulnerable_vault.ts:23 fn=withdraw Recipient `to` is prover-chosen in `withdraw`
HIGH O1JS_UNCONSTRAINED_WITNESS vulnerable_vault.ts:23 fn=withdraw Unconstrained witness `amount` flows to send_amount in `withdraw`
o1js-scan: 2 finding(s) [1 high, 1 low] in 1 of 1 file(s) — fails (--fail-on high)
$ echo $?
1
--include-examples es necesario aquí solo porque el archivo de demostración se encuentra bajo
examples/, que el clasificador de rutas degrada por defecto para que el propio código de ejemplo de un repositorio no pueda fallar su compilación. El mismo contrato en tu src/ reporta
HIGH sin ninguna bandera.
El hallazgo HIGH es el bug drenable. El contrato corregido
(examples/safe_vault.ts) lo elimina y sale con 0, manteniendo solo el LOW informativo
sobre el destinatario elegido por el probador:
$ o1js-scan examples/safe_vault.ts --include-examples
LOW O1JS_UNCONSTRAINED_RECIPIENT safe_vault.ts:23 fn=withdraw Recipient `to` is prover-chosen in `withdraw`
o1js-scan: 1 finding(s) [1 low] in 1 of 1 file(s) — passes (--fail-on high)
$ echo $?
0
Consulta examples/ para los pares vulnerable/corregido de o1js y Noir.
pip install o1js-scan
Para una instalación global aislada de la CLI, use pipx:
pipx install o1js-scan
Para repositorios de aplicaciones Noir, Aztec u o1js basados en Node/npm, instala el wrapper de npm:
npm install -D o1js-scan
npx noir-scan . --lang noir --fail-on high
El paquete npm es un envoltorio fino alrededor del mismo analizador de Python y requiere
Python 3.8+ en PATH (python3 o python). Establece O1JS_SCAN_PYTHON para elegir un
intérprete específico.
O desde el código fuente:
git clone https://github.com/auditinfra-io/o1js-scan
cd o1js-scan
pip install -e .
Sin dependencias de Python de terceros. Python 3.8+. El script de consola noir-scan se
instala junto con o1js-scan (mismo punto de entrada), incluso a través del wrapper
de npm.
# scan a directory (recursively; skips node_modules, target/, .git, …)
o1js-scan path/to/project
# Noir-only / o1js-only
noir-scan circuits --lang noir
o1js-scan src --lang o1js
# scan a single file
o1js-scan src/MyContract.ts
noir-scan src/main.nr
# machine-readable output for CI
o1js-scan src --json
# SARIF 2.1.0 for GitHub code scanning (writes o1js-scan.sarif by default)
o1js-scan src --sarif
noir-scan . --lang noir --sarif noir.sarif
# choose which severity fails CI (critical|high|medium|low|none; default high)
o1js-scan src --fail-on medium
# progressive/power-user gate (equivalent to --fail-on medium)
o1js-scan src --strict
# test code is excluded by default (both backends); opt back in
o1js-scan src --include-tests
# example code is downgraded to LOW by default; keep original severity
o1js-scan src --include-examples
# a path with no o1js / Noir source exits 2; opt out where that is expected
o1js-scan packages/ --allow-empty
o1js-scan --version
El código de salida es 1 cuando hay un hallazgo igual o superior al nivel de --fail-on (por defecto high) y 0 en caso contrario, por lo que puedes integrarlo directamente en CI. Con el valor predeterminado, un hallazgo de severidad baja/media (incluida la regla informativa de destinatarios que se describe a continuación) no hace fallar la compilación; usa --fail-on none para solo informar, o --strict (una forma abreviada de --fail-on medium) para aplicar un filtro más estricto mientras sigues tratando los hallazgos de severidad baja como informativos. Las dos opciones son mutuamente excluyentes, de modo que la configuración de CI no puede ser ambigua. Una ruta de escaneo inexistente sale con 2 y un error en stderr, así que un error tipográfico no puede pasar silenciosamente en CI como una ejecución limpia. Lo mismo ocurre con una ruta que existe pero no contiene código fuente o1js o Noir que el analizador pueda leer (por ejemplo, --lang noir apuntando a un proyecto o1js); usa --allow-empty cuando eso sea legítimo. Cada ejecución imprime un resumen de una línea (recuentos por severidad y el veredicto del filtro) en stderr.
El código de prueba se excluye por defecto — en ambos backends. Las pruebas construyen deliberadamente valores inválidos y transacciones incorrectas para demostrar que las aserciones las rechazan, por lo que un hallazgo allí es el propósito de la prueba y no un error del circuito. Un archivo se considera código de prueba cuando: