Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
o1js-scan — محلل ثابت بدون تبعيات لأخطاء سلامة دوائر zk في تطبيقات o1js/Mina zkApps ودوائر Noir | Kitploit
أدوات/GitHubGitHub/auditinfra-io/o1js-scan
أدوات دفاعيةالتحليل الثابتماسحات الثغرات الأمنيةتحليل الشفرة الثابت (SAST)تحليل الثغرات الأمنيةتحليل الكودالتشفيرDevSecOps
GitHubauditinfra-io/o1js-scan

o1js-scan

محلل ثابت بدون تبعيات لأخطاء سلامة دوائر zk في تطبيقات o1js/Mina zkApps ودوائر Noir

عرض المستودع
210منذ 4 أياملم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة
الموقع الإلكتروني

o1js-scan

CI Python License PyPI npm

حزمة مجتمعية: o1js-scan مُدرجة في الدليل الرسمي o1js Community Packages.

الأحدث: 0.20.0 — يقوم المحلل الآن بقراءة العقود التي extends TokenContract. حتى هذا الإصدار كان فحص العقود يطابق SmartContract وحده، لذا كل رمز قابل للاستبدال ومجموعة NFT ومجمّع AMM في المنظومة كان يُفحص بنتيجة "لا توجد اكتشافات". إذا فحصت عقد رمز قبل 0.20.0، فأعد فحصه. راجع CHANGELOG.

محلل ثابت سريع وخالٍ من التبعيات لاكتشاف أخطاء سلامة دوائر zk في:

  • o1js / Mina zkApps (TypeScript .ts / .js) — دوائر Kimchi من أجسام @method
  • Noir (.nr) — لغة ZK DSL الخاصة بـ Aztec الشبيهة بـ Rust (بما في ذلك الأنماط المشابهة لـ aztec-nr)

عادةً لا تكون الأخطاء الحرجة أمنيًا في نظام الإثبات — بل في قيود التطبيق نفسه: الشهود الذين يتحكم بهم المُثبِت لكن الدائرة لا تربطهم أبدًا. o1js-scan هو ماسح الإشارات غير المُقيَّدة لأبناء عمومة Circom في منظومتي Mina و 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:~
### مثال

بالنظر إلى خزنة يكون فيها مبلغ `withdraw` شاهدًا يتحكم فيه المُثبِت ولا
يُربط أبدًا بحالة السلسلة:```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 مطلوب هنا فقط لأن ملف العرض التوضيحي يقع تحت examples/، وهو ما يصنّفه مصنّف المسار على أنه أقل خطورة افتراضيًا حتى لا يتسبب الكود النموذجي الخاص بالمستودع في فشل عملية البناء. نفس العقد في src/ يُبلّغ عن HIGH بدون أي علامة.

اكتشاف HIGH هو الثغرة القابلة للسحب. العقد المُصلَّح (examples/safe_vault.ts) يُسقطه ويخرج بـ 0، محتفظًا فقط بالمعلوماتي LOW على المستلم الذي يختاره المُثبِت:```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:~
راجع [`examples/`](https://github.com/auditinfra-io/o1js-scan/blob/main/examples) للحصول على أزواج o1js وNoir القابلة للاستغلال/المصححة.

## المحتويات

- [التثبيت](#install)
- [الاستخدام](#usage) · [تجاهل نتيجة](#suppressing-a-reviewed-finding)
- [إجراء GitHub](#github-action)
- [ما يكتشفه — o1js](#what-it-detects-o1js) · [Noir](#what-it-detects-noir)
- [القيود المعروفة](#known-limitations) · [أين تتوقف هذه الأداة](#where-this-tool-stops)
- [الخصوصية والتعليمات البرمجية الخاصة](#privacy-and-private-code)
- [مراجعة ما بعد الكم](#post-quantum-review)
- [التوافق](#compatibility) · [كيف يعمل](#how-it-works)
- [المساهمة](#roadmap--contributing)

## التثبيت```bash
pip install o1js-scan

للتثبيت المعزول لواجهة سطر الأوامر العامة، استخدم pipx:```bash pipx install o1js-scan

root@kitploit:~
بالنسبة لمستودعات تطبيقات Noir أو Aztec أو o1js القائمة على Node/npm، قم بتثبيت غلاف npm:```bash
npm install -D o1js-scan
npx noir-scan . --lang noir --fail-on high

حزمة npm هي غلاف رفيع حول نفس محلل Python وتتطلب Python 3.8+ على PATH (python3 أو python). اضبط O1JS_SCAN_PYTHON لاختيار مفسر محدد.

أو من المصدر:```bash git clone https://github.com/auditinfra-io/o1js-scan cd o1js-scan pip install -e .

root@kitploit:~
لا توجد تبعيات Python من طرف ثالث. Python 3.8+. يتم تثبيت سكربت الطرفية `noir-scan`
إلى جانب `o1js-scan` (نفس نقطة الدخول)، بما في ذلك عبر غلاف npm.

## الاستخدام```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

يُعاد رمز الخروج 1 عند وجود نتيجة عند مستوى --fail-on أو أعلى منه (الافتراضي high) و0 بخلاف ذلك — لذا يمكنك إدراجه مباشرة في CI. مع الإعداد الافتراضي، لا تؤدي نتيجة منخفضة/متوسطة (بما في ذلك قاعدة المستلم الإعلامية أدناه) إلى إفشال البناء؛ استخدم --fail-on none للإبلاغ فقط، أو --strict (اختصار لـ --fail-on medium) لفرض بوابة أكثر صرامة مع الاستمرار في التعامل مع النتائج منخفضة الخطورة كاستشارية. الخياران متعارضان فلا يمكن أن يكون إعداد CI غامضًا. مسار فحص مفقود يخرج بـ 2 مع خطأ على stderr، فلا يمكن لخطأ مطبعي أن يمر عبر CI بصمت كتشغيل نظيف. كل تشغيل يطبع ملخصًا من سطر واحد (أعداد حسب الخطورة وحكم البوابة) إلى stderr.

يُستثنى كود الاختبار افتراضيًا — في كلا الخلفيتين. تبني الاختبارات عمدًا قيمًا غير صالحة ومعاملات سيئة لإثبات أن التأكيدات ترفضها، لذا فإن وجود نتيجة هناك هو الغرض من الاختبار وليس خطأ في الدائرة. يُحتسب الملف ككود اختبار عندما:

  • يطابق اسمه *.test.ts / *.spec.ts (ومتغيرات .js/.jsx/.tsx/.mjs/.cjs)، أو *_test.nr / test_*.nr؛
  • يقع تحت دليل test/ أو tests/ أو __tests__/ أو spec/ أو __mocks__/؛
  • (Noir فقط، بناءً على المحتوى) تحمل الدالة سمة #[test] / ، أو تقع داخل كتلة / — محصورة بالكتلة، لذا فإن وحدة اختبار في أسفل ملف إنتاجي لا تُسكِت بقية الملف.

مرّر --include-tests للإبلاغ عنها.

يُخفَّض كود المثال، لا يُحذف. أي نتيجة في دليل examples/ أو example/، أو في ملف باسم *.eg.ts (وكذلك .nr وبقية امتدادات JS/TS)، تُخفَّض إلى LOW مع ملاحظة — لا تزال مُبلَّغًا عنها، لكنها لم تعد قادرة على إفشال البناء. كود المثال مبسَّط عمدًا، ووسم أمثلة إطار العمل نفسه كالثغرات هو ضجيج؛ لكنه يُنسخ إلى الإنتاج أكثر بكثير مما يُنسخ كود الاختبار، ولهذا يُخفَّض بدلًا من إخفائه. مرّر --include-examples للحفاظ على الخطورة الأصلية.

كلما انطبقت أي من السياستين، يطبع التشغيل سطرًا إلى stderr يوضح ذلك — مثلًا 6 file(s) skipped as test code, 1 finding(s) downgraded as examples — فلا يكون الفحص الهادئ هادئًا بصمت أبدًا. تظهر الأعداد أيضًا في SARIF تحت invocation.properties. لاحظ المقايضة: الكشف قائم على المسار فقط (لا تحليل لـ describe(/it()، لذا فإن دائرة إنتاجية مخزنة تحت tests/ سيتم تخطيها — وسطر stderr هو كيف تلاحظ ذلك.

الأدلة التي يتم تخطيها عند التنقل في شجرة: node_modules، target (nargo)، .git، dist، build، __pycache__، .venv، venv.

كتم نتيجة تمت مراجعتها

أسكِت نتيجة قمت بفرزها دون تخفيف البوابة، بتعليق مضمّن على — أو على السطر فوق — السطر المُعلَّم:```ts this.send({ to, amount }); // o1js-scan-disable-line O1JS_UNCONSTRAINED_WITNESS

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

root@kitploit:~
## المكونات الإضافية

### المكونات الإضافية الرسمية

- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/backslash-powered-scanner) - ماسح ضوئي احترافي للثغرات من نوع backslash powered scanner.
- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/active-scan-plus-plus) - ماسح ضوئي احترافي للثغرات من نوع active scan++.
- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/param-miner) - ماسح ضوئي احترافي للثغرات من نوع param miner.
- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/collaborator-everywhere) - ماسح ضوئي احترافي للثغرات من نوع collaborator everywhere.
- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/http-request-smuggler) - ماسح ضوئي احترافي للثغرات من نوع http request smuggler.
- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/turbo-intruder) - ماسح ضوئي احترافي للثغرات من نوع turbo intruder.
- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/logger-plus-plus) - ماسح ضوئي احترافي للثغرات من نوع logger++.
- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/authorize) - ماسح ضوئي احترافي للثغرات من نوع authorize.
- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/retire-js) - ماسح ضوئي احترافي للثغرات من نوع retire.js.
- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/software-vulnerability-scanner) - ماسح ضوئي احترافي للثغرات من نوع software vulnerability scanner.
- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/reflected-parameters) - ماسح ضوئي احترافي للثغرات من نوع reflected parameters.
- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/backslash-powered-scanner) - ماسح ضوئي احترافي للثغرات من نوع backslash powered scanner.
- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/active-scan-plus-plus) - ماسح ضوئي احترافي للثغرات من نوع active scan++.
- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/param-miner) - ماسح ضوئي احترافي للثغرات من نوع param miner.
- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/collaborator-everywhere) - ماسح ضوئي احترافي للثغرات من نوع collaborator everywhere.
- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/http-request-smuggler) - ماسح ضوئي احترافي للثغرات من نوع http request smuggler.
- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/turbo-intruder) - ماسح ضوئي احترافي للثغرات من نوع turbo intruder.
- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/logger-plus-plus) - ماسح ضوئي احترافي للثغرات من نوع logger++.
- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/authorize) - ماسح ضوئي احترافي للثغرات من نوع authorize.
- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/retire-js) - ماسح ضوئي احترافي للثغرات من نوع retire.js.
- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/software-vulnerability-scanner) - ماسح ضوئي احترافي للثغرات من نوع software vulnerability scanner.
- [**مكون Burp Suite الإضافي**](https://github.com/portswigger/reflected-parameters) - ماسح ضوئي احترافي للثغرات من نوع reflected parameters.```nr
let inv = unsafe { hint(x) };  // o1js-scan-disable-line NOIR_UNCONSTRAINED_WITNESS

اسرد معرّف قاعدة واحدًا أو أكثر لكبت تلك القواعد فقط؛ التوجيه المجرّد (بدون معرّفات) يكبت كل قاعدة على السطر الهدف.

كـمكتبة:```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

أضف الماسح الضوئي إلى CI في بضعة أسطر. تظهر النتائج كتعليقات توضيحية على فرق PR وك تنبيهات في علامة التبويب **Security → Code scanning** الخاصة بالمستودع.```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

وصفة CI الخاصة بـ Noir فقط

موصى بها لمشاريع Noir التي تريد تنبيهات فحص الكود وبوابة للأخطاء عالية الخطورة:```yaml

  • uses: auditinfra-io/[email protected] with: path: . lang: noir fail-on: high
root@kitploit:~
أو بدون الإجراء:```bash
pip install o1js-scan
noir-scan . --lang noir --fail-on high --sarif noir.sarif

pre-commit (اختياري)```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:~
المدخلات: `path` (افتراضي `.`)، `lang` (`auto`|`o1js`|`noir`، افتراضي `auto`)،
`version` (إصدار PyPI المراد تثبيته، افتراضي الأحدث)، `upload-sarif` (افتراضي
`true`)، `fail-on` (`critical`|`high`|`medium`|`low`|`none`، افتراضي `none`)،
`fail-on-findings` (مهمل، افتراضي `false`)، `include-tests` (افتراضي
`false`)، `include-examples` (افتراضي `false`). المخرجات: `sarif-file`. يتطلب رفع SARIF
صلاحية `security-events: write` وتمكين فحص الكود.

يُبنى التقرير والبوابة من مصفوفة وسائط واحدة، لذا ينطبق `include-tests`
و`include-examples` على كليهما — فملف SARIF الذي تقرؤه ورمز الخروج الذي
تعتمد عليه يصفان دائمًا نفس مجموعة المصدر. تعمل مرحلة إعداد التقرير عند
`--fail-on none` بحيث لا تحجب النتائج أبدًا رفع SARIF، لكن أي فشل تشغيلي
(مسار غير موجود، خطأ في استخدام CLI) لا يزال يُفشل الخطوة
بدلًا من الإبلاغ عنها كفحص نظيف.

يُحتفظ بـ `fail-on-findings: true` للتوافق ويُترجم إلى `fail-on: high`
عندما يُترك `fail-on` عند `none`؛ ويصدر تحذيرًا بالإهمال. يُفضَّل
`fail-on`، الذي يمكنه تقييد البوابة عند أي مستوى خطورة.

## ما يكتشفه (o1js)

### القواعد المدعومة في لمحة

<!-- BEGIN GENERATED RULE SUMMARY -->
| الواجهة الخلفية | القواعد | قادرة على high | قادرة على medium | قادرة على low |
|---------|------:|-------------:|---------------:|------------:|
| o1js | 18 | 11 | 12 | 2 |
| Noir | 11 | 4 | 9 | 1 |
| **الإجمالي** | **29** | **15** | **21** | **3** |
<!-- END GENERATED RULE SUMMARY -->

الأعداد هي معرّفات قواعد مميزة تدعمها كل واجهة خلفية. القاعدة التي تُسنِد
مستوى الخطورة وفقًا للسياق (على سبيل المثال، high لنقل قيمة و
medium لكتابة حالة) تظهر في أكثر من عمود خطورة، لذا فإن
أعمدة الخطورة لا تجمع عمدًا إلى إجمالي القواعد. لا توجد حاليًا
قواعد بخطورة critical أو info. الأوصاف الكاملة
وحراس الإيجابيات الكاذبة فيما يلي.

<!-- BEGIN GENERATED O1JS RULE TABLE -->
| القاعدة | الخطورة | ما تعنيه |
|------|----------|---------------|
| `O1JS_MISSING_STATE_PRECONDITION` | high | قراءة `this.x.get()` بدون `requireEquals(...)` / `getAndRequireEquals()` مطابقة. فـ `get()` المجرد لا يضيف **أي** شرط مسبق على الحساب، لذا لا يربط الإثبات `x` بقيمته على السلسلة — يمكن للمُثبِت استبدال أي قيمة. |
| `O1JS_UNCONSTRAINED_WITNESS` | high / medium | وسيط `@method` (شاهد خاص يتحكم فيه المُثبِت) يتدفق إلى **مبلغ** إرسال (`this.send(...)` أو `AccountUpdate.create*(...).send(...)` في نفس الدالة) أو إلى `.set(...)` للحالة و**لا** يُؤكَّد أبدًا. نظير مباشر لإشارة Circom غير مقيَّدة بشكل كافٍ. high عندما يصل إلى نقل قيمة. |
| `O1JS_UNCONSTRAINED_PROVABLE_WITNESS` | high / medium / low | متغير محلي من `Provable.witness(...)` يتدفق إلى تأثير إرسال/حالة **بدون** أي تأكيد داخل الدائرة. يُنفَّذ callback الشاهد *خارج* الدائرة (إنه مجرد تلميح للمُثبِت)، لذا تكون النتيجة قيمة جديدة يتحكم فيها المُثبِت — وهو مصدر الشاهد الآخر بجانب وسائط `@method`. يجب إعادة اشتقاقه وتأكيده (`x.assertEquals(<recomputed>)`) أو ربطه بالحالة. high على مبلغ إرسال (`this.send(...)` أو `AccountUpdate.create*` في نفس الدالة). |
| `O1JS_UNCONSTRAINED_RECIPIENT` | low | وسيط `@method` يُستخدم **فقط** كمستلم `to:` لعملية إرسال. هذا عادةً مقصود (المستخدم يحدد وجهة السحب الخاصة به) وهو إعلامي — لا يهم إلا إذا كان المقصود أن تكون الوجهة خزينة ثابتة أو عنوانًا مسجلًا في الحالة. **لا** يُفعِّل بوابة رمز الخروج في CI. |
| `O1JS_WITNESS_NOT_BOUND_TO_STATE` | medium | شاهد مقيَّد *بشكل تافه* فقط (مثل `> 0`، أو مقارن بثابت) قبل تأثير — ولا يُربط أبدًا بالحالة على السلسلة. تأكد من أن التنسيق خارج السلسلة يجعل هذا آمنًا، وإلا فإن الرصيد قابل للسحب حتى قيمته القائمة. |
| `O1JS_STALE_MERKLE_ROOT` | high | تعيد دالة حساب جذر Merkle من شاهد يقدمه المُثبِت (`computeRootAndKey` / `calculateRoot`) لكنها لا تربط **أيًا** من الجذور المعاد حسابها بالجذر الحالي على السلسلة. بدون `this.root.requireEquals(...)` / `assertEquals` مقابل الجذر الحي، يمكن للمُثبِت تمرير شاهد لشجرة مُلفَّقة أو قديمة — تزوير العضوية أو إعادة تشغيل حالة قديمة. قد يوجد الربط في دالة مساعدة غير مزخرفة في نفس الفئة (`this.verifyX(witness)`)؛ ويغطي انتشار الدوال المساعدة ذلك. |
| `O1JS_UNVERIFIED_PROOF` | high | وسيط `@method` من النوع `Proof<...>` / `SelfProof<...>` / `DynamicProof<...>` لا يُجرى عليه `.verify()` أبدًا قبل استخدام حقوله العامة. تمرير Proof لا يتحقق منه — بدون تحقق صريح يمكن للمُثبِت تقديم كائن إثبات عشوائي، وأي استخدام لـ `publicOutput` الخاص به يكون غير مقيَّد. يُفعَّل أيضًا عندما يكون `.verifyIf(flag)` مقيَّدًا بوسيط `@method` غير مقيَّد وتُقرأ الحقول العامة للإثبات، لأن المُثبِت يمكنه جعل الشرط خاطئًا. |
| `O1JS_UNASSERTED_BOOL` | high / medium | مُسند o1js (`equals` / `lessThanOrEqual` / …) يُعيد `Bool` ولا يضيف **أي** قيد ما لم تُؤكَّد النتيجة أو تُستخدم. HIGH عندما يكون الاستدعاء عبارة مجردة مُهمَلة؛ MEDIUM عندما يُسنَد إلى متغير محلي لا يُشار إليه مرة أخرى. |
| `O1JS_UNCONSTRAINED_SENDER` | high / medium | يُعيد `this.sender.getUnconstrained()` مرسل المعاملة دون إثباته. HIGH عندما تتدفق تلك القيمة (أو متغير محلي منها) إلى تأكيد / `.set` للحالة / `send` (فحص فارغ)؛ MEDIUM بخلاف ذلك. يُفضَّل `this.sender.getAndRequireSignature()`، أو الصيغة الموسَّعة `AccountUpdate.createSigned(sender)`. **يبقى صامتًا عندما** (1) تستدعي نفس `@method` أيضًا `this.sender.getAndRequireSignature()` في أي مكان (متطلب التوقيع على مستوى الدالة)، أو (2) تكون قيمة المرسل المشهودة هي الوسيط لـ `AccountUpdate.createSigned(...)` / `AccountUpdate.create(...).requireSignature()` على نفس المفتاح (مطلوب تطابق الوسيط — فـ `createSigned` على مفتاح مختلف لا يكتم). |
| `MissingRangeCheck` | high | يُستخدم `Field` خام (وليس `UInt64`/`UInt32` المفحوصين بالنطاق) كمبلغ تحويل. `Field` عنصر بمعامل p وغير محدود بالنطاق. |
| `O1JS_WEAK_PERMISSIONS` | high / medium | `editState` / `send` مضبوطان على `proofOrSignature()` أو `none()`، مما يسمح لمفتاح حساب zkApp بتجاوز الدائرة عبر التوقيع. يُشير أيضًا إلى `setVerificationKey` / `setPermissions` المتروكين عند `signature` / `proofOrSignature` / `none` (عجلات تدريب الترقية الموثقة في Mina)؛ HIGH عند دمجه مع `editState`/`send` ضعيف في نفس `permissions.set`. |
| `O1JS_LOGIC_OUTSIDE_PROOF` | high | منطق أمني (assert / approve / send / `.set` للحالة) داخل `Provable.asProver(...)` أو callback `Provable.witness*`. تُنفَّذ هذه الـ callbacks *خارج* الدائرة — يمكن لمُثبِت خبيث حذفها ولا يزال يُنتج إثباتًا يتحقق بنجاح. |
| `O1JS_APPROVE_WITHOUT_BINDING` | medium | تستدعي `@method` الدالة `approve` / `approveAccountUpdate` / `approveBase` دون قراءة `balanceChange` / `publicKey` ودون `assertCanMint` / `assertCanBurn` / فحص حفظ `forEachUpdate` — وهو النموذج الأصلي لـ Mina FlawedTokenContract. |
| `O1JS_VACUOUS_ASSERT` | high / medium | تأكيد مُحقَّق بالبناء: `x.assertEquals(x)`، `x.equals(x).assertTrue()`، أو `Bool(true).assertTrue()`. HIGH للمقارنات الذاتية (غالبًا خطأ مطبعي)؛ MEDIUM لتأكيدات Bool الثابتة. |
| `O1JS_CONDITIONAL_ASSERT` | medium | تأكيد داخل `if <flag> { ... }` حيث `<flag>` هو `Bool` من `@method` يتحكم فيه المُثبِت (أو متغير محلي من `.toBoolean()`). الشرط في JS لا يقيّد الدائرة كما يفعل `Provable.if`. تبقى المقارنات المضمَّنة غير مُبلَّغ عنها للدقة. |
| `O1JS_GUARDED_INVERSE` | medium | `.div()` / `.inv()` / `.sqrt()` داخل فرع `Provable.if`، محمي بشرط على القيمة نفسها التي يفشل عليها. يُقيَّم الفرعان داخل الدائرة وتؤكد هذه الاستدعاءات دون شرط وجود المعكوس أو الجذر، لذا لا يتخطى الحارس التأكيد — الدائرة غير قابلة للإرضاء بالضبط للمدخل الذي كُتب الحارس للتعامل معه، ولا يمكن إثبات الدالة له أبدًا. أبلغت عنه Veridise باسم `V-O1J-VUL-060`. احسب مقسومًا آمنًا أولًا (`Provable.if(isZero, Field(1), d)`) واختر النتيجة بعد ذلك. **يبقى صامتًا عندما** لا يقول الحارس شيئًا عن المقسوم، فلا يُشير إلى `Provable.if` غير ذي صلة حول قسمة آمنة. |
| `O1JS_PRECONDITION_OVERWRITTEN` | medium | استدعاءان أو أكثر لـ `requireEquals` / `requireBetween` / `requireNothing` على **نفس** الخاصية في دالة واحدة، بوسائط مختلفة. تُضبَط الشروط المسبقة على AccountUpdate بدلًا من تراكمها، لذا يستبدل كل استدعاء السابق ولا يُفرَض إلا الأخير — بخلاف التأكيدات داخل الدائرة التي تتكامل. `a.requireEquals(b)` ثم `a.requireEquals(c)` يعني `a === c`، وليس `a === b`. أبلغت عنه Veridise باسم `V-O1J-VUL-012`. **يبقى صامتًا عندما** تكون الوسائط متطابقة (لا شيء يُفقد)، وعند `getAndRequireEquals()` (دالة مختلفة، لذا تكرار قراءات الحالة مقبول)، وعندما تكون الاستدعاءات في فروع JS متنافية، والتي تُحل وقت بناء الدائرة. قد يخفي هذا الإعفاء الأخير استبدالًا حقيقيًا يمتد عبر `if`/`else` غير ذي صلة. |
| `O1JS_STATE_READ_AFTER_WRITE` | medium | يُقرأ حقل `@state` (`get()` / `getAndRequireEquals()`) بعد اكتمال `set(...)` على نفس الحقل، في نفس الدالة. يسجل `set()` التغيير على AccountUpdate لكنه لا يكتب عبره إلى `get()`، لذا لا تزال القراءة ترى القيمة من قبل الكتابة وأي حساب مبني عليها يكون خاطئًا بصمت بمقدار تلك الكتابة. أبلغت عنه Veridise باسم `V-O1J-VUL-030`. احتفظ بالقيمة الجديدة في متغير محلي بدلًا من قراءة الحالة مرة أخرى. **يبقى صامتًا عندما** تكون القراءة متداخلة داخل وسائط الكتابة نفسها (صيغة القراءة-التعديل-الكتابة `this.x.set(this.x.getAndRequireEquals().add(1))`، وهي صحيحة)، وعندما تكون الكتابة والقراءة في فروع JS متنافية. محصور في دالة واحدة — حالة التخزين المؤقت عبر الدوال التي تصفها Veridise أيضًا تحتاج معرفة برسم الاستدعاءات لا تملكها هذه القاعدة. |
<!-- END GENERATED O1JS RULE TABLE -->

### حراس الإيجابيات الكاذبة (o1js)

صُمم المحلل ليبقى صامتًا على الكود الصحيح:

- **تُتخطى الدوال المحمية بالتوقيع.** دالة `@method` تستدعي
  `this.requireSignature()` (أو `getAndRequireSignature`، `AccountUpdate.createSigned`،
  `Signature.verify`) محمية بالمالك/المشرف — وسائطها يختارها حامل
  المفتاح، وليس مُثبِتًا عشوائيًا — لذا لا تُشير شهودها. هذا هو
  مكافئ o1js لـ `onlyOwner`.
- **تُتخطى الشهود المرتبطون بالحالة.** وسيط مؤكَّد مساوٍ لـ (أو
  محدود بمقارنة ترتيبية مقابل) قيمة مشتقة من `getAndRequireEquals()`
  سليم ولن يُبلَّغ عنه. يغطي هذا الصيغة المباشرة —
  `amount.assertLessThanOrEqual(bal)` — والصيغة المتسلسلة
  `amount.lessThanOrEqual(bal).assertTrue()`. الربط الموجود في
  دالة مساعدة غير مزخرفة في نفس الفئة (`this.verifyX(arg)`) يُتعرف عليه أيضًا،
  بما في ذلك عبر سلسلة من هذه الدوال المساعدة.
- **تُتخطى الإثباتات المتحقق منها.** وسيط من النوع `Proof` / `SelfProof` / `DynamicProof` /
  `*Proof` يُستدعى عليه `.verify()` مقيَّد
  بالدائرة المتحقق منها — تُكتَم نتائج الشهود عليه (وعلى `publicOutput` /
  `publicInput` الخاص به). يُحتسب `.verifyIf(flag)` فقط عندما
  لا يكون الشرط وسيط دالة غير مقيَّد، أو يكون مؤكَّدًا بنفسه. ينطبق
  الشيء نفسه على غلاف OffchainState القانوني
  `this.offchainState.settle(proof)` (يتحقق الإطار داخل `settle`).
  لا يُفترض أن `.settle(proof)` المكتوب يدويًا
  يتحقق. الحالة العكسية (وسيط من نوع proof لا يُتحقق منه أبدًا
  ولا يُسوَّى عبر OffchainState) تُبلَّغ عنها باسم `O1JS_UNVERIFIED_PROOF`.
- **تُتخطى Bool المؤكَّدة / المستخدمة.** مُسند متسلسل مع
  `.assertTrue()` / `.assertFalse()`، أو متداخل في `Provable.if(...)`، أو
  مُسنَد إلى متغير محلي يُشار إليه لاحقًا، لا يُبلَّغ عنه باسم
  `O1JS_UNASSERTED_BOOL`.
- **تُتخطى المرسلون الموثقون.** لا يُفعَّل `this.sender.getUnconstrained()`
  عندما تستدعي نفس `@method` أيضًا
  `this.sender.getAndRequireSignature()`، أو عندما تُمرَّر تلك القيمة المشهودة
  إلى `AccountUpdate.createSigned(...)` / تُوثَّق عبر
  `.requireSignature()` على AccountUpdate مبني منها (مطلوب تطابق
  الوسيط).
- تُجرَّد التعليقات والسلاسل النصية قبل التحليل، لذا لا يمكن لـ `assert`
  داخل سلسلة نصية أن يُنشئ نتيجة كاذبة.

## ما يكتشفه (Noir)

تنطبق نفس فكرة السلامة — الشهود غير المقيَّدين بشكل كافٍ — على
دوائر [Noir](https://noir-lang.org) (`.nr`). وجّه الماسح إلى ملفات `.nr`
(أو استخدم `--lang noir`) وسيحللها بمجموعة قواعد Noir.
نفس النهج المعجمي الخالي من التبعيات. مُعاير مقابل اصطلاحات aztec-nr oracle /
`unsafe` — انظر [`docs/noir_calibration.md`](https://github.com/auditinfra-io/o1js-scan/blob/main/docs/noir_calibration.md).

<!-- BEGIN GENERATED NOIR RULE TABLE -->
| القاعدة | الخطورة | ما تعنيه |
|------|----------|---------------|
| `NOIR_UNCONSTRAINED_WITNESS` | high | قيمة مرتبطة من كتلة `unsafe { ... }` — نتيجة `unconstrained fn` (تلميح oracle / Brillig) — لا يُعاد تقييدها أبدًا بـ `assert` / `assert_eq` (أو دالة مساعدة مؤكِّدة / فحص merkle). يعمل التلميح **خارج** الدائرة. نظير `O1JS_UNCONSTRAINED_PROVABLE_WITNESS`. |
| `NOIR_UNCONSTRAINED_INPUT` | medium | مدخل خاص (شاهد) لـ `fn main` يتدفق إلى **لا** `assert` / `assert_eq` و**ليس** جزءًا من المخرجات العامة. نظير `O1JS_UNCONSTRAINED_WITNESS`. |
| `NOIR_UNCONSTRAINED_PUBLIC_INPUT` | medium | مدخل **عام** لـ `fn main` لا يصل إلى أي قيد ولا إلى أي مخرج — لا تقرؤه الدائرة أبدًا. وهو *النقيض* لقاعدة الشاهد الخاص: يقدم المتحقق القيمة ويعتقد أن العبارة عنها، بينما تتجاهلها الدائرة (مثل `merkle_root: pub Field` لا يُفحص أبدًا، فلم تُثبَت العضوية فعليًا). MEDIUM لأن المدخل العام غير المستخدم عمدًا هو أيضًا اصطلاح مشروع لربط إثبات بسياق (nonce / chain id / recipient)، وهو غير قابل للتمييز معجميًا — لذا لا يقيّد CI عند `--fail-on high` الافتراضي. |
| `NOIR_UNCHECKED_CAST` | medium | قيمة يتحكم فيها المُثبِت محوَّلة إلى نوع غير مُوقَّع ضيق (`as u8`/`u16`/`u32`) **بدون** تأكيد نطاق. نظير `MissingRangeCheck` في o1js. |
| `NOIR_UNCONSTRAINED_ARRAY_INDEX` | medium | قيمة يتحكم فيها المُثبِت تُستخدم كفهرس مصفوفة (`arr[i]`) **بدون** أي فحص من أي نوع عليها. فحص الحدود الضمني في Noir يثبت فقط أن الفهرس *داخل النطاق* — وليس أنه الفهرس *الصحيح* — لذا يبقى المُثبِت حرًا في اختيار أي عنصر ولا يزال يُنتج إثباتًا يتحقق بنجاح. هذا هو خطأ حرية المحدِّد الكامن وراء مواضع مسار Merkle واختيار الملاحظات وعضوية قائمة السماح. يُكتَم عندما يكون الفهرس محدودًا بالنطاق، أو مثبَّتًا بمساواة، أو محدودًا قبل تحويل (`index.assert_max_bit_size::<8>(); let i = index as u32;`)، أو عندما تكون القيمة المقروءة مثبَّتة بنفسها بـ `assert_eq`. |
| `NOIR_UNASSERTED_BOOL` | high / medium | مقارنة نتيجتها `bool` **مُهمَلة**. نظير `O1JS_UNASSERTED_BOOL` في o1js. |
| `NOIR_CONDITIONAL_ASSERT` | medium | `assert` داخل `if <flag> { ... }` حيث `<flag>` هو `bool` مجرد يتحكم فيه المُثبِت أو متغير محلي مشتق من قيم يتحكم فيها المُثبِت. القيد داخل شرط ينطبق فقط عندما يكون الشرط صحيحًا، لذا يمكن لفرع يختاره المُثبِت تخطي الفحص. تُترك المقارنات المضمَّنة (`if x != 0`) للدقة؛ ويُبلَّغ عن إسناد الحارس إلى متغير محلي (`let gate = x != 0; if gate`) ما لم يكن `gate` مؤكَّدًا بنفسه. |
| `NOIR_CONDITIONAL_CONSTRAIN` | medium | استدعاء `constrain_*` / `confirm_*` / `verify_*` فقط تحت `if` يتحكم فيه المُثبِت، بينما لا يزال تلميح `unsafe` يصل إلى المخرجات. |
| `NOIR_UNUSED_CHECK_RESULT` | high / medium | نتيجة `check_*` / `confirm_*` / `verify_*` / `constrain_*` مُهمَلة (استدعاء مجرد) أو مُسنَدة ولا تُؤكَّد أبدًا — الفحص لا يربط الدائرة. |
| `NOIR_VACUOUS_CONSTRAINT` | high / medium | قيد مُحقَّق بالبناء: مقارنة ذاتية (`assert(x == x)`، `assert_eq(x, x)`، `x >= x`) أو شرط ثابت (`assert(true)`). لا يضيف أي قيد، لكن السطر *يُقرأ* كفحص — مما يجعله أخطر من قيد مفقود، لأن المراجعة تتوقف عنده. HIGH للمقارنة الذاتية (غالبًا خطأ مطبعي لفحص حقيقي: `assert(computed == expected)` مكتوب خطأً كـ `assert(expected == expected)`)؛ MEDIUM للثابت، الذي يكون غالبًا عنصرًا نائبًا. `x != x` **لا** يُشار إليه — فهو غير قابل للإرضاء، خطأ حيوية وليس ثقبًا صامتًا في السلامة. |
| `NOIR_UNSAFE_MISSING_SAFETY` | low | كتلة `unsafe { ... }` بدون تعليق `// Safety:` مجاور. إعلامي؛ لا يُفشل CI عند `--fail-on high` الافتراضي. |
<!-- END GENERATED NOIR RULE TABLE -->

### حراس الإيجابيات الكاذبة (Noir)

- **assert / قفزة let / دوال مساعدة مؤكِّدة في نفس الملف** تربط تلميحات `unsafe`.
- **أسماء مواقع الاستدعاء** `constrain_*` / `confirm_*` / `verify_*` /
  `check_(non_)membership*` / `public_data_storage_read` تحتسب الوسائط (مع
  كشف النتائج غير المستخدمة للفحوصات المُهمَلة).
- **غير المقيَّد المقصود الموثق** (يتطلب `// Safety:` مجاور):
  `random()`، `avm::…`، وصياغة kernel/rollup/discovery المؤجلة.
- **`let` للـ tuple + أعلام مؤكَّدة** تربط شهود merkle الممرَّرين إلى فحوصات العضوية.

مثال:```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)

كما هو الحال مع مثال o1js أعلاه، فإن --include-examples مطلوب فقط لأن ملفات العرض التوضيحي هذه تقع تحت examples/.

القيود المعروفة

المحلل هو واجهة أمامية معجمية خالية من التبعيات مع طبقة دلالية خفيفة تقوم بتتبع الأسماء المستعارة والانتشار بين الإجراءات عبر الدوال المساعدة من نفس الفئة. وهو ليس واجهة أمامية لمترجم TypeScript، ولا مدقق أنواع، ولا محرك تدفق بيانات على مستوى البرنامج بأكمله، ولا توجد طبقة SMT أو إثبات رسمي في هذا الماسح الضوئي. ضع هذه النقاط العمياء في الاعتبار عند الفرز — فهي معروفة ومقصودة لهذا التصميم الخالي من التبعيات، وليست أخطاء:

  • يتم تتبع الأسماء المستعارة البسيطة فقط. يتتبع رصد الشواهد الأسماء المستعارة العادية ضمن نفس الدالة مثل const q = qty، ولكن ليس التعبيرات المشتقة أو التفكيك: ```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:~
  • ربط الطرق المتقاطعة يغطي سلاسل المساعدين من نفس الفئة فقط. يمكن لمساعد غير مزخرف من نفس الفئة يُستدعى كـ this.verifyX(arg) أن يربط حالة وسيطة للمستدعي، ومنذ 0.19.0 تُتبَّع سلاسل منهم (@method → المساعد A → المساعد B) إلى نقطة ثابتة. خطوة المساعد→المساعد تُعيّن فقط مرجع معامل مجرّد، لذا helperA(x.add(1)) لا ينتشر. الدوال الحرة والمستوردة لا تزال غير متتبَّعة، والاستعارة عبر متغير محلي لوسيطة المساعد تبقى قيدًا موثّقًا.

  • كشف Bool غير المؤكَّد ذو شكل عبارة. المستوى A يعلّم فقط عبارات التعبير المجرّدة التي يكون استدعاؤها الخارجي محمول Bool دون أي شيء مسلسل بعده. المحمولات المتداخلة داخل Provable.if(...)، أو المُعيَّنة والمستخدمة لاحقًا، لا تُعلَّم. قد تظل الاستخدامات المعقدة لتدفق التحكم لمتغير Bool محلي مفقودة إذا لم يُشار إلى الاسم أبدًا (نمط الفشل: تفويت، وليس إيجابية كاذبة).

  • بوابة التوقيع على مستوى الطريقة وقائمة على السلاسل الفرعية. _method_is_signature_gated تعامل @method كاملة كبوابة مالك إذا احتوت على اصطلاح توقيع، ولا تتعرف على المدقق إلا عندما يحتوي اسم المستقبل حرفيًا على — لذا يُتعرف عليه كبوابة، بينما فحص توقيع غير ذي صلة في مكان آخر داخل طريقة كبيرة قد يفرط في الكبت. إنه كل شيء أو لا شيء لكل طريقة.

هذه هي الأسباب التي تجعل النتائج نقطة انطلاق للمراجعة البشرية، وليست براهين. إعادة الكتابة الواعية بتدفق البيانات خارج النطاق عمدًا عن المحلل المعجمي.

أين تتوقف هذه الأداة

o1js-scan هو عمدًا تمرير معجمي سطحي أحادي الملف — لا محلل، لا تدفق بيانات، لا حلّال. هذا ما يجعله بلا اعتماديات وفوريًا في CI، وهو أيضًا سقف صلب. القيود أعلاه ليست قائمة مهام؛ بل نتائج للتصميم.

لذا يجدر أن نكون صريحين بشأن ما يمكن لهذه الأداة أن تخبرك به وما لا يمكنها:

  • تشغيل نظيف ليس تدقيقًا. يعني أن أي شكل يتعرف عليه هذا الماسح لم يتطابق — وليس أن الدائرة سليمة. فئات الأخطاء التي تحتاج تدفق بيانات، أو حساسية للمسار، أو حلّ قيود هي خارج متناول أداة بهذا الشكل، بأي لغة.
  • النتيجة خيط استدلالي، وليست حكمًا. كل قاعدة هنا استكشافية مع فئة إيجابيات كاذبة موثّقة.

هذه المقايضة هي الصحيحة لأداة فحص تشغّلها على كل commit. إذا كنت تعمل على شيء يهم فيه الفرق — بروتوكول يحمل قيمة حقيقية، أو دائرة لا تستطيع تحمّل الخطأ فيها — عامل هذا كتمريرة أولى وخصّص ميزانية لمراجعة حقيقية.

للتحليل الأعمق، يُصان الماسح الكامل المنفصل في مستودع audit-engine-cli. o1js-scan هو الماسح المفتوح الخفيف عمدًا؛ معرفة الكشف الخاصة بالماسح الكامل وتفاصيل تنفيذه غير مستنسخة هنا. للوصول أو لمراجعة دائرة أكثر اكتمالًا، تواصل: [email protected].

الخصوصية والكود الخاص

تحلل أداة CLI المثبَّتة الملفات محليًا. ليس لديها قياس عن بُعد، ولا عميل شبكة، ولا حساب، ولا خطوة رفع، وبيئة تشغيل Python الخاصة بها بلا اعتماديات من أطراف ثالثة. تشغيل o1js-scan path/to/private-repo لا يرسل المصدر أو النتائج إلى أي مكان.

مثل سجلات المترجم، قد يحتوي مخرَج الماسح على مسارات ومعرّفات ومقتطفات مصدر. يحدد SARIF أيضًا مواقع المستودع الدقيقة، ويرفعه إجراء GitHub إلى فحص كود GitHub. استخدم نفس ضوابط الوصول للمستودع و CI التي تستخدمها بالفعل للمصدر الذي يجري فحصه.

تريد المساهمة بتقرير مفيد عن إيجابية كاذبة أو كشف مفوَّت دون مشاركة تطبيق؟ أعد إنتاج الصياغة بأسماء وثوابت مُختلقة، وأزل منطق العمل عبارة تلو الأخرى، وتحقق من أن المقتطف الاصطناعي لا يزال يفعّل نفس القاعدة قبل نشره. يحتوي دليل المساهمة الآمن للخصوصية على قائمة تحقق ملموسة و عدة طرق لمساعدة مجتمع o1js دون الكشف عن دائرة خاصة.

هذا الحد لا يمنع الماسح المفتوح من التحسن. يمكن لوثائق o1js العامة والمستودعات دعم قواعد جديدة وتركيبات توافق؛ ويمكن للأمثلة الاصطناعية اختبار الإيجابيات الكاذبة والقيود المفوَّتة؛ ويمكن تحسين مرونة المحلل، والتشخيصات، و SARIF، والأداء، والتغليف، والمعايرة كلها دون نشر تقنية تدقيق خاصة أو كود عميل. ينبغي للماسح المفتوح أن يقدم ادعاءات قابلة للتفسير بشكل مستقل؛ ويمكن أن يبقى البحث الخاص في محرك التدقيق المنفصل.

مراجعة ما بعد الكم

ترتبط مخاطر الكم بأمن الدوائر، لكنها ليست قاعدة قيد مفقود. لا يحدد o1js-scan ما إذا كان توقيع أو تجزئة أو التزام، أو نظام إثبات Kimchi، أو Mina نفسها يفي بهدف أمني لما بعد الكم. تلك الإجابات تعتمد على البدائية والمعاملات الملموسة، وافتراضات المنصة، والعمر المطلوب للنشر، وخطة الترحيل الخاصة به — وليس فقط على معرّف TypeScript يمكن لماسح معجمي رؤيته.

مستوحى من Qubit or Not Qubit من O(1) Labs، يحوّل دليل مراجعة ما بعد الكم ذلك الحد إلى جرد خاص بـ o1js وقائمة تحقق للرشاقة التشفيرية. استخدمه إلى جانب هذا الماسح بدلًا من تفسير فحص نظيف كتقييم لما بعد الكم.

التوافق

يعمل على o1js 1.x و 2.x و 3.x، بما في ذلك تفريعة Mesa الصلبة التي يستهدفها o1js 3.0.0. يحلل o1js-scan مصدر TypeScript كنص وليس لديه اعتمادية وقت تشغيل على o1js — لا شيء مثبَّت بإصدار. يعتمد على واجهة الشرط المسبق الحديثة require* (getAndRequireEquals، requireEquals، requireSignature، getAndRequireSignature)، ومزخرفات @method / @method() / @method.returns(...)، وحقول @state المُعلَّمة، و this.send({...})، وتحويلات المستوى المنخفض AccountUpdate.balance.subInPlace(...)، و Permissions.*. تبقى الصيغ الراسخة متوافقة عبر حدود 1.x → 2.x → 3.x، بينما يقبل الماسح أيضًا المزخرف الموثّق حديثًا ومتغيرات التحويل منخفض المستوى. يُتعرف على اصطلاح مصادقة المالك في 2.x كبوابة توقيع. (لا تزال الشروط المسبقة القديمة مقبولة، لذا لا ينكسر الكود الأقدم أيضًا.)

جميع تغييرات Mesa الكاسرة على مستوى وقت التشغيل والبروتوكول — إزالة Transaction.setFeePerSnarkCost() وثوابت TransactionCost.*، وشكل VerificationKey.toJSON() الجديد، ومفاتيح التحقق المُعاد توليدها، ورفع MAX_ZKAPP_STATE_FIELDS من 8 إلى 32، وصيغة معاملة mina-signer v4. لا شيء منها يعيد تسمية واجهة برمجية يطابقها هذا الماسح، لذا لم تتغير أي قاعدة من أجل Mesa، وهذا مُتحقَّق منه لا مُدَّعى. يمسح scripts/o1js_release_matrix.sh إصدارين مثبَّتين من o1js يحيطان بحد البروتوكول — 2.15.0 (9620ef08، آخر إصدار 2.x) و 3.0.0 (cc18a919، Mesa) — ويقارن كل نتيجة مقابل tests/fixtures/o1js_release_matrix.json:

33 نتيجة متطابقة عبر الحد، ولم تُفقد أي منها، وجميع الثلاث الجديدة في src/examples/zkapps/big-state-zkapp.ts — مثال الحقول الـ32 للحالة الذي يوجد فقط لأن Mesa رفعت MAX_ZKAPP_STATE_FIELDS. هذا الفارق مثبَّت باختبار، لذا لا يمكن أن ينحرف بصمت. تعمل المصفوفة على كل بناء CI؛ ومهمة o1js-upstream-canary الأسبوعية تتبع إضافةً o1js عند HEAD، متقدمةً على أي إصدار.

تُطبَّع صيغ القيود المكافئة للتحليل: assertEquals(...) على المثيل، و Provable.assertEqual(Type, ...) الساكنة، وسلاسل المساواة equals(...).assertTrue() كلها تربط نفس المعاملات. استخراج الطرق متوازن الأقواس بعد إخفاء التعليقات والسلاسل بطول محفوظ، ويقبل المزخرفات متعددة الأسطر، وأنواع المعاملات المتداخلة على شكل callback، ومحددات وصول TypeScript، والأسماء المستعارة للهوية متعددة الأسطر (بما في ذلك الصيغ بين قوسين وصيغ as Type).

يستهدف تحليل Noir صياغة Noir المستخدمة في مشاريع Aztec / nargo (.nr)؛ ولا يستدعي nargo أو يترجم الدوائر.

كيف يعمل

إنه محلل معجمي، وليس محللًا كاملًا لـ TypeScript أو Noir — مصادر o1js و Noir محددة بأقواس وقابلة للمعالجة بالتعبيرات النمطية، والمخرَج مقصود أن يفرزه إنسان. هذا يبقيه بلا اعتماديات وفوري التشغيل في CI. النتائج نقطة انطلاق للمراجعة، وليست براهين.

خارطة الطريق / المساهمة

المساهمات مرحّب بها — عائلات قواعد جديدة، ومزيد من حراس الإيجابيات الكاذبة، ونماذج معايرة من العالم الحقيقي كلها قيّمة. انظر CONTRIBUTING.md.

لمسار مقترح من إدراج Community Packages إلى فحص استشاري في مستودع o1js، انظر مقترح تكامل o1js upstream الجاهز للإرسال.

شغّل الاختبارات وأداة الفحص بـ:```bash pip install -e ".[dev]" pytest # unit tests + Noir/o1js corpus ruff check . # lint npm run format:check # prettier, npm wrapper only

root@kitploit:~
## الترخيص

Apache-2.0. انظر [`LICENSE`](https://github.com/auditinfra-io/o1js-scan/blob/main/LICENSE).
تنزيل الأداة
#[test(...)]
mod test { … }
mod tests { … }
signature
sig.verify(admin, msg)
لا
  • مصادقة المرسل قائمة على الاسم وفي نفس الطريقة فقط. O1JS_UNCONSTRAINED_SENDER يكبت عندما يظهر this.sender.getAndRequireSignature() أو AccountUpdate.createSigned(<that sender>) في نفس جسم @method. متطلب التوقيع الذي يوجد فقط في مساعد (this.requireSenderSig() → getAndRequireSignature بالداخل) لا يُتبَّع — نمط الفشل هو إيجابية كاذبة على كود صحيح يغلّف الاصطلاح، وليس خطأ حقيقي مفوَّت.

  • مساعدات Noir عبر الحزم تُتعرف عليها بـاصطلاح الاسم فقط (لا Nargo.toml / حل الاستيراد). تفضيل التفويت على الإيجابية الكاذبة.

  • this.sender.getAndRequireSignature()
    assertEquals
    الإصدارالنتائجHIGHMEDIUMLOWالملفات
    o1js 2.15.036826218
    o1js 3.0.0 (Mesa)39829219