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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
vm2 — صندوق رمل (Sandbox) معزول للغة JavaScript في بيئة Node.js، يعمل على تشغيل الكود غير الموثوق مع تقييد الوصول إلى الوحدات المدمجة وموارد المضيف عبر الاعتراض القائم على Proxy. | Kitploit
أدوات/GitHubGitHub/patriksimek/vm2
التحليل الديناميكي (عزل)تحليل الكودالمحاكاة الافتراضية للأمانالأدوات والمكونات
GitHubpatriksimek/vm2

vm2

صندوق رمل (Sandbox) معزول للغة JavaScript في بيئة Node.js، يعمل على تشغيل الكود غير الموثوق مع تقييد الوصول إلى الوحدات المدمجة وموارد المضيف عبر الاعتراض القائم على Proxy.

عرض المستودع
4.1k32626منذ 2 أيامتمت المراجعة من قبل Kitploit

الأكثر شعبية

عرض الكل →

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

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

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

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

vm2 [![NPM Version][npm-image]][npm-url] [![NPM Downloads][downloads-image]][downloads-url] [![License][license-image]][license-url] Node.js CI [![Known Vulnerabilities][snyk-image]][snyk-url]

vm2 هو صندوق رمل يمكنه تشغيل كود غير موثوق به مع وحدات Node.js المدمجة المدرجة في القائمة البيضاء.

التثبيت```sh

npm install vm2

root@kitploit:~
## أمثلة سريعة```js
import { VM } from 'vm2';

const vm = new VM();
vm.run(`process.exit()`); // TypeError: process.exit is not a function

بعد اكتمال التثبيت، يمكنك التحقق من التثبيت عن طريق تشغيل الأمر التالي:

root@kitploit:~
toolname --version

يجب أن يظهر إصدار الأداة في الإخراج. إذا واجهت أي أخطاء، تأكد من تثبيت جميع المتطلبات الأساسية بشكل صحيح.

الاستخدام

لاستخدام الأداة، اتبع الخطوات التالية:

  1. افتح الطرفية (Terminal) أو موجه الأوامر (Command Prompt).
  2. انتقل إلى الدليل الذي تم تثبيت الأداة فيه.
  3. قم بتشغيل الأمر التالي:
root@kitploit:~
toolname [options] <target>

الخيارات المتاحة

أمثلة

فيما يلي بعض الأمثلة على الاستخدام الشائع:

root@kitploit:~
# فحص هدف أساسي
toolname https://example.com

# فحص مع إخراج مفصل
toolname -v https://example.com

# حفظ النتائج في ملف
toolname -o results.txt https://example.com

استكشاف الأخطاء وإصلاحها

إذا واجهت مشاكل أثناء استخدام الأداة، راجع الأقسام التالية:

خطأ: "Permission denied"

يحدث هذا الخطأ عادةً عندما لا تملك صلاحيات كافية لتنفيذ الأداة. حاول تشغيل الأمر مع sudo على أنظمة Linux أو macOS:

root@kitploit:~
sudo toolname https://example.com

خطأ: "Module not found"

تأكد من تثبيت جميع التبعيات المطلوبة. يمكنك إعادة تثبيتها باستخدام:

root@kitploit:~
pip install -r requirements.txt

خطأ: "Connection timeout"

قد يكون الهدف غير متاح أو أن الشبكة بطيئة. حاول زيادة المهلة الزمنية باستخدام الخيار -t:

root@kitploit:~
toolname -t 60 https://example.com

المساهمة

نرحب بالمساهمات من المجتمع! إذا كنت ترغب في المساهمة في تطوير هذه الأداة، يرجى اتباع الخطوات التالية:

  1. قم بعمل Fork للمستودع.
  2. أنشئ فرعًا جديدًا لميزتك أو إصلاحك.
  3. قم بإجراء التغييرات اللازمة.
  4. تأكد من اجتياز جميع الاختبارات.
  5. أرسل طلب سحب (Pull Request) مع وصف واضح للتغييرات.

الترخيص

هذه الأداة مرخصة بموجب رخصة MIT. راجع ملف LICENSE للحصول على التفاصيل الكاملة.

الإخلاء القانوني

هذه الأداة مخصصة للأغراض التعليمية والاختبارات الأمنية المشروعة فقط. لا يجوز استخدامها لأي أنشطة غير قانونية أو ضارة. المستخدم مسؤول بالكامل عن أي استخدام غير مناسب لهذه الأداة.```js import { NodeVM } from 'vm2';

const vm = new NodeVM({ require: { external: true, root: './', }, });

vm.run( var request = require('request'); request('http://www.google.com', function (error, response, body) { console.error(error); if (!error && response.statusCode == 200) { console.log(body); // Show the HTML for the Google homepage. } });, 'vm.js', );

root@kitploit:~
## إخلاء مسؤولية أمني مهم

**قبل استخدام vm2، يجب أن تفهم كيف يعمل وقيوده.**

يحاول vm2 عزل كود JavaScript غير الموثوق **داخل نفس عملية Node.js** الخاصة بتطبيقك. يفعل ذلك من خلال شبكة معقدة من [الوكلاء (Proxies)](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Proxy) التي تعترض وتتوسط كل تفاعل بين بيئة العزل وبيئة المضيف.

### التحدي الأساسي

JavaScript لغة ديناميكية بشكل استثنائي. يمكن الوصول إلى الكائنات من خلال سلاسل النماذج الأولية (prototype chains)، ويمكن الوصول إلى المُنشئات عبر كائنات الأخطاء، وتوفر الرموز (symbols) خطافات بروتوكول، وينشئ التنفيذ غير المتزامن نوافذ توقيت. العدد الهائل من الطرق للتنقل من كائن إلى آخر في JavaScript يجعل بناء عزل آمن داخل العملية أمرًا صعبًا للغاية.

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

1. **من المرجح اكتشاف تجاوزات جديدة في المستقبل.** تحقق من [التنبيهات الأمنية](https://github.com/patriksimek/vm2/security/advisories) الخاصة بنا للثغرات المعروفة.
2. **يجب عليك إبقاء vm2 محدثًا** للاستفادة من أحدث الإصلاحات الأمنية. اشترك في التنبيهات الأمنية وحدّث فورًا.
3. **لا ينبغي أن يكون vm2 خط دفاعك الوحيد.** الدفاع المتعمق (Defense in depth) ضروري عند تشغيل كود غير موثوق.

### بدائل أكثر قوة

إذا كنت بحاجة إلى ضمانات عزل أقوى، ففكر في هذه البدائل التي توفر **عزلًا حقيقيًا على مستوى العملية أو مستوى الأجهزة**:

| الحل | النهج | الأداء | المقايضات |
|----------|----------|-------------|------------|
| **[isolated-vm](https://github.com/laverdet/isolated-vm)** | عوازل V8 منفصلة (كومة V8 مختلفة) | سريع | في وضع الصيانة؛ يتطلب تحديثات V8 يدوية |
| **عملية منفصلة / Worker** | `child_process` أو Worker threads بصلاحيات محدودة | متوسط | حمل IPC أعلى؛ يجب تسلسل البيانات |
| **الحاويات / الأجهزة الافتراضية** | Docker، gVisor، Firecracker | بطيء | حمل بدء التشغيل؛ كثيف الموارد |
| **الخدمات المُدارة** | تنفيذ الكود المستند إلى السحابة (مثل AWS Lambda، Cloudflare Workers) | متغير | زمن استجابة الشبكة؛ اعتماد خارجي |

### متى قد يظل vm2 مناسبًا

يمكن أن يكون vm2 مناسبًا عندما:
- تحتاج إلى تكامل وثيق مع كائنات المضيف وتواصل متزامن سريع
- يأتي الكود غير الموثوق من مصدر موثوق نسبيًا (مثل الأدوات الداخلية، أنظمة الإضافات مع مؤلفين معتمدين)
- تجمع بين vm2 وطبقات أمنية أخرى (عزل الشبكة، قيود نظام الملفات، حدود الموارد)
- تقبل المخاطر وتراقب بنشاط التحديثات الأمنية

**إذا كنت تشغّل كودًا من مصادر غير موثوقة تمامًا (مثل إرسالات المستخدمين العشوائية)، فنوصي بشدة باستخدام حل بضمانات عزل أقوى.**

## بيئات التشغيل (Runtimes)

| بيئة التشغيل | الحالة |
|---------|--------|
| Node.js | مدعومة. بيئة العزل هي حدود أمنية. |
| Bun | **تجريبي.** توافق وظيفي جزئي — **ليست** حدودًا أمنية. |

ينطبق قيدان منفصلان على Bun، ولا يعني أحدهما الآخر.

**إنها ليست حدودًا أمنية.** نموذج التهديد الخاص بـ vm2، وكتالوج الهجمات في
[`docs/ATTACKS.md`](https://github.com/patriksimek/vm2/blob/main/docs/ATTACKS.md)، وكل اختبار انحدار في `test/ghsa/`
مشتقة من دواخل V8. JavaScriptCore، الذي يستخدمه Bun، له
ما يعادله الخاص، ولم يتم تدقيق أي منها مقابل جسر vm2. نجاح المجموعة
تحت Bun يُظهر التوافق، وليس أن العزل يصمد هناك. **لا
تستخدم vm2 على Bun لعزل كود غير موثوق.**

**التوافق جزئي، وليس تكافؤًا.** تشغيل Bun الأخضر يغطي فقط الاختبارات
التي تُنفَّذ فعليًا هناك. يسرد `test/bun-skips.js` ما هو مستبعد ولماذا،
وتشمل الفجوات السلوكية المعروفة ما يلي:

- `Buffer.from(arrayLike)` يُرجع مخزنًا مؤقتًا بطول صفري
- بيانات `VMScript` الوصفية `filename` / `lineOffset` / `columnOffset` غير
  قابلة للملاحظة، لأن كائنات CallSite الخاصة بـ JSC لا تحمل أي طرق
- `Object.freeze` على كائن مضيف مجمّد مع مُوصِّل غير قابل للتهيئة
  يرمي خطأ `TypeError` بانتهاك قيد الوكيل حيث لا يفعل V8 ذلك
- بعض عمليات `Buffer` عبر حدود بيئة العزل أبطأ بشكل كبير —
  يستغرق `allocUnsafe` بحجم 64 ميجابايت أكثر من 400 ثانية مقابل 1.7 على Node، بطيء بما يكفي
  ليُقرأ كتعليق

تعامل مع دعم Bun كتوافق بأفضل جهد ممكن للكود الموثوق، وتحقق من
قائمة التخطي قبل الاعتماد على أي سلوك معين.

## الميزات

-   تشغيل كود غير موثوق بأمان في عملية واحدة مع كودك جنبًا إلى جنب
-   تحكم كامل في مخرجات وحدة التحكم الخاصة ببيئة العزل
-   تتمتع بيئة العزل بوصول محدود إلى طرق العملية
-   من الممكن استدعاء الوحدات (المدمجة والخارجية) من بيئة العزل
-   يمكنك تقييد الوصول إلى وحدات مدمجة معينة (أو كلها)
-   يمكنك استدعاء الطرق وتبادل البيانات والاستدعاءات الرجعية (callbacks) بين بيئات العزل بأمان
-   صيانة نشطة مع تصحيحات لطرق الهروب المعروفة (انظر [إخلاء المسؤولية الأمني](#important-security-disclaimer))
-   دعم المُحوِّل (Transpiler)

## كيف يعمل

-   يستخدم وحدة VM الداخلية لإنشاء سياق آمن.
-   يستخدم [الوكلاء (Proxies)](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Proxy) لمنع الهروب من بيئة العزل.
-   يتجاوز دالة require المدمجة للتحكم في الوصول إلى الوحدات.

للحصول على نظرة متعمقة على دواخل vm2، انظر [docs/ATTACKS.md](https://github.com/patriksimek/vm2/blob/main/docs/ATTACKS.md).

## ما الفرق بين vm الخاصة بـ Node وvm2؟

جرّبها بنفسك:```js
import { runInNewContext } from "node:vm";

runInNewContext('this.constructor.constructor("return process")().exit()');
console.log('Never gets executed.');

بعد اكتمال التثبيت، يمكنك تشغيل الأداة باستخدام الأمر التالي:

root@kitploit:~
toolname --help

لمزيد من المعلومات حول خيارات سطر الأوامر، راجع التوثيق.

المتطلبات

  • Python 3.8 أو أحدث
  • pip
  • اتصال بالإنترنت (لتنزيل التبعيات)

التثبيت من المصدر

إذا كنت تفضل التثبيت من المصدر، اتبع الخطوات التالية:

root@kitploit:~
git clone https://github.com/example/toolname.git
cd toolname
pip install -r requirements.txt
python setup.py install

الاستخدام

الفحص الأساسي

لتشغيل فحص أساسي على هدف:

root@kitploit:~
toolname scan --target example.com

الفحص المتقدم

لإجراء فحص متقدم مع خيارات إضافية:

root@kitploit:~
toolname scan --target example.com --verbose --output report.json

تصدير النتائج

يدعم الأداة تصدير النتائج بصيغ متعددة:

الصيغةالامتدادالوصف
JSON.jsonصيغة منظمة للآلة
CSV.csv

خيارات سطر الأوامر

أمثلة

فحص نطاق فرعي

root@kitploit:~
toolname subdomain --target example.com --wordlist subdomains.txt

فحص المنافذ

root@kitploit:~
toolname portscan --target 192.168.1.1 --ports 1-1000

فحص الثغرات

root@kitploit:~
toolname vuln --target example.com --severity high

استكشاف الأخطاء وإصلاحها

خطأ في التبعيات

إذا واجهت أخطاء في تثبيت التبعيات، حاول تحديث pip:

root@kitploit:~
pip install --upgrade pip

مشاكل الاتصال

تأكد من أن لديك اتصالاً بالإنترنت وأن جدار الحماية لا يحظر المنافذ المطلوبة.

المساهمة

نرحب بالمساهمات! يرجى اتباع الخطوات التالية:

  1. قم بعمل fork للمستودع
  2. أنشئ فرعًا جديدًا (git checkout -b feature/amazing-feature)
  3. قم بتطبيق تغييراتك
  4. قم بعمل commit (git commit -m 'Add some amazing feature')
  5. ادفع التغييرات (git push origin feature/amazing-feature)
  6. افتح طلب سحب (Pull Request)

الترخيص

هذا المشروع مرخص بموجب رخصة MIT - راجع ملف LICENSE للحصول على التفاصيل.

الإشعارات

  • هذه الأداة مخصصة للأغراض التعليمية والاختبارات الأمنية المصرح بها فقط.
  • لا تستخدم الأداة ضد أهداف دون إذن صريح.
  • المستخدم مسؤول عن أي استخدام غير قانوني للأداة.```js import { VM } from 'vm2';

new VM().run('this.constructor.constructor("return process")().exit()'); // Throws ReferenceError: process is not defined

root@kitploit:~
## التوثيق

-   [VM](#vm)
-   [NodeVM](#nodevm)
-   [VMScript](#vmscript)
-   [معالجة الأخطاء](#error-handling)
-   [تصحيح أخطاء الكود المعزول](#debugging-a-sandboxed-code)
-   [الكائنات للقراءة فقط](#read-only-objects-experimental)
-   [الكائنات المحمية](#protected-objects-experimental)
-   [العلاقات بين العزلات](#cross-sandbox-relationships)
-   [واجهة سطر الأوامر](#cli)
-   [تغييرات 2.x إلى 3.x](https://github.com/patriksimek/vm2/wiki/2.x-to-3.x-changes)
-   [توثيق 1.x و 2.x](https://github.com/patriksimek/vm2/wiki/1.x-and-2.x-docs)
-   [المساهمة](https://github.com/patriksimek/vm2/wiki/Contributing)

## VM

VM هو عزل بسيط لتشغيل الكود غير الموثوق بشكل متزامن دون ميزة `require`. تتوفر فقط كائنات JavaScript المدمجة و`Buffer` الخاصة بـ Node. دوال الجدولة (`setInterval`, `setTimeout` و `setImmediate`) غير متوفرة افتراضيًا.

**الخيارات:**

-   `timeout` - مهلة البرنامج النصي بالمللي ثانية. **تحذير**: قد ترغب في استخدام هذا الخيار مع `allowAsync=false`. علاوة على ذلك، فإن التعامل مع الكائنات المُعادة من العزل يمكن أن يشغّل كودًا عشوائيًا ويتجاوز المهلة. يجب على المرء اختبار ما إذا كان الكائن المُعاد بدائيًا باستخدام `typeof` والتخلص منه تمامًا (قد يؤدي تسجيل الدخول أو إنشاء رسائل خطأ باستخدام مثل هذا الكائن أيضًا إلى تشغيل كود عشوائي مرة أخرى) في الحالة الأخرى.
-   `sandbox` - الكائن العام لـ VM.
-   `compiler` - `javascript` (الافتراضي)، `typescript`، `coffeescript` أو دالة مترجم مخصصة. تتوقع المكتبة أن يكون لديك المترجم مثبتًا مسبقًا إذا تم تعيين القيمة على `typescript` أو `coffeescript`. **يتطلب `typescript` إصدار `typescript@6` أو أحدث** — انظر [المترجمون](#compilers).
-   `eval` - إذا تم تعيينه على `false`، فإن أي استدعاءات لـ `eval` أو منشئات الدوال (`Function`, `GeneratorFunction`, إلخ) ستُطلق `EvalError` (الافتراضي: `true`).
-   `wasm` - إذا تم تعيينه على `false`، فإن أي محاولة لتجميع وحدة WebAssembly ستُطلق `WebAssembly.CompileError` (الافتراضي: `true`). ملاحظة: تتم إزالة `WebAssembly.JSTag` داخل العزل لأسباب أمنية، لذا لا يمكن لكود wasm التقاط استثناءات JavaScript.
-   `allowAsync` - إذا تم تعيينه على `false`، فإن أي محاولة لتشغيل كود باستخدام `async` ستُطلق `VMError` (الافتراضي: `true`).
-   `bufferAllocLimit` - الحد الأقصى للحجم بالبايت لطلب واحد من `Buffer.alloc` / `Buffer.allocUnsafe` / `Buffer.allocUnsafeSlow` / `Buffer(N)` / `new Buffer(N)` من داخل العزل. الطلبات التي تتجاوز هذا الحد تُطلق `RangeError` بشكل متزامن دون تنفيذ التخصيص على المضيف. الافتراضي: `Infinity` (بدون حد، متوافق تمامًا مع الإصدارات السابقة). يجب على المُضمّنين الذين يشغّلون كودًا غير موثوق في بيئات محدودة الذاكرة (Docker / Kubernetes / Lambda / serverless) اختيار حد محدود (مثل `32 * 1024 * 1024`) كجزء من الدفاع الطبقي ضد DoS، بنفس الطريقة التي يختارون بها `timeout`. انظر [توصيات التحصين](#hardening-recommendations) أدناه.

**مهم**: المهلة فعالة فقط على الكود المتزامن الذي تشغّله عبر `run`. المهلة **لا** تعمل على أي طريقة مُعادة من VM. هناك بعض الحالات التي لا تعمل فيها المهلة - انظر [#244](https://github.com/patriksimek/vm2/pull/244).```js
import { VM } from 'vm2';

const vm = new VM({
	timeout: 1000,
	allowAsync: false,
	sandbox: {},
});

vm.run('process.exit()'); // throws ReferenceError: process is not defined

يمكنك أيضًا استرجاع القيم من الجهاز الافتراضي.```js let number = vm.run('1337'); // returns 1337

root@kitploit:~
**نصيحة**: راجع الاختبارات لمزيد من أمثلة الاستخدام.

## NodeVM

على عكس `VM`، يتيح لك `NodeVM` استيراد الوحدات بنفس الطريقة التي تستخدمها في سياق Node العادي.

**الخيارات:**

-   `console` - `inherit` لتمكين وحدة التحكم، `redirect` لإعادة التوجيه إلى الأحداث، `off` لتعطيل وحدة التحكم (الافتراضي: `inherit`).
-   `sandbox` - الكائن العام لـ VM.
-   `compiler` - `javascript` (الافتراضي)، `typescript`، `coffeescript` أو دالة مترجم مخصصة (تستقبل الكود ومسار ملفه). تتوقع المكتبة أن يكون لديك المترجم مثبتًا مسبقًا إذا تم تعيين القيمة إلى `typescript` أو `coffeescript`. **يتطلب `typescript` الإصدار `typescript@6` أو إصدارًا أقدم** — راجع [المترجمون](#compilers).
-   `eval` - إذا تم تعيينه إلى `false`، فإن أي استدعاء لـ `eval` أو منشئات الدوال (`Function`، `GeneratorFunction`، إلخ) سيؤدي إلى رمي خطأ `EvalError` (الافتراضي: `true`).
-   `wasm` - إذا تم تعيينه إلى `false`، فإن أي محاولة لتجميع وحدة WebAssembly ستؤدي إلى رمي خطأ `WebAssembly.CompileError` (الافتراضي: `true`). ملاحظة: تتم إزالة `WebAssembly.JSTag` داخل بيئة العزل لأسباب أمنية، لذا لا يمكن لرمز wasm التقاط استثناءات JavaScript.
-   `bufferAllocLimit` - نفس الدلالات كما في `VM` — الحد الأقصى للحجم بالبايت لطلب واحد من عائلة `Buffer.alloc` من داخل بيئة العزل. الافتراضي: `Infinity`. راجع [توصيات التقوية](#hardening-recommendations).
-   `sourceExtensions` - مصفوفة من امتدادات الملفات التي سيتم التعامل معها ككود مصدري (الافتراضي: `['js']`).
-   `require` - `true`، أو كائن، أو أداة حل (Resolver) لتمكين طريقة `require` (الافتراضي: `false`).
-   `require.external` - يمكن أن تكون القيم `true`، أو مصفوفة من الوحدات الخارجية المسموح بها، أو كائنًا (الافتراضي: `false`). يُسمح باستيراد جميع المسارات المطابقة لـ `/node_modules/${any_allowed_external_module}/(?!/node_modules/)`.
-   `require.external.modules` - مصفوفة من الوحدات الخارجية المسموح بها. تدعم أيضًا أحرف البدل، لذا فإن تحديد `['@scope/*-ver-??]`، على سبيل المثال، سيسمح باستخدام جميع الوحدات التي تحمل اسمًا بالشكل `@scope/something-ver-aa`، `@scope/other-ver-11`، إلخ. لا يطابق حرف البدل `*` فواصل المسارات.
-   `require.external.transitive` - قيمة منطقية تشير إلى ما إذا كانت التبعيات غير المباشرة للوحدات الخارجية مسموحًا بها (الافتراضي: `false`). **تحذير**: عندما يتم استيراد وحدة بشكل غير مباشر، يصبح بإمكان أي وحدة أخرى استيرادها بشكل طبيعي، حتى لو لم يكن ذلك ممكنًا قبل تحميلها.
-   `require.builtin` - مصفوفة من الوحدات المدمجة المسموح بها، تقبل `["\*"]` للجميع (الافتراضي: لا شيء). **تحذير**: يمكن أن يكون `"\*"` خطيرًا حيث يمكن إضافة وحدات مدمجة جديدة.
-   `require.root` - المسار (المسارات) المقيدة حيث يمكن استيراد الوحدات المحلية (الافتراضي: كل مسار).
-   `require.mock` - مجموعة من الوحدات الوهمية (سواء كانت خارجية أو مدمجة).
-   `require.context` - `host` (الافتراضي) لاستيراد الوحدات في المضيف وتمريرها عبر وكيل إلى بيئة العزل. `sandbox` لتحميل الوحدات وتجميعها واستيرادها داخل بيئة العزل. `callback(moduleFilename, ext)` لاختيار سياق ديناميكيًا لكل وحدة. سيكون الافتراضي هو بيئة العزل إذا لم يتم تحديد أي شيء. باستثناء `events`، يتم دائمًا استيراد الوحدات المدمجة في المضيف وتمريرها عبر وكيل إلى بيئة العزل.
-   `require.import` - مصفوفة من الوحدات التي سيتم تحميلها في NodeVM عند البدء.
-   `require.resolve` - دالة بحث إضافية في حال لم يتم العثور على وحدة في أحد مسارات البحث التقليدية في Node.
-   `require.customRequire` - يُستخدم بدلاً من دالة `require` لتحميل الوحدات من المضيف.
-   `require.strict` - `false` لعدم فرض الوضع الصارم على الوحدات المحملة بواسطة require (الافتراضي: `true`).
-   `require.fs` - تنفيذ مخصص لنظام الملفات.
-   `nesting` - **تحذير**: السماح بهذا يشكل خطرًا أمنيًا حيث يمكن للبرامج النصية إنشاء NodeVM يمكنه استيراد أي وحدة من المضيف. `true` لتمكين تداخل VMs (الافتراضي: `false`).
-   `wrapper` - `commonjs` (الافتراضي) لتغليف البرنامج النصي في غلاف CommonJS، `none` لاسترجاع القيمة التي يعيدها البرنامج النصي.
-   `argv` - مصفوفة يتم تمريرها إلى `process.argv`.
-   `env` - كائن يتم تمريره إلى `process.env`.
-   `strict` - `true` لتحميل الوحدات في الوضع الصارم (الافتراضي: `false`).

**مهم**: المهلة الزمنية غير فعالة مع NodeVM لذا فهو ليس محصنًا ضد `while (true) {}` أو ما شابه ذلك من الأكواد الضارة.

**تذكر**: كلما زادت الوحدات التي تسمح بها، زادت هشاشة بيئة العزل لديك.```js
import { NodeVM } from 'vm2';

const vm = new NodeVM({
	console: 'inherit',
	sandbox: {},
	require: {
		external: true,
		builtin: ['fs', 'path'],
		root: './',
		mock: {
			fs: {
				readFileSync: () => 'Nice try!',
			},
		},
	},
});

// Sync

let functionInSandbox = vm.run('module.exports = function(who) { console.log("hello "+ who); }');
functionInSandbox('world');

// Async

let functionWithCallbackInSandbox = vm.run('module.exports = function(who, callback) { callback("hello "+ who); }');
functionWithCallbackInSandbox('world', greeting => {
	console.log(greeting);
});

عندما يتم تعيين wrapper إلى none، يتصرف NodeVM بشكل أشبه بـ VM بالنسبة للكود المتزامن.```js assert.ok(vm.run('return true') === true);

root@kitploit:~
**نصيحة**: راجع الاختبارات لمزيد من أمثلة الاستخدام.

### تحميل الوحدات عبر مسار نسبي

لتحميل الوحدات عبر مسار نسبي، يجب عليك تمرير المسار الكامل للبرنامج النصي الذي تقوم بتشغيله كوسيط ثانٍ لطريقة `run` الخاصة بـ vm إذا كان البرنامج النصي عبارة عن سلسلة نصية. يتم بعد ذلك عرض اسم الملف في أي تتبعات مكدس (stack traces) يتم إنشاؤها بواسطة البرنامج النصي.```js
vm.run('require("foobar")', '/data/myvmscript.js');

إذا كان السكربت الذي تقوم بتشغيله هو VMScript، فسيتم إعطاء المسار في مُنشئ VMScript.```js const script = new VMScript('require("foobar")', { filename: '/data/myvmscript.js' }); vm.run(script);

root@kitploit:~
### Resolver

يمكن إنشاء resolver عبر `makeResolverFromLegacyOptions` واستخدامه لعدة نسخ من `NodeVM` مما يسمح بمشاركة كود الوحدة المترجمة وربما تسريع أوقات التحميل. يمكن إعادة كتابة المثال الأول من `NodeVM` باستخدام `makeResolverFromLegacyOptions` على النحو التالي.```js
const resolver = makeResolverFromLegacyOptions({
	external: true,
	builtin: ['fs', 'path'],
	root: './',
	mock: {
		fs: {
			readFileSync: () => 'Nice try!',
		},
	},
});
const vm = new NodeVM({
	console: 'inherit',
	sandbox: {},
	require: resolver,
});

VMScript

يمكنك زيادة الأداء باستخدام السكربتات المترجمة مسبقًا. يمكن تشغيل VMScript المترجم مسبقًا عدة مرات. من المهم ملاحظة أن الكود غير مرتبط بأي VM (سياق)؛ بل يتم ربطه قبل كل تشغيل، فقط لهذا التشغيل.```js import { VM, VMScript } from 'vm2';

const vm = new VM(); const script = new VMScript('Math.random()'); console.log(vm.run(script)); console.log(vm.run(script));

root@kitploit:~
يعمل لكل من `VM` و `NodeVM`.```js
import { NodeVM, VMScript } from 'vm2';

const vm = new NodeVM();
const script = new VMScript('module.exports = Math.random()');
console.log(vm.run(script));
console.log(vm.run(script));

يتم تجميع الكود تلقائيًا في أول مرة يتم تشغيله. يمكن للمرء تجميع الكود في أي وقت باستخدام script.compile(). بمجرد تجميع الكود، لا يكون لهذه الطريقة أي تأثير.

المترجمون

يقبل compiler القيم javascript (الافتراضي)، typescript، coffeescript، أو دالة خاصة بك. مترجما typescript و coffeescript اختياريان — قم بتثبيت الحزمة بنفسك؛ لا يعتمد vm2 على أي منهما.

TypeScript

يتطلب مترجم typescript المدمج إصدار typescript@6 أو إصدارًا أقدم.

يقوم vm2 بالتحويل البرمجي عبر واجهة برمجة التطبيقات transpileModule() الخاصة بـ TypeScript. أزال TypeScript 7 هذه الواجهة من نقطة دخول الحزمة — حيث يتحول require('typescript') هناك إلى { version, versionMajorMinor } فقط، وتقع واجهة الاستبدال خلف المسارات الفرعية غير المستقرة صراحةً typescript/unstable/*، ولا يوفر أي منها بديلًا مكافئًا للتحويل البرمجي لملف واحد. لذلك لا يوجد لدى vm2 أي خيار احتياطي على الإصدار 7.x.

اختيار compiler: 'typescript' مع تثبيت TypeScript 7 يؤدي إلى إلقاء خطأ عند new VMScript(...) / new VM(...):``` VMError: The installed TypeScript (7.0.2) does not expose the transpileModule() API that vm2's built-in TypeScript compiler uses; it was removed from the package entry point in TypeScript 7. Install typescript@6 or earlier, or pass your own transpiler as a function: { compiler: (code, filename) => javaScriptSource }.

root@kitploit:~
إما أن تثبّت `typescript@6`، أو وفّر المترجم الخاص بك — أي دالة تُرجع JavaScript تعمل، لذا فإن `tsc` الخاص بـ TypeScript 7، أو esbuild، أو swc، أو أداة إزالة الأنواع كلها صالحة:```js
import { VM, VMScript } from 'vm2';
import { transformSync } from 'esbuild';

const script = new VMScript('const x: number = 1; x', {
	compiler: (code, filename) => transformSync(code, { loader: 'ts', format: 'cjs' }).code,
});

new VM().run(script);

مُجمِّع مخصص يستقبل (code, filename) ويجب أن يُرجع كود JavaScript. يعمل في نطاق المضيف، قبل العزل (sandboxing) — تعامل معه ككود موثوق ولا تقم أبدًا ببنائه من مدخلات غير موثوقة.

CoffeeScript

يتطلب تثبيت coffee-script. يتم الترجمة باستخدام { header: false, bare: true }؛ أي compilerOptions تمررها سيتم دمجها فوق تلك الخيارات.

معالجة الأخطاء

يمكن التعامل مع الأخطاء في ترجمة الكود وتنفيذ الكود المتزامن باستخدام try-catch. أما الأخطاء في تنفيذ الكود غير المتزامن فيمكن التعامل معها عن طريق إرفاق معالج حدث uncaughtException بعملية Node's process.```js try { var script = new VMScript('Math.random()').compile(); } catch (err) { console.error('Failed to compile script.', err); }

try { vm.run(script); } catch (err) { console.error('Failed to execute script.', err); }

process.on('uncaughtException', err => { console.error('Asynchronous error caught.', err); });

root@kitploit:~
## تصحيح أخطاء الكود المعزول

يمكنك تصحيح أو فحص الكود الذي يعمل داخل العزل (sandbox) كما لو كان يعمل في عملية عادية.

-   يمكنك استخدام نقاط التوقف (breakpoints) (وهذا يتطلب منك تحديد اسم ملف السكربت)
-   يمكنك استخدام الكلمة المفتاحية `debugger`.
-   يمكنك استخدام خطوة-إلى-الداخل (step-in) للدخول داخل الكود الذي يعمل في العزل.

### مثال

/tmp/main.js:```js
import { VM, VMScript } from 'vm2';
import { readFileSync } from 'node:fs';

const file = `${__dirname}/sandbox.js`;

// By providing a file name as second argument you enable breakpoints
const script = new VMScript(readFileSync(file), file);

new VM().run(script);

/tmp/sandbox.js```js const foo = 'ahoj';

// The debugger keyword works just fine everywhere. // Even without specifying a file name to the VMScript object. debugger;

root@kitploit:~
## كائنات للقراءة فقط (تجريبي)

لمنع البرامج النصية المعزولة من إضافة أو تغيير أو حذف الخصائص من الكائنات المُوكَّلة (proxied)، يمكنك استخدام طرق `freeze` لجعل الكائن للقراءة فقط. هذا فعّال فقط داخل VM. الكائنات المجمَّدة تتأثر بعمق. لا يمكن تجميد الأنواع البدائية (Primitive types).

**مثال بدون استخدام `freeze`:**```js
const util = {
	add: (a, b) => a + b,
};

const vm = new VM({
	sandbox: { util },
});

vm.run('util.add = (a, b) => a - b');
console.log(util.add(1, 1)); // returns 0

مثال باستخدام freeze:```js const vm = new VM(); // Objects specified in the sandbox cannot be frozen. vm.freeze(util, 'util'); // Second argument adds object to global.

vm.run('util.add = (a, b) => a - b'); // Fails silently when not in strict mode. console.log(util.add(1, 1)); // returns 2

root@kitploit:~
**مهم:** لا يمكن تجميد الكائنات التي تم بالفعل تمريرها كوسيط (proxy) إلى الآلة الافتراضية.

## الكائنات المحمية (تجريبي)

على عكس `freeze`، تسمح هذه الطريقة للبرامج النصية المعزولة بإضافة أو تغيير أو حذف الخصائص على الكائنات، مع استثناء واحد - لا يمكن إرفاق الدوال. وبالتالي، لا تستطيع البرامج النصية المعزولة تعديل طرق مثل `toJSON` أو `toString` أو `inspect`.

**مهم:** لا يمكن حماية الكائنات التي تم بالفعل تمريرها كوسيط (proxy) إلى الآلة الافتراضية.

## العلاقات عبر العزل (Cross-sandbox)```js
const assert = require('assert');
const { VM } = require('vm2');

const sandbox = {
	object: new Object(),
	func: new Function(),
	buffer: new Buffer([0x01, 0x05]),
};

const vm = new VM({ sandbox });

assert.ok(vm.run(`object`) === sandbox.object);
assert.ok(vm.run(`object instanceof Object`));
assert.ok(vm.run(`object`) instanceof Object);
assert.ok(vm.run(`object.__proto__ === Object.prototype`));
assert.ok(vm.run(`object`).__proto__ === Object.prototype);

assert.ok(vm.run(`func`) === sandbox.func);
assert.ok(vm.run(`func instanceof Function`));
assert.ok(vm.run(`func`) instanceof Function);
assert.ok(vm.run(`func.__proto__ === Function.prototype`));
assert.ok(vm.run(`func`).__proto__ === Function.prototype);

assert.ok(vm.run(`new func() instanceof func`));
assert.ok(vm.run(`new func()`) instanceof sandbox.func);
assert.ok(vm.run(`new func().__proto__ === func.prototype`));
assert.ok(vm.run(`new func()`).__proto__ === sandbox.func.prototype);

assert.ok(vm.run(`buffer`) === sandbox.buffer);
assert.ok(vm.run(`buffer instanceof Buffer`));
assert.ok(vm.run(`buffer`) instanceof Buffer);
assert.ok(vm.run(`buffer.__proto__ === Buffer.prototype`));
assert.ok(vm.run(`buffer`).__proto__ === Buffer.prototype);
assert.ok(vm.run(`buffer.slice(0, 1) instanceof Buffer`));
assert.ok(vm.run(`buffer.slice(0, 1)`) instanceof Buffer);

CLI

قبل أن تتمكن من استخدام vm2 في سطر الأوامر، قم بتثبيته عالميًا باستخدام npm install vm2 -g.```sh vm2 ./script.js

root@kitploit:~
## توصيات التقوية

يمنع vm2 عمليات الهروب من بيئة الاختبار (حصول الكود غير الموثوق على وصول إلى بيئة المضيف). وهو **لا** يمنع، بحد ذاته، كل أشكال استنزاف الموارد أو رفض الخدمة. يجب على المُضمّنين الذين يشغّلون كودًا غير موثوق إضافة الدفاعات الطبقية التالية حول بيئة الاختبار.

### 1. تقييد تخصيص الذاكرة باستخدام `bufferAllocLimit`

استدعاء واحد لـ `Buffer.alloc(N)` مع `N` يتحكم فيه المهاجم يعمل كتخصيص واحد متزامن في C++ على المضيف لا يمكن لمهلة V8 (`timeout`) مقاطعته. في البيئات المقيّدة بالذاكرة، يمكن لحمولة صغيرة في بيئة الاختبار بحجم ~100 بايت أن ترفع استخدام ذاكرة المضيف (RSS) بأكثر من 100 ميجابايت وتُسقط عملية المضيف عبر نفاد الذاكرة (OOM). اضبط `bufferAllocLimit` (مثل `32 * 1024 * 1024`) لتقييد التخصيصات الفردية:```js
const vm = new VM({
	timeout: 1000,
	bufferAllocLimit: 32 * 1024 * 1024,
	allowAsync: false,
});

ينطبق الحد الأقصى أيضًا على مساري Buffer(N) وnew Buffer(N) المهجورين. لاحظ أن الاستنزاف التجميعي (العديد من التخصيصات الصغيرة، Buffer.concat، Uint8Array، String.repeat، Array(n).fill()، وما إلى ذلك) لا يشمله هذا الحد الأقصى — ادمجه مع حد ذاكرة على مستوى المضيف (--max-old-space-size، حد الحاوية، cgroup) لتغطية كاملة.

2. تثبيت معالج unhandledRejection على مستوى المضيف

توجد فئة من هجمات رفض الخدمة (DoS) بإحباط عملية المضيف حيث ينشئ كود بيئة الحماية async function أو async function* أو await using يرمي جسمه قيمة تؤدي إلى خطأ في نطاق المضيف أثناء تنسيق المكدس (مثل e.name = Symbol(); e.stack). ينشئ V8 وعد الرفض عبر Promise الجوهري لنطاق التنفيذ، مما يتجاوز تغليف فئة Promise الفرعية في vm2، لذلك يهرب الرفض إلى المضيف كـ unhandledRejection. في Node 15+ السلوك الافتراضي هو إنهاء العملية.

يتطلب إغلاق هذا الثغرة تغيير سلوك المضيف الملحوظ، لذلك لا يوفر vm2 إصلاحًا افتراضيًا. يجب على المدمجين تثبيت معالج على مستوى العملية يبتلع (أو يسجل) حالات الرفض الناشئة من بيئة الحماية:```js // Recommended: filter rejections that originated inside vm2 and swallow them, // while letting your own host-side rejections propagate. process.on('unhandledRejection', (reason, promise) => { // Heuristic: rejections from the sandbox frequently surface as values // without proper Error semantics, or with stacks pointing at vm.js. // Adjust the predicate to match your application. if (looksLikeSandboxOrigin(reason)) { return; // swallow — don't terminate the process } // Otherwise: handle (or rethrow) as normal for your host code. yourLogger.error('unhandled rejection', reason); });

root@kitploit:~
إذا لم يكن لتطبيقك أي مصدر آخر للرفض غير المعالج، فإن الابتلاع الشامل + التسجيل مقبول:```js
process.on('unhandledRejection', reason => {
	yourLogger.warn('swallowed sandbox rejection', reason);
});

إصلاح مُقيَّد قد يُطرح خلف علامة اختيارية swallowSandboxUnhandledRejections في إصدار ثانوي مستقبلي؛ حتى ذلك الحين، يُعدّ المعالج على جانب المضيف التخفيف الموصى به.

3. التشغيل مع حد أقصى للذاكرة على مستوى العملية

حتى مع ضبط bufferAllocLimit، شغّل عملية المضيف مع --max-old-space-size (أو حد ذاكرة حاوية مكافئ) بحجم يتناسب مع عبء العمل. يحمي الحد الأقصى من بدائية التخصيص الفردي؛ بينما يحمي الحد على مستوى نظام التشغيل من الاستنزاف الكلي ومن أي بدائية تخصيص مستقبلية لم يقم vm2 بتقييدها بعد.

4. التعامل مع require.builtin: ['*'] كتهيئة غير معزولة

يتوسّع حرف البدل '*' ليشمل معظم الوحدات المدمجة في Node، بما في ذلك child_process وfs وdgram وnet وhttp وdns. هذه بدائيات بقدرات مضيف كاملة — require('child_process').execSync('id') يمكن الوصول إليه من داخل العزل تحت '*'. دلالات '*' في vm2 مقصودة (بعض المُضمِّنين يشغّلون كودًا موثوقًا لكن معزولًا)، لكن لا ينبغي استخدامها كإعداد افتراضي للكود غير الموثوق. فضّل قائمة سماح صريحة بأصغر مجموعة وحدات يحتاجها عزلك فعليًا.

5. nesting: true هو باب هروب

يتيح nesting: true لكود العزل تنفيذ require('vm2') وبناء NodeVMs متداخلة. تهيئة require للـ VM المتداخل تُختار بواسطة كود العزل الذي يبنيها، وليست مقيّدة بالـ VM الخارجي. تحديدًا:```js const vm = new NodeVM({ nesting: true, require: { builtin: [] } }); vm.run( const { NodeVM: NVM } = require('vm2'); // Inner VM's config is whatever the sandbox writes here: const inner = new NVM({ require: { builtin: ['child_process'] } }); inner.run('require("child_process").execSync("id")'); // RCE);

root@kitploit:~
إذا قمت بتعيين `nesting: true`، فأنت بذلك منحت الصندوق الرملي نفس مستوى الثقة الذي تتمتع به أنت. **لا تقم بتفعيل `nesting: true` للكود غير الموثوق.** استخدمه فقط عندما تثق بالكود داخل الصندوق الرملي نفسه ولكنك تريد دلالات تنفيذ بنمط VM (بيئة عامة جديدة، مهلات زمنية محكومة) لأسباب غير أمنية.

`nesting: true` **يتطلب كائن إعدادات `require` صريحًا** (مثل `require: { builtin: [] }` أو `require: {}`). أي شكل آخر — `require: false`، أو `require: undefined`، أو `require: null`، أو حذف `require` تمامًا — يرمي خطأ `VMError` عند الإنشاء (GHSA-m4wx-m65x-ghrr، يحل محل GHSA-8hg8-63c5-gwmx). جميع هذه الأشكال تنتج محللًا من نوع NESTING_OVERRIDE فقط: يمكن للصندوق الرملي استدعاء `require('vm2')` ولكن لا شيء آخر، وهو بدائية هروب خالصة لا فائدة مشروعة منها. لمنع جميع الاستدعاءات، قم بإزالة `nesting: true`. للسماح بـ VMs متداخلة، قم بتوفير إعداد `require` صريح بحيث يكون المقايض مرئيًا في موقع الاستدعاء.

## المشكلات المعروفة

-   ليس من الممكن تعريف فئة تمتد من فئة مُوكَّلة (proxied class). يتضمن ذلك استخدام فئة مُوكَّلة في `Object.create`.
-   التقييم المباشر (Direct eval) لا يعمل.
-   تسجيل مصفوفات الصندوق الرملي سيكرر جزء المصفوفة في الخصائص.
-   تحويلات الكود المصدري يمكن أن تؤدي إلى سلسلة مصدر مختلفة للدالة.
-   هناك طرق لتعطيل عملية node من داخل الصندوق الرملي. راجع [توصيات التقوية](#hardening-recommendations).
-   مترجم `typescript` المدمج لا يعمل مع TypeScript 7 أو أحدث، الذي أزال واجهة برمجة التطبيقات `transpileModule()` التي يستخدمها vm2. استخدم `typescript@6` أو مرر المترجم الخاص بك — راجع [المترجمون](#compilers).

[npm-image]: https://img.shields.io/npm/v/vm2.svg
[npm-url]: https://www.npmjs.com/package/vm2
[license-image]: https://img.shields.io/npm/l/vm2.svg
[license-url]: https://raw.githubusercontent.com/patriksimek/vm2/resurrection/LICENSE.md
[downloads-image]: https://img.shields.io/npm/dm/vm2.svg
[downloads-url]: https://www.npmjs.com/package/vm2
[snyk-image]: https://snyk.io/test/github/patriksimek/vm2/badge.svg
[snyk-url]: https://snyk.io/test/github/patriksimek/vm2
تنزيل الأداة
الخيارالوصف
-h, --helpعرض رسالة المساعدة والخروج
-v, --verboseتفعيل وضع الإخراج المفصل
-o, --output <file>حفظ النتائج في ملف محدد
-t, --timeout <seconds>تعيين مهلة زمنية للطلبات (الافتراضي: 30)
جدول بيانات للتحليل
HTML.htmlتقرير قابل للقراءة
الخيارالوصف
--targetالهدف المراد فحصه (مطلوب)
--verboseإخراج تفصيلي
--outputملف الإخراج
--threadsعدد الخيوط المتوازية
--timeoutمهلة الطلب بالثواني