Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
Tools/GitHubGitHub/auditinfra-io/o1js-scan
Defensive ToolsStatic AnalysisVulnerability ScannersStatic Code Analysis (SAST)Vulnerability AnalysisCode AnalysisCryptographyDevSecOps
GitHubauditinfra-io/o1js-scan

o1js-scan

Dependency-free static analyzer for zk circuit soundness bugs in o1js/Mina zkApps and Noir circuits

View Repository
313617 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Website
Share

o1js-scan

CI Python License PyPI npm

Community package: o1js-scan is listed in the official o1js Community Packages directory.

Latest: 0.22.0 — a local MCP server lets Claude Code, Cursor and other AI coding assistants run the scanner while you write a zkApp: pip install 'o1js-scan[mcp]'. It runs on your machine over stdio and uploads nothing. A scan that analyzed no files is an error, not a clean result, and a result with no findings says it is not a security guarantee. The core scanner still has no dependencies. See CHANGELOG.

A fast, dependency-free static analyzer for zk circuit soundness bugs in:

  • o1js / Mina zkApps (TypeScript .ts / .js) — Kimchi circuits from @method bodies
  • Noir (.nr) — Aztec's Rust-like ZK DSL (including aztec-nr-shaped patterns)

The security-critical bugs usually aren't in the proving system — they're in the application's own constraints: witnesses the prover controls but the circuit never binds. o1js-scan is the under-constrained-signal scanner for Circom's cousins in the Mina and Noir ecosystems.

See also: gnark-safety (gnark circuits), vk-guard (verification-key regression).

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

Example

Given a vault whose withdraw amount is a prover-controlled witness that is never bound to on-chain state:

$ 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 is needed here only because the demo file lives under examples/, which the path classifier downgrades by default so that a repo's own sample code cannot fail its build. The same contract in your src/ reports HIGH with no flag.

The HIGH finding is the drainable bug. The fixed contract (examples/safe_vault.ts) drops it and exits 0, keeping only the informational LOW on the prover-chosen recipient:

$ 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

See examples/ for the o1js and Noir vulnerable/fixed pairs.

Contents

  • Install
  • Usage · Suppressing a finding
  • GitHub Action · MCP server for AI assistants
  • What it detects — o1js · Noir
  • Known limitations · Where this tool stops
  • Privacy and private code
  • Post-quantum review
  • Compatibility · How it works
  • Contributing

Install

pip install o1js-scan

For an isolated global CLI install, use pipx:

pipx install o1js-scan

For Node/npm-based Noir, Aztec, or o1js app repositories, install the npm wrapper:

npm install -D o1js-scan
npx noir-scan . --lang noir --fail-on high

The npm package is a thin wrapper around the same Python analyzer and requires Python 3.8+ on PATH (python3 or python). Set O1JS_SCAN_PYTHON to choose a specific interpreter.

Or from source:

git clone https://github.com/auditinfra-io/o1js-scan
cd o1js-scan
pip install -e .

No third-party Python dependencies. Python 3.8+. The noir-scan console script is installed alongside o1js-scan (same entry point), including through the npm wrapper.

Usage

# 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

Exit code is 1 when a finding at or above the --fail-on level (default high) is present and 0 otherwise — so you can drop it straight into CI. With the default, a low/medium finding (including the informational recipient rule below) does not fail the build; use --fail-on none to only report, or --strict (a shorthand for --fail-on medium) to gate more strictly while still treating low-severity findings as advisory. The two options are mutually exclusive so CI configuration cannot be ambiguous. A missing scan path exits 2 with an error on stderr, so a typo can't silently pass CI as a clean run. So does a path that exists but holds no o1js or Noir source the analyzer can read (for example --lang noir pointed at an o1js project); pass --allow-empty where that is legitimate. Every run prints a one-line summary (counts by severity and the gate verdict) to stderr.

Test code is excluded by default — both backends. Tests deliberately build invalid values and bad transactions to prove the asserts reject them, so a finding there is the point of the test rather than a circuit bug. A file counts as test code when:

  • its name matches *.test.ts / *.spec.ts (and the .js/.jsx/.tsx/.mjs /.cjs variants), or *_test.nr / test_*.nr;
  • it sits under a test/, tests/, __tests__/, spec/ or __mocks__/ directory;
  • (Noir only, content-based) the function carries a #[test] / #[test(...)] attribute, or sits inside a mod test { … } / mod tests { … } block — block-scoped, so a test module at the foot of a production file does not silence the rest of it.

Pass --include-tests to report them.

Download Tool