Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
o1js-scan — Abhängigkeitsfreier statischer Analysator für Soundness-Fehler in zk-Schaltkreisen bei o1js/Mina zkApps und Noir-Schaltkreisen | Kitploit
Tools/GitHubGitHub/auditinfra-io/o1js-scan
DefensivwerkzeugeStatische AnalyseSchwachstellenscannerStatische Code-Analyse (SAST)SchwachstellenanalyseCode-AnalyseKryptographieDevSecOps
GitHubauditinfra-io/o1js-scan

o1js-scan

Abhängigkeitsfreier statischer Analysator für Soundness-Fehler in zk-Schaltkreisen bei o1js/Mina zkApps und Noir-Schaltkreisen

Repository anzeigen
210vor 4 TagenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Webseite
Teilen

o1js-scan

CI Python License PyPI npm

Community-Paket: o1js-scan ist im offiziellen Verzeichnis o1js Community Packages gelistet.

Neueste Version: 0.20.0 — der Analyzer liest jetzt Contracts, die extends TokenContract verwenden. Bis zu diesem Release erfasste das Contract-Gate nur SmartContract, sodass jeder Fungible Token, jede NFT-Sammlung und jeder AMM-Pool im Ökosystem als "no findings" gescannt wurde. Wenn Sie einen Token-Contract vor 0.20.0 gescannt haben, scannen Sie ihn erneut. Siehe .

CHANGELOG

Ein schneller, abhängigkeitsfreier statischer Analyzer für zk-Circuit-Soundness-Bugs in:

  • o1js / Mina zkApps (TypeScript .ts / .js) — Kimchi-Circuits aus @method-Bodies
  • Noir (.nr) — Aztecs Rust-ähnliche ZK-DSL (einschließlich aztec-nr-förmiger Muster)

Die sicherheitskritischen Bugs liegen meist nicht im Proving-System — sie liegen in den eigenen Constraints der Anwendung: Witnesses, die der Prover kontrolliert, aber der Circuit niemals bindet. o1js-scan ist der Under-Constrained-Signal-Scanner für die Cousins von Circom in den Ökosystemen Mina und Noir.```bash 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

root@kitploit:~
### Beispiel

Gegeben sei ein Vault, dessen `withdraw`-Betrag ein vom Prover kontrollierter Witness ist, der
niemals an den On-Chain-Zustand gebunden wird:```console
$ 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 wird hier nur benötigt, weil die Demo-Datei unter examples/ liegt, was der Pfad-Klassifizierer standardmäßig herabstuft, damit der Beispielcode eines Repos seinen eigenen Build nicht fehlschlagen lässt. Derselbe Vertrag in deinem src/ meldet HIGH ohne Flag.

Der HIGH-Fund ist der ausleerbare Bug. Der korrigierte Vertrag (examples/safe_vault.ts) verwirft ihn und beendet mit 0, wobei nur der informative LOW beim vom Prover gewählten Empfänger erhalten bleibt:```console $ 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

root@kitploit:~
Siehe [`examples/`](https://github.com/auditinfra-io/o1js-scan/blob/main/examples) für die o1js- und Noir-Paare aus verwundbaren/fixed Versionen.

## Inhalt

- [Installation](#install)
- [Verwendung](#usage) · [Einen Befund unterdrücken](#suppressing-a-reviewed-finding)
- [GitHub Action](#github-action)
- [Was es erkennt — o1js](#what-it-detects-o1js) · [Noir](#what-it-detects-noir)
- [Bekannte Einschränkungen](#known-limitations) · [Wo dieses Tool an seine Grenzen stößt](#where-this-tool-stops)
- [Datenschutz und privater Code](#privacy-and-private-code)
- [Post-Quanten-Überprüfung](#post-quantum-review)
- [Kompatibilität](#compatibility) · [Funktionsweise](#how-it-works)
- [Mitwirken](#roadmap--contributing)

## Installation```bash
pip install o1js-scan

Für eine isolierte globale CLI-Installation verwenden Sie pipx:```bash pipx install o1js-scan

root@kitploit:~
Für Node/npm-basierte Noir-, Aztec- oder o1js-App-Repositories installieren Sie den npm-Wrapper:```bash
npm install -D o1js-scan
npx noir-scan . --lang noir --fail-on high

Das npm-Paket ist ein dünner Wrapper um denselben Python-Analyzer und erfordert Python 3.8+ im PATH (python3 oder python). Setzen Sie O1JS_SCAN_PYTHON, um einen bestimmten Interpreter auszuwählen.

Oder aus dem Quellcode:```bash git clone https://github.com/auditinfra-io/o1js-scan cd o1js-scan pip install -e .

root@kitploit:~
Keine Python-Abhängigkeiten von Drittanbietern. Python 3.8+. Das Konsolenskript `noir-scan` wird
zusammen mit `o1js-scan` installiert (gleicher Einstiegspunkt), auch über den npm-
Wrapper.

## Verwendung```bash
# 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

o1js-scan --version

Der Exit-Code ist 1, wenn ein Finding auf oder über der --fail-on-Stufe (Standard high) vorliegt, und andernfalls 0 — du kannst ihn also direkt in CI einbinden. Mit dem Standard lässt ein Low-/Medium-Finding (einschließlich der unten beschriebenen informativen Empfänger-Regel) den Build nicht fehlschlagen; verwende --fail-on none, um nur zu berichten, oder --strict (eine Kurzform für --fail-on medium), um strenger zu filtern und Findings mit niedrigem Schweregrad weiterhin als Hinweis zu behandeln. Die beiden Optionen schließen sich gegenseitig aus, damit die CI-Konfiguration nicht mehrdeutig sein kann. Ein fehlender Scan-Pfad beendet mit 2 und einer Fehlermeldung auf stderr, sodass ein Tippfehler nicht stillschweigend als sauberer Lauf durch die CI gehen kann. Jeder Lauf gibt eine einzeilige Zusammenfassung (Anzahl nach Schweregrad und das Gate-Urteil) auf stderr aus.

Testcode ist standardmäßig ausgeschlossen — bei beiden Backends. Tests bauen absichtlich ungültige Werte und fehlerhafte Transaktionen, um zu belegen, dass die Asserts sie ablehnen; ein Finding dort ist also der Sinn des Tests und kein Circuit-Bug. Eine Datei gilt als Testcode, wenn:

  • ihr Name *.test.ts / *.spec.ts entspricht (und den .js/.jsx/.tsx/.mjs /.cjs-Varianten) oder *_test.nr / test_*.nr;
  • sie unter einem Verzeichnis test/, tests/, __tests__/, spec/ oder __mocks__/ liegt;
  • (nur Noir, inhaltsbasiert) die Funktion ein #[test] / #[test(...)]-Attribut trägt oder sich innerhalb eines mod test { … } / mod tests { … }-Blocks befindet — blockbezogen, sodass ein Testmodul am Ende einer Produktionsdatei nicht den Rest davon stummschaltet.

Übergib --include-tests, um sie zu melden.

Beispielcode wird herabgestuft, nicht verworfen. Ein Finding in einem examples/- oder example/-Verzeichnis oder in einer Datei namens *.eg.ts (.nr und die anderen JS/TS- Erweiterungen ebenfalls) wird auf LOW herabgestuft, mit einem Hinweis — weiterhin gemeldet, aber nicht mehr in der Lage, einen Build fehlschlagen zu lassen. Beispielcode ist absichtlich vereinfacht, und die eigenen Beispiele eines Frameworks als Schwachstellen zu markieren, ist Rauschen; aber er wird in die Produktion kopiert weit häufiger als Testcode, weshalb er herabgestuft statt verborgen wird. Übergib --include-examples, um den ursprünglichen Schweregrad beizubehalten.

Wann immer eine der beiden Richtlinien greift, gibt der Lauf eine Zeile auf stderr aus, die dies mitteilt — z. B. 6 file(s) skipped as test code, 1 finding(s) downgraded as examples — damit ein ruhiger Scan niemals stillschweigend ruhig ist. Die Zählungen erscheinen auch in SARIF unter invocation.properties. Beachte den Kompromiss: Die Erkennung ist nur pfadbasiert (kein describe(/it(-Parsing), sodass ein Produktions-Circuit, der unter tests/ gespeichert ist, übersprungen wird — die stderr-Zeile ist, wie du es bemerkst.

Verzeichnisse, die beim Durchlaufen eines Baums übersprungen werden: node_modules, target (nargo), .git, dist, build, __pycache__, .venv, venv.

Unterdrücken eines überprüften Findings

Schalte ein Finding, das du triagiert hast, stumm, ohne das Gate zu lockern, mit einem Inline- Kommentar auf — oder in der Zeile über — der markierten Zeile:```ts this.send({ to, amount }); // o1js-scan-disable-line O1JS_UNCONSTRAINED_WITNESS

// o1js-scan-disable-next-line this.send({ to, amount });

root@kitploit:~
Ihre Anfrage konnte nicht verarbeitet werden, da kein zu übersetzender Inhalt bereitgestellt wurde. Bitte senden Sie den Markdown-Text, den Sie übersetzen möchten.```nr
let inv = unsafe { hint(x) };  // o1js-scan-disable-line NOIR_UNCONSTRAINED_WITNESS

Eine oder mehrere Regel-IDs auflisten, um nur diese zu unterdrücken; eine reine Direktive (ohne IDs) unterdrückt jede Regel in der Zielzeile.

Als Bibliothek:```python from o1js_scan import analyze_file, analyze_project

for path, finding in analyze_project("src", lang="auto"): print(path, finding.rule_id, finding.severity.value, finding.title)

root@kitploit:~
## GitHub Action

Fügen Sie den Scanner in wenigen Zeilen zur CI hinzu. Befunde erscheinen als Annotationen im PR-Diff und als Warnungen im Tab **Security → Code scanning** des Repositorys.```yaml
# .github/workflows/o1js-scan.yml
name: o1js-scan
on: [push, pull_request]

permissions:
  contents: read
  security-events: write   # required to upload SARIF to code scanning

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: auditinfra-io/[email protected]
        with:
          path: src              # optional, defaults to the repo root
          lang: auto             # auto | o1js | noir
          # version: 0.20.0       # optional, pin the scanner version
          # fail-on: high         # optional, fail the job on high/critical

Nur-Noir-CI-Rezept

Empfohlen für Noir-Projekte, die Code-Scanning-Warnungen und ein Gate für hohe Schweregrade wünschen:```yaml

  • uses: auditinfra-io/[email protected] with: path: . lang: noir fail-on: high
root@kitploit:~
Oder ohne die Action:```bash
pip install o1js-scan
noir-scan . --lang noir --fail-on high --sarif noir.sarif

pre-commit (optional)```yaml

.pre-commit-config.yaml

  • repo: local hooks:
    • id: noir-scan name: noir-scan entry: noir-scan language: system pass_filenames: false args: [".", "--lang", "noir", "--fail-on", "high"]
root@kitploit:~
Inputs: `path` (Standard `.`), `lang` (`auto`|`o1js`|`noir`, Standard `auto`),
`version` (zu installierende PyPI-Version, Standard neueste), `upload-sarif` (Standard
`true`), `fail-on` (`critical`|`high`|`medium`|`low`|`none`, Standard `none`),
`fail-on-findings` (veraltet, Standard `false`), `include-tests` (Standard
`false`), `include-examples` (Standard `false`). Ausgabe: `sarif-file`. SARIF-
Upload benötigt `security-events: write` und aktiviertes Code Scanning.

Der Bericht und das Gate werden aus einem Argument-Array erstellt, sodass `include-tests`
und `include-examples` auf beide angewendet werden — das SARIF, das Sie lesen, und der Exit-Code, auf den Sie
gaten, beschreiben immer denselben Quellsatz. Der Reporting-Durchlauf läuft mit
`--fail-on none`, sodass Befunde den SARIF-Upload nie blockieren, aber ein operativer
Fehler (ein Pfad, der nicht existiert, ein CLI-Nutzungsfehler) lässt den Schritt
weiterhin fehlschlagen, anstatt als sauberer Scan gemeldet zu werden.

`fail-on-findings: true` bleibt aus Kompatibilitätsgründen erhalten und wird auf `fail-on: high`
abgebildet, wenn `fail-on` auf `none` belassen wird; es gibt eine Veraltungswarnung aus. Bevorzugen Sie
`fail-on`, das bei jeder Schwere gate kann.

## Was es erkennt (o1js)

### Unterstützte Regeln auf einen Blick

<!-- BEGIN GENERATED RULE SUMMARY -->
| Backend | Regeln | High-fähig | Medium-fähig | Low-fähig |
|---------|------:|-------------:|---------------:|------------:|
| o1js | 18 | 11 | 12 | 2 |
| Noir | 11 | 4 | 9 | 1 |
| **Gesamt** | **29** | **15** | **21** | **3** |
<!-- END GENERATED RULE SUMMARY -->

Die Zählungen sind unterschiedliche Regel-IDs, die von jedem Backend unterstützt werden. Eine Regel, die
Schwere je nach Kontext zuweist (zum Beispiel high für einen Werttransfer und
medium für einen State-Write), erscheint in mehr als einer Schwere-Spalte, sodass die
Schwere-Spalten absichtlich nicht zur Regel-Gesamtzahl addieren. Derzeit gibt es keine
Critical- oder Info-Schwere-Regeln. Die vollständigen Beschreibungen und
False-Positive-Guards folgen unten.

<!-- BEGIN GENERATED O1JS RULE TABLE -->
| Regel | Schwere | Was sie bedeutet |
|------|----------|---------------|
| `O1JS_MISSING_STATE_PRECONDITION` | high | `this.x.get()`-Lesen ohne passendes `requireEquals(...)` / `getAndRequireEquals()`. Ein bloßes `get()` fügt **keine** Account-Vorbedingung hinzu, sodass der Proof `x` nicht an seinen On-Chain-Wert bindet — ein Prover kann jeden Wert einsetzen. |
| `O1JS_UNCONSTRAINED_WITNESS` | high / medium | Ein `@method`-Argument (ein prover-kontrollierter privater Witness) fließt in einen Send-**Betrag** (`this.send(...)` oder ein `AccountUpdate.create*(...).send(...)` derselben Methode) oder ein State-`.set(...)` und wird **nie** zugesichert. Direktes Analogon zu einem unterbeschränkten Circom-Signal. High, wenn es einen Werttransfer erreicht. |
| `O1JS_UNCONSTRAINED_PROVABLE_WITNESS` | high / medium / low | Eine lokale `Provable.witness(...)`-Variable fließt in einen Send-/State-Effekt mit **keiner** In-Circuit-Zusicherung. Der Witness-Callback läuft *außerhalb* des Circuits (er ist nur ein Prover-Hinweis), sodass das Ergebnis ein frischer prover-kontrollierter Wert ist — die andere Witness-Quelle neben `@method`-Argumenten. Er muss neu abgeleitet und zugesichert (`x.assertEquals(<recomputed>)`) oder an State gebunden werden. High bei einem Send-Betrag (`this.send(...)` oder `AccountUpdate.create*` derselben Methode). |
| `O1JS_UNCONSTRAINED_RECIPIENT` | low | Ein `@method`-Argument wird **nur** als `to:`-Empfänger eines Sends verwendet. Dies ist normalerweise beabsichtigt (ein Nutzer benennt sein eigenes Auszahlungsziel) und ist informativ — es ist nur relevant, wenn das Ziel eine feste Treasury oder eine im State erfasste Adresse sein soll. Löst **nicht** das CI-Exit-Code-Gate aus. |
| `O1JS_WITNESS_NOT_BOUND_TO_STATE` | medium | Ein Witness ist nur *trivial* beschränkt (z. B. `> 0` oder gegen eine Konstante verglichen), bevor ein Effekt erfolgt — nie an On-Chain-State gebunden. Bestätigen Sie, dass die Off-Chain-Orchestrierung dies sicher macht, oder das Guthaben ist bis zu seinem Bestandswert abziehbar. |
| `O1JS_STALE_MERKLE_ROOT` | high | Eine Methode berechnet einen Merkle-Root aus einem prover-gelieferten Witness (`computeRootAndKey` / `calculateRoot`) neu, bindet aber **keinen** der neu berechneten Roots an den aktuellen On-Chain-Root. Ohne ein `this.root.requireEquals(...)` / `assertEquals` gegen den Live-Root kann ein Prover einen Witness für einen fabrizierten oder veralteten Baum übergeben — Mitgliedschaft fälschen oder alten State wiedergeben. Die Bindung kann in einem undekorierten Helper derselben Klasse (`this.verifyX(witness)`) liegen; die Helper-Propagierung deckt das ab. |
| `O1JS_UNVERIFIED_PROOF` | high | Ein `@method`-Parameter vom Typ `Proof<...>` / `SelfProof<...>` / `DynamicProof<...>` wird nie `.verify()`'d, bevor seine öffentlichen Felder verwendet werden. Das Übergeben eines Proofs verifiziert ihn nicht — ohne explizites Verify kann der Prover ein beliebiges Proof-Objekt liefern, und jede Verwendung seines `publicOutput` ist unbeschränkt. Löst auch aus, wenn `.verifyIf(flag)` durch ein unbeschränktes `@method`-Argument gegated wird und die öffentlichen Felder des Proofs gelesen werden, weil der Prover die Bedingung falsch machen kann. |
| `O1JS_UNASSERTED_BOOL` | high / medium | Ein o1js-Prädikat (`equals` / `lessThanOrEqual` / …) gibt ein `Bool` zurück und fügt **keine** Beschränkung hinzu, es sei denn, das Ergebnis wird zugesichert oder verwendet. HIGH, wenn der Aufruf eine bloße verworfene Anweisung ist; MEDIUM, wenn er einer lokalen Variable zugewiesen wird, die nie wieder referenziert wird. |
| `O1JS_UNCONSTRAINED_SENDER` | high / medium | `this.sender.getUnconstrained()` gibt den Tx-Sender zurück, ohne ihn zu beweisen. HIGH, wenn dieser Wert (oder eine lokale Variable daraus) in ein Assert / State-`.set` / `send` fließt (leere Prüfung); andernfalls MEDIUM. Bevorzugen Sie `this.sender.getAndRequireSignature()` oder das erweiterte Idiom `AccountUpdate.createSigned(sender)`. **Bleibt still, wenn** (1) dieselbe `@method` auch irgendwo `this.sender.getAndRequireSignature()` aufruft (Signaturanforderung ist methodenbezogen), oder (2) der gewitness-te Sender-Wert das Argument für `AccountUpdate.createSigned(...)` / ein `AccountUpdate.create(...).requireSignature()` auf demselben Schlüssel ist (Argumentidentität erforderlich — ein `createSigned` auf einem anderen Schlüssel unterdrückt nicht). |
| `MissingRangeCheck` | high | Ein rohes `Field` (nicht das range-geprüfte `UInt64`/`UInt32`) wird als Transferbetrag verwendet. Ein `Field` ist ein Element mod p und nicht range-beschränkt. |
| `O1JS_WEAK_PERMISSIONS` | high / medium | `editState` / `send` auf `proofOrSignature()` oder `none()` gesetzt, wodurch der zkApp-Account-Schlüssel den Circuit durch Signieren umgehen kann. Markiert auch `setVerificationKey` / `setPermissions`, die auf `signature` / `proofOrSignature` / `none` belassen wurden (Minas dokumentierte Upgrade-Trainingsräder); HIGH in Kombination mit einem schwachen `editState`/`send` im selben `permissions.set`. |
| `O1JS_LOGIC_OUTSIDE_PROOF` | high | Sicherheitslogik (Assert / Approve / Send / State-`.set`) innerhalb von `Provable.asProver(...)` oder einem `Provable.witness*`-Callback. Diese Callbacks laufen *außerhalb* des Circuits — ein bösartiger Prover kann sie löschen und dennoch einen verifizierenden Proof erzeugen. |
| `O1JS_APPROVE_WITHOUT_BINDING` | medium | Eine `@method` ruft `approve` / `approveAccountUpdate` / `approveBase` auf, ohne `balanceChange` / `publicKey` zu lesen und ohne `assertCanMint` / `assertCanBurn` / eine `forEachUpdate`-Erhaltungsprüfung — der Mina FlawedTokenContract-Archetyp. |
| `O1JS_VACUOUS_ASSERT` | high / medium | Ein Assert, das konstruktionsbedingt erfüllt ist: `x.assertEquals(x)`, `x.equals(x).assertTrue()` oder `Bool(true).assertTrue()`. HIGH für Selbstvergleiche (fast immer ein Tippfehler); MEDIUM für konstante Bool-Asserts. |
| `O1JS_CONDITIONAL_ASSERT` | medium | Ein Assert innerhalb von `if <flag> { ... }`, wobei `<flag>` ein prover-kontrolliertes `@method`-`Bool` ist (oder eine lokale Variable aus `.toBoolean()`). Ein JS-Bedingung beschränkt den Circuit nicht so, wie es `Provable.if` tut. Inline-Vergleiche bleiben aus Präzisionsgründen ungemeldet. |
| `O1JS_GUARDED_INVERSE` | medium | Ein `.div()` / `.inv()` / `.sqrt()` innerhalb eines `Provable.if`-Zweigs, geschützt durch eine Bedingung auf genau den Wert, bei dem es fehlschlägt. Beide Zweige werden in-circuit ausgewertet, und diese Aufrufe sichern bedingungslos zu, dass die Inverse oder Wurzel existiert, sodass der Guard die Zusicherung nicht überspringt — der Circuit ist für genau die Eingabe unerfüllbar, für die der Guard geschrieben wurde, und die Methode kann dafür nie bewiesen werden. Gemeldet von Veridise als `V-O1J-VUL-060`. Berechnen Sie zuerst einen sicheren Divisor (`Provable.if(isZero, Field(1), d)`) und wählen Sie das Ergebnis danach aus. **Bleibt still, wenn** der Guard nichts über den Divisor aussagt, sodass ein unabhängiges `Provable.if` um eine sichere Division nicht markiert wird. |
| `O1JS_PRECONDITION_OVERWRITTEN` | medium | Zwei oder mehr `requireEquals` / `requireBetween` / `requireNothing`-Aufrufe auf derselben Eigenschaft in einer Methode mit unterschiedlichen Argumenten. Vorbedingungen werden auf dem AccountUpdate *gesetzt* statt akkumuliert, sodass jeder Aufruf den vorherigen überschreibt und nur der letzte durchgesetzt wird — anders als In-Circuit-Zusicherungen, die sich zusammensetzen. `a.requireEquals(b)` dann `a.requireEquals(c)` impliziert `a === c`, nicht `a === b`. Gemeldet von Veridise als `V-O1J-VUL-012`. **Bleibt still, wenn** die Argumente identisch sind (idempotent, nichts geht verloren), bei `getAndRequireEquals()` (eine andere Methode, sodass wiederholte State-Reads in Ordnung sind) und wenn die Aufrufe in sich gegenseitig ausschließenden JS-Zweigen liegen, die zur Circuit-Build-Zeit aufgelöst werden. Diese letzte Ausnahme kann ein echtes Overwrite verbergen, das einen unabhängigen `if`/`else` überspannt. |
| `O1JS_STATE_READ_AFTER_WRITE` | medium | Ein `@state`-Feld wird gelesen (`get()` / `getAndRequireEquals()`), nachdem ein `set(...)` auf demselben Feld in derselben Methode abgeschlossen ist. `set()` zeichnet die Änderung auf dem AccountUpdate auf, schreibt aber nicht durch zu `get()`, sodass das Lesen noch den Wert von vor dem Schreiben beobachtet und jede darauf aufgebaute Arithmetik still um dieses Schreiben daneben liegt. Gemeldet von Veridise als `V-O1J-VUL-030`. Behalten Sie den neuen Wert in einer lokalen Variable, anstatt den State zurückzulesen. **Bleibt still, wenn** das Lesen innerhalb der eigenen Argumente des Schreibens verschachtelt ist (das Read-Modify-Write-Idiom `this.x.set(this.x.getAndRequireEquals().add(1))`, das korrekt ist), und wenn Schreiben und Lesen in sich gegenseitig ausschließenden JS-Zweigen liegen. Auf eine einzelne Methode beschränkt — der Cross-Method-Caching-Fall, den Veridise ebenfalls beschreibt, benötigt Call-Graph-Wissen, das diese Regel nicht hat. |
<!-- END GENERATED O1JS RULE TABLE -->

### False-Positive-Guards (o1js)

Der Analyzer ist darauf ausgelegt, bei korrektem Code still zu bleiben:

- **Signatur-gegatete Methoden werden übersprungen.** Eine `@method`, die
  `this.requireSignature()` (oder `getAndRequireSignature`, `AccountUpdate.createSigned`,
  `Signature.verify`) aufruft, ist owner/admin-gegatet — ihre Argumente werden vom Schlüssel-
  Inhaber gewählt, nicht von einem beliebigen Prover — sodass ihre Witnesses nicht markiert werden. Dies ist das
  o1js-Äquivalent zu `onlyOwner`.
- **State-gebundene Witnesses werden übersprungen.** Ein Argument, das als gleich zu (oder
  beschränkt durch einen Ordnungsvergleich gegen) einen `getAndRequireEquals()`-abgeleiteten
  Wert zugesichert wird, ist solide und wird nicht gemeldet. Dies deckt sowohl die direkte Form ab —
  `amount.assertLessThanOrEqual(bal)` — als auch die verkettete Form
  `amount.lessThanOrEqual(bal).assertTrue()`. Bindung, die in einem
  undekorierten Helper derselben Klasse (`this.verifyX(arg)`) liegt, wird ebenfalls erkannt,
  einschließlich durch eine Kette solcher Helper.
- **Verifizierte Proofs werden übersprungen.** Ein `Proof` / `SelfProof` / `DynamicProof` /
  `*Proof`-typisiertes Argument, auf dem `.verify()` aufgerufen wird, ist durch den
  verifizierten Circuit beschränkt — Witness-Befunde darauf (und auf sein `publicOutput` /
  `publicInput`) werden unterdrückt. Ein `.verifyIf(flag)` wird nur angerechnet, wenn die
  Bedingung kein unbeschränktes Methodenargument ist oder selbst zugesichert wird. Dasselbe gilt für den kanonischen OffchainState-Wrapper
  `this.offchainState.settle(proof)` (das Framework verifiziert innerhalb von `settle`).
  Ein handgeschriebenes `.settle(proof)` wird
  **nicht** als verifizierend angenommen. Der umgekehrte Fall (proof-typisiertes Argument nie verifiziert
  und nicht OffchainState-gesettlet) wird als `O1JS_UNVERIFIED_PROOF` gemeldet.
- **Zugesicherte / verwendete Bools werden übersprungen.** Ein Prädikat, das mit
  `.assertTrue()` / `.assertFalse()` verkettet, in `Provable.if(...)` verschachtelt oder
  einer lokalen Variable zugewiesen wird, die später referenziert wird, wird nicht als
  `O1JS_UNASSERTED_BOOL` gemeldet.
- **Authentifizierte Sender werden übersprungen.** `this.sender.getUnconstrained()`
  löst nicht aus, wenn dieselbe `@method` auch
  `this.sender.getAndRequireSignature()` aufruft, oder wenn dieser gewitness-te Wert
  an `AccountUpdate.createSigned(...)` übergeben / über `.requireSignature()` auf einem daraus erstellten AccountUpdate authentifiziert wird (Argument-
  identität erforderlich).
- Kommentare und String-Literale werden vor der Analyse entfernt, sodass ein `assert`
  innerhalb eines Strings kein falsches Ergebnis erzeugen kann.

## Was es erkennt (Noir)

Dieselbe Soundness-Idee — unterbeschränkte Witnesses — gilt für
[Noir](https://noir-lang.org) (`.nr`)-Circuits. Richten Sie den Scanner auf `.nr`-
Dateien (oder verwenden Sie `--lang noir`), und er analysiert sie mit dem Noir-Regelsatz.
Derselbe lexikalische, abhängigkeitsfreie Ansatz. Kalibriert gegen aztec-nr-Oracle- /
`unsafe`-Idiome — siehe [`docs/noir_calibration.md`](https://github.com/auditinfra-io/o1js-scan/blob/main/docs/noir_calibration.md).

<!-- BEGIN GENERATED NOIR RULE TABLE -->
| Regel | Schwere | Was sie bedeutet |
|------|----------|---------------|
| `NOIR_UNCONSTRAINED_WITNESS` | high | Ein Wert, der aus einem `unsafe { ... }`-Block gebunden wird — das Ergebnis einer `unconstrained fn` (Oracle- / Brillig-Hinweis) —, der nie durch ein `assert` / `assert_eq` (oder einen bestätigenden Helper / Merkle-Check) neu beschränkt wird. Der Hinweis läuft **außerhalb** des Circuits. Analogon zu `O1JS_UNCONSTRAINED_PROVABLE_WITNESS`. |
| `NOIR_UNCONSTRAINED_INPUT` | medium | Ein privater (Witness-)Input von `fn main`, der in **kein** `assert` / `assert_eq` fließt und **nicht** Teil des öffentlichen Outputs ist. Analogon zu `O1JS_UNCONSTRAINED_WITNESS`. |
| `NOIR_UNCONSTRAINED_PUBLIC_INPUT` | medium | Ein **öffentlicher** Input von `fn main`, der keine Beschränkung und keinen Output erreicht — der Circuit liest ihn nie. Das *Dual* der Private-Witness-Regel: Der Verifier liefert den Wert und glaubt, die Aussage handelt von ihm, während der Circuit ihn ignoriert (z. B. ein `merkle_root: pub Field`, das nie geprüft wird, sodass Mitgliedschaft nie tatsächlich bewiesen wurde). MEDIUM, weil ein absichtlich ungenutzter öffentlicher Input auch ein legitimes Idiom ist, um einen Proof an einen Kontext (Nonce / Chain-ID / Empfänger) zu binden, was lexikalisch nicht unterscheidbar ist — daher gatet es CI nicht beim Standard `--fail-on high`. |
| `NOIR_UNCHECKED_CAST` | medium | Ein prover-kontrollierter Wert, der auf einen schmalen unsigned Typ (`as u8`/`u16`/`u32`) gecastet wird, mit **keiner** Range-Zusicherung. Analogon zu o1js `MissingRangeCheck`. |
| `NOIR_UNCONSTRAINED_ARRAY_INDEX` | medium | Ein prover-kontrollierter Wert, der als Array-Index (`arr[i]`) verwendet wird, mit **keiner** Prüfung jeglicher Art darauf. Noirs implizite Bounds-Prüfung stellt nur fest, dass der Index *im Bereich* liegt — nicht, dass er der *korrekte* Index ist —, sodass der Prover frei bleibt, jedes Element auszuwählen und dennoch einen verifizierenden Proof zu erzeugen. Dies ist der Selector-Freedom-Bug hinter Merkle-Pfadpositionen, Note-Auswahl und Allow-List-Mitgliedschaft. Unterdrückt, wenn der Index range-beschränkt, durch eine Gleichheit gepinnt, vor einem Cast beschränkt (`index.assert_max_bit_size::<8>(); let i = index as u32;`) oder wenn der zurückgelesene Wert selbst durch ein `assert_eq` gepinnt ist. |
| `NOIR_UNASSERTED_BOOL` | high / medium | Ein Vergleich, dessen `bool`-Ergebnis **verworfen** wird. Analogon zu o1js `O1JS_UNASSERTED_BOOL`. |
| `NOIR_CONDITIONAL_ASSERT` | medium | Ein `assert` innerhalb von `if <flag> { ... }`, wobei `<flag>` ein prover-kontrolliertes bloßes `bool` oder eine lokale Variable aus prover-kontrollierten Werten ist. Eine Beschränkung innerhalb eines Conditionals gilt nur, wenn die Bedingung wahr ist, sodass ein prover-gewählter Zweig die Prüfung überspringen kann. Inline-Vergleiche (`if x != 0`) werden aus Präzisionsgründen in Ruhe gelassen; das Zuweisen des Guards an eine lokale Variable (`let gate = x != 0; if gate`) wird gemeldet, es sei denn, `gate` wird selbst zugesichert. |
| `NOIR_CONDITIONAL_CONSTRAIN` | medium | Ein `constrain_*` / `confirm_*` / `verify_*`-Aufruf nur unter einem prover-kontrollierten `if`, während ein `unsafe`-Hinweis noch den Output erreicht. |
| `NOIR_UNUSED_CHECK_RESULT` | high / medium | Ein `check_*` / `confirm_*` / `verify_*` / `constrain_*`-Ergebnis wird verworfen (bloßer Aufruf) oder zugewiesen und nie zugesichert — die Prüfung bindet den Circuit nicht. |
| `NOIR_VACUOUS_CONSTRAINT` | high / medium | Eine Beschränkung, die konstruktionsbedingt erfüllt ist: ein Selbstvergleich (`assert(x == x)`, `assert_eq(x, x)`, `x >= x`) oder eine konstante Bedingung (`assert(true)`). Sie fügt keine Einschränkung hinzu, aber die Zeile *liest sich* wie eine Prüfung — was sie gefährlicher macht als eine fehlende Beschränkung, weil die Überprüfung dort aufhört. HIGH für einen Selbstvergleich (fast immer ein Tippfehler für eine echte Prüfung: `assert(computed == expected)` falsch getippt als `assert(expected == expected)`); MEDIUM für eine Konstante, die häufiger ein Platzhalter ist. `x != x` wird **nicht** markiert — das ist unerfüllbar, ein Liveness-Bug statt eines stillen Soundness-Lochs. |
| `NOIR_UNSAFE_MISSING_SAFETY` | low | Ein `unsafe { ... }`-Block ohne angrenzenden `// Safety:`-Kommentar. Informativ; lässt CI beim Standard `--fail-on high` nicht fehlschlagen. |
<!-- END GENERATED NOIR RULE TABLE -->

### False-Positive-Guards (Noir)

- **Assert / Let-Hop / Same-File-Confirm-Helper** binden `unsafe`-Hinweise.
- **Call-Site-Namen** `constrain_*` / `confirm_*` / `verify_*` /
  `check_(non_)membership*` / `public_data_storage_read` rechnen Argumente an (mit
  Unused-Result-Erkennung für verworfene Prüfungen).
- **Dokumentiert absichtlich unbeschränkt** (erfordert angrenzendes `// Safety:`):
  `random()`, `avm::…` und Kernel/Rollup/Discovery-Deferred-Formulierungen.
- **Tuple-`let` + zugesicherte Flags** binden Merkle-Witnesses, die in Membership-Prüfungen übergeben werden.

Beispiel:```console
$ noir-scan examples/noir_unconstrained.nr --include-examples
HIGH     NOIR_UNCONSTRAINED_WITNESS         noir_unconstrained.nr:16  fn=main  Unconstrained `unsafe` result `inv` in `main`
LOW      NOIR_UNSAFE_MISSING_SAFETY         noir_unconstrained.nr:16  fn=  `unsafe` block without a `// Safety:` comment
noir-scan: 2 finding(s) [1 high, 1 low] in 1 of 1 file(s) — fails (--fail-on high)

$ noir-scan examples/noir_constrained.nr --include-examples
noir-scan: no findings in 1 o1js or Noir file(s) — passes (--fail-on high)

Wie beim o1js-Beispiel oben ist --include-examples nur deshalb erforderlich, weil diese Demo-Dateien unter examples/ liegen.

Bekannte Einschränkungen

Der Analyzer ist ein abhängigkeitsfreies lexikalisches Frontend plus eine leichtgewichtige semantische Schicht, die Alias-Verfolgung und interprozedurale Propagation durch Hilfsfunktionen derselben Klasse durchführt. Er ist kein TypeScript-Compiler-Frontend, kein Type-Checker und keine Ganzprogramm-Datenfluss-Engine, und es gibt keine SMT- oder Formalbeweis-Schicht in diesem Scanner. Behalten Sie diese blinden Flecken beim Triage im Hinterkopf — sie sind für dieses abhängigkeitsfreie Design bekannt und beabsichtigt, keine Bugs:

  • Nur einfache Aliase werden verfolgt. Die Witness-Verfolgung folgt einfachen Aliasen innerhalb derselben Methode wie const q = qty, aber nicht abgeleiteten Ausdrücken oder Destrukturierung: ```ts const q = qty; this.send({ to: dest, amount: q }); // followed const q = qty.add(1); this.send({ to: dest, amount: q }); // not followed const slot = this.root; slot.get(); // missing precondition missed

    root@kitploit:~
  • Cross-Method-Bindung deckt nur Same-Class-Helper-Ketten ab. Ein undekorierter Same-Class-Helper, der als this.verifyX(arg) aufgerufen wird, kann ein Argument des Aufrufers state-binden, und seit 0.19.0 werden Ketten davon (@method → Helper A → Helper B) bis zu einem Fixpunkt verfolgt. Der Helper→Helper-Schritt bildet nur eine bloße Parameterreferenz ab, daher wird helperA(x.add(1)) nicht propagiert. Freie und importierte Funktionen werden weiterhin nicht verfolgt, und lokale Variablen-Aliasing des Helper-Arguments bleibt eine dokumentierte Einschränkung.

  • Unasserted-Bool-Erkennung ist statement-förmig. Tier A markiert nur bloße Expression-Statements, deren äußerster Aufruf ein Bool-Prädikat ist, an das nichts angehängt ist. Prädikate, die in Provable.if(...) verschachtelt oder zugewiesen und später verwendet werden, werden nicht markiert. Komplexe Kontrollfluss-Verwendungen eines Bool-Lokals können weiterhin übersehen werden, wenn der Name nie referenziert wird (Fehlermodus: Übersehen, kein falsch Positiver).

  • Signature-Gating ist methodenbezogen und substring-basiert. _method_is_signature_gated behandelt eine ganze @method als owner-gated, wenn sie ein Signatur-Idiom enthält, und erkennt einen Verifier nur, wenn der Receiver-Name wörtlich signature enthält — daher wird sig.verify(admin, msg) nicht als Gating erkannt, während eine unabhängige Signaturprüfung an anderer Stelle in einer großen Methode übermäßig unterdrücken kann. Es ist alles-oder-nichts pro Methode.

  • Sender-Authentifizierung ist namensbasiert und nur innerhalb derselben Methode. O1JS_UNCONSTRAINED_SENDER unterdrückt, wenn this.sender.getAndRequireSignature() oder AccountUpdate.createSigned(<that sender>) im selben @method-Body erscheint. Eine Signaturanforderung, die nur in einem Helper lebt (this.requireSenderSig() → getAndRequireSignature darin), wird nicht verfolgt — der Fehlermodus ist ein falsch Positiver bei korrektem Code, der das Idiom kapselt, kein übersehener echter Bug.

  • Noir Cross-Crate-Helper werden nur durch Namenskonvention erkannt (keine Nargo.toml / Import-Auflösung). Übersehen wird einem falsch Positiven vorgezogen.

Diese sind der Grund, warum Findings ein Ausgangspunkt für menschliche Überprüfung sind, nicht Beweise. Ein datenflussbewusster Rewrite liegt bewusst außerhalb des Umfangs des lexikalischen Analysators.

Wo dieses Tool aufhört

o1js-scan ist bewusst ein flacher, dateiweiser lexikalischer Durchlauf — kein Parser, kein Datenfluss, kein Solver. Das macht es abhängigkeitsfrei und sofort in CI einsetzbar, und es ist zugleich eine harte Obergrenze. Die obigen Einschränkungen sind kein Backlog; sie sind Konsequenzen des Designs.

Daher lohnt es sich, explizit zu sagen, was dieses Tool Ihnen sagen kann und was nicht:

  • Ein sauberer Durchlauf ist kein Audit. Er bedeutet, dass keine Form, die dieser Scanner erkennt, übereingestimmt hat — nicht, dass der Circuit fehlerfrei ist. Bug-Klassen, die Datenfluss, Pfadsensitivität oder Constraint-Solving erfordern, sind für ein Tool dieser Form außer Reichweite, in jeder Sprache.
  • Ein Finding ist ein Hinweis, kein Urteil. Jede Regel hier ist eine Heuristik mit einer dokumentierten Klasse von falsch Positiven.

Dieser Kompromiss ist der richtige für einen Linter, den Sie bei jedem Commit ausführen. Wenn Sie an etwas arbeiten, wo der Unterschied zählt — ein Protokoll, das echten Wert hält, ein Circuit, bei dem Sie sich keinen Fehler leisten können —, behandeln Sie dies als den ersten Durchlauf und planen Sie eine echte Überprüfung ein.

Für eine tiefere Analyse wird der separate vollständige Scanner im audit-engine-cli-Repository gepflegt. o1js-scan ist der bewusst leichte, offene Scanner; das proprietäre Erkennungswissen und die Implementierungsdetails des vollständigen Scanners werden hier nicht reproduziert. Für Zugang oder eine vollständigere Circuit-Überprüfung wenden Sie sich an: [email protected].

Datenschutz und privater Code

Die installierte CLI analysiert Dateien lokal. Sie hat keine Telemetrie, keinen Netzwerk- Client, kein Konto und keinen Upload-Schritt, und ihre Python-Laufzeit hat keine Drittanbieter- Abhängigkeiten. Das Ausführen von o1js-scan path/to/private-repo sendet den Quellcode oder Findings nirgendwohin.

Wie Compiler-Logs können Scanner-Ausgaben Pfade, Identifikatoren und Quellcode- Fragmente enthalten. SARIF identifiziert zudem exakte Repository-Positionen, und die GitHub- Action lädt es zum GitHub-Code-Scanning hoch. Verwenden Sie dieselben Repository- und CI-Zugriffs- kontrollen, die Sie bereits für den gescannten Quellcode verwenden.

Möchten Sie einen nützlichen Falsch-Positiv- oder Übersehen-Bericht beitragen, ohne eine Anwendung zu teilen? Reproduzieren Sie die Syntax mit erfundenen Namen und Konstanten, entfernen Sie Geschäftslogik Statement für Statement, und verifizieren Sie, dass das synthetische Snippet weiterhin dieselbe Regel auslöst, bevor Sie es posten. Der datenschutzsichere Beitragsleitfaden enthält eine konkrete Checkliste und mehrere Möglichkeiten, der o1js-Community zu helfen, ohne einen privaten Circuit offenzulegen.

Diese Grenze hindert den offenen Scanner nicht daran, besser zu werden. Öffentliche o1js-Dokumentation und -Repositories können neue Regeln und Kompatibilitäts- Fixtures unterstützen; synthetische Beispiele können falsch Positive und übersehene Constraints testen; und Parser-Resilienz, Diagnostik, SARIF, Performance, Packaging und Kalibrierung können alle verbessert werden, ohne eine private Audit-Technik oder Client-Code zu veröffentlichen. Der offene Scanner sollte unabhängig erklärbare Aussagen machen; private Forschung kann im separaten Audit-Engine verbleiben.

Post-Quanten-Überprüfung

Quantenrisiko hängt mit Circuit-Sicherheit zusammen, ist aber keine Regel für fehlende Constraints. o1js-scan bestimmt nicht, ob eine Signatur, ein Hash, ein Commitment, das Kimchi-Proof-System oder Mina selbst ein Post-Quanten-Sicherheitsziel erfüllt. Diese Antworten hängen vom konkreten Primitiv und den Parametern, Plattformannahmen, der erforderlichen Lebensdauer des Deployments und seinem Migrationsplan ab — nicht bloß von einem TypeScript-Identifikator, den ein lexikalischer Scanner sehen kann.

Inspiriert von O(1) Labs' Qubit or Not Qubit, macht der Post-Quanten-Überprüfungsleitfaden diese Grenze zu einem o1js-spezifischen Inventar und einer Krypto-Agilitäts-Checkliste. Verwenden Sie ihn zusammen mit diesem Scanner, statt einen sauberen Scan als Post-Quanten- Bewertung zu interpretieren.

Kompatibilität

Funktioniert mit o1js 1.x, 2.x und 3.x, einschließlich des Mesa-Hardforks, auf den o1js 3.0.0 abzielt. o1js-scan analysiert TypeScript-Quellcode als Text und hat keine Laufzeit- Abhängigkeit von o1js — nichts ist versionsgebunden. Es setzt auf die moderne require*-Vorbedingungs-API (getAndRequireEquals, requireEquals, requireSignature, getAndRequireSignature), die @method / @method() / @method.returns(...)-Dekoratoren, annotierte @state- Felder, this.send({...}), Low-Level-AccountUpdate.balance.subInPlace(...)- Transfers und Permissions.*. Die etablierten Formen bleiben über die Grenzen 1.x → 2.x → 3.x hinweg kompatibel, während der Scanner auch die neu dokumentierten Dekorator- und Low-Level-Transfer-Varianten akzeptiert. Das 2.x-Owner-Auth-Idiom this.sender.getAndRequireSignature() wird als Signature-Gating erkannt. (Legacy-assertEquals-Vorbedingungen werden weiterhin akzeptiert, sodass älterer Code ebenfalls nicht bricht.)

Mesas Breaking Changes sind alle auf Laufzeit- und Protokollebene — die Entfernung von Transaction.setFeePerSnarkCost() und den TransactionCost.*-Konstanten, die neue VerificationKey.toJSON()-Form, neu generierte Verification Keys, MAX_ZKAPP_STATE_FIELDS von 8 auf 32 erhöht und das mina-signer-v4- Transaktionsformat. Keine davon benennt eine API um, auf die dieser Scanner matcht, daher hat sich keine Regel für Mesa geändert, und das ist verifiziert statt behauptet. scripts/o1js_release_matrix.sh scannt zwei gepinnte o1js-Releases, die die Protokollgrenze überspannen — 2.15.0 (9620ef08, das letzte 2.x-Release) und 3.0.0 (cc18a919, Mesa) — und vergleicht jedes Finding mit tests/fixtures/o1js_release_matrix.json:

ReleaseFindingsHIGHMEDIUMLOWDateien
o1js 2.15.036826218
o1js 3.0.0 (Mesa)39829219

33 Findings sind über die Grenze hinweg identisch, keine gingen verloren, und alle drei neuen befinden sich in src/examples/zkapps/big-state-zkapp.ts — das 32-State-Field- Beispiel, das nur existiert, weil Mesa MAX_ZKAPP_STATE_FIELDS erhöht hat. Dieses Delta ist durch einen Test gepinnt, sodass es nicht stillschweigend driften kann. Die Matrix läuft bei jedem CI-Build; der wöchentliche o1js-upstream-canary-Job verfolgt o1js zusätzlich am HEAD, vor jedem Release.

Äquivalente Constraint-Schreibweisen werden für die Analyse normalisiert: Instanz- assertEquals(...), statisches Provable.assertEqual(Type, ...) und equals(...).assertTrue()-Gleichheitsketten binden alle dieselben Operanden. Die Methoden- Extraktion ist klammerbalanciert nach längenerhaltender Kommentar- und String- Maskierung und akzeptiert mehrzeilige Dekoratoren, verschachtelte callback-förmige Parameter- Typen, TypeScript-Zugriffsmodifikatoren und mehrzeilige Identitäts-Aliase (einschließlich parenthesierter und as Type-Formen).

Die Noir-Analyse zielt auf Noir-Syntax ab, die von Aztec- / nargo-Projekten verwendet wird (.nr); sie ruft nargo nicht auf und kompiliert keine Circuits.

Wie es funktioniert

Es ist ein lexikalischer Analysator, kein vollständiger TypeScript- oder Noir-Parser — o1js- und Noir- Quellen sind klammerbegrenzt und regex-tauglich, und die Ausgabe ist dafür gedacht, von einem Menschen triagiert zu werden. Das hält es abhängigkeitsfrei und sofort in CI ausführbar. Findings sind ein Ausgangspunkt für die Überprüfung, keine Beweise.

Roadmap / Mitwirken

Beiträge willkommen — neue Regelfamilien, mehr FP-Guards und realweltliche Kalibrierungs-Archetypen sind alle wertvoll. Siehe CONTRIBUTING.md.

Für einen vorgeschlagenen Weg von der Community-Packages-Listung zu einer Advisory-Prüfung im o1js-Repository siehe den versandfertigen o1js-Upstream-Integrationsvorschlag.

Führen Sie die Tests und den Linter aus mit:```bash pip install -e ".[dev]" pytest # unit tests + Noir/o1js corpus ruff check . # lint npm run format:check # prettier, npm wrapper only

root@kitploit:~
## Lizenz

Apache-2.0. Siehe [`LICENSE`](https://github.com/auditinfra-io/o1js-scan/blob/main/LICENSE).
Tool herunterladen