
vm2 v3.11.6
Node.js के लिए पृथक JavaScript सैंडबॉक्स जो Proxy-आधारित इंटरसेप्शन के माध्यम से बिल्ट-इन मॉड्यूल और होस्ट संसाधनों तक प्रतिबंधित पहुँच के साथ अविश्वसनीय कोड चलाता है।
vm2 [![NPM Version][npm-image]][npm-url] [![NPM Downloads][downloads-image]][downloads-url] [![License][license-image]][license-url]
[![Known Vulnerabilities][snyk-image]][snyk-url]
vm2 एक सैंडबॉक्स है जो अनट्रस्टेड कोड को व्हाइटलिस्टेड Node के बिल्ट-इन मॉड्यूल के साथ चला सकता है।
इंस्टॉलेशन```sh
npm install vm2
## त्वरित उदाहरण```js
import { VM } from 'vm2';
const vm = new VM();
vm.run(`process.exit()`); // TypeError: process.exit is not a function
मैं आपकी मदद करने के लिए यहाँ हूँ, लेकिन आपने कोई इनपुट प्रदान नहीं किया है। कृपया वह Markdown सामग्री साझा करें जिसे आप अनुवाद करना चाहते हैं, और मैं इसे हिंदी में अनुवाद कर दूँगा।```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',
);
## महत्वपूर्ण सुरक्षा अस्वीकरण
**vm2 का उपयोग करने से पहले, आपको समझना चाहिए कि यह कैसे काम करता है और इसकी सीमाएँ क्या हैं।**
vm2 अविश्वसनीय JavaScript कोड को आपके एप्लिकेशन के **उसी Node.js प्रोसेस के भीतर** सैंडबॉक्स करने का प्रयास करता है। यह [Proxies](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Proxy) के एक जटिल नेटवर्क के माध्यम से ऐसा करता है जो सैंडबॉक्स और होस्ट वातावरण के बीच हर इंटरैक्शन को इंटरसेप्ट और मध्यस्थ करता है।
### मूलभूत चुनौती
JavaScript एक अत्यंत गतिशील भाषा है। ऑब्जेक्ट्स को प्रोटोटाइप चेन के माध्यम से एक्सेस किया जा सकता है, कंस्ट्रक्टर्स को एरर ऑब्जेक्ट्स के माध्यम से पहुँचा जा सकता है, सिंबल प्रोटोकॉल हुक प्रदान करते हैं, और एसिंक्रोनस निष्पादन टाइमिंग विंडो बनाता है। 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 अपडेट की आवश्यकता |
| **अलग प्रोसेस / वर्कर** | `child_process` या सीमित अनुमतियों वाले वर्कर थ्रेड | मध्यम | उच्च IPC ओवरहेड; डेटा को सीरियलाइज़ किया जाना चाहिए |
| **कंटेनर / VM** | Docker, gVisor, Firecracker | धीमा | स्टार्टअप ओवरहेड; संसाधन-भारी |
| **प्रबंधित सेवाएँ** | क्लाउड-आधारित कोड निष्पादन (जैसे, AWS Lambda, Cloudflare Workers) | परिवर्तनशील | नेटवर्क विलंबता; बाहरी निर्भरता |
### vm2 कब अभी भी उपयुक्त हो सकता है
vm2 तब उपयुक्त हो सकता है जब:
- आपको होस्ट ऑब्जेक्ट्स के साथ घनिष्ठ एकीकरण और तेज़ सिंक्रोनस संचार की आवश्यकता हो
- अविश्वसनीय कोड अपेक्षाकृत विश्वसनीय स्रोत से आता है (जैसे, आंतरिक उपकरण, सत्यापित लेखकों वाले प्लगइन सिस्टम)
- आप vm2 को अन्य सुरक्षा परतों के साथ जोड़ते हैं (नेटवर्क अलगाव, फाइलसिस्टम प्रतिबंध, संसाधन सीमाएँ)
- आप जोखिम स्वीकार करते हैं और सुरक्षा अपडेट के लिए सक्रिय रूप से निगरानी करते हैं
**यदि आप पूरी तरह से अविश्वसनीय स्रोतों (जैसे, मनमाने उपयोगकर्ता सबमिशन) से कोड चला रहे हैं, तो हम दृढ़ता से मजबूत अलगाव गारंटी वाले समाधान का उपयोग करने की सलाह देते हैं।**
## रनटाइम
| रनटाइम | स्थिति |
|---------|--------|
| 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 के अंतर्गत सूट का पास होना संगतता प्रदर्शित करता है, यह नहीं कि सैंडबॉक्स वहाँ टिकता है। **अविश्वसनीय कोड को अलग करने के लिए Bun पर vm2 का उपयोग न करें।**
**संगतता आंशिक है, समानता नहीं।** एक हरा Bun रन केवल उन परीक्षणों को कवर करता है जो वास्तव में वहाँ निष्पादित होते हैं। `test/bun-skips.js` सूचीबद्ध करता है कि क्या बाहर रखा गया है और क्यों, और ज्ञात व्यवहारिक अंतरालों में शामिल हैं:
- `Buffer.from(arrayLike)` शून्य-लंबाई वाला बफर लौटाता है
- `VMScript` `filename` / `lineOffset` / `columnOffset` मेटाडेटा अवलोकन योग्य नहीं है, क्योंकि JSC के CallSite ऑब्जेक्ट्स में कोई विधियाँ नहीं होती हैं
- एक गैर-कॉन्फ़िगर करने योग्य एक्सेसर के साथ जमे हुए होस्ट ऑब्जेक्ट पर `Object.freeze` एक प्रॉक्सी-इनवेरिएंट `TypeError` फेंकता है जहाँ V8 नहीं फेंकता
- सैंडबॉक्स सीमा के पार कुछ `Buffer` ऑपरेशन काफी धीमे हैं — एक 64 MB `allocUnsafe` Node पर 1.7 के मुकाबले 400 सेकंड से अधिक लेता है, इतना धीमा कि हैंग जैसा लगे
Bun समर्थन को विश्वसनीय कोड के लिए सर्वोत्तम-प्रयास संगतता के रूप में मानें, और किसी विशेष व्यवहार पर भरोसा करने से पहले स्किप सूची की जाँच करें।
## विशेषताएँ
- अविश्वसनीय कोड को आपके कोड के साथ एक ही प्रोसेस में सुरक्षित रूप से चलाता है
- सैंडबॉक्स के कंसोल आउटपुट पर पूर्ण नियंत्रण
- सैंडबॉक्स की प्रोसेस की विधियों तक सीमित पहुँच होती है
- सैंडबॉक्स से मॉड्यूल (बिल्ट-इन और बाहरी) को require करना संभव है
- आप कुछ (या सभी) बिल्ट-इन मॉड्यूल तक पहुँच सीमित कर सकते हैं
- आप सैंडबॉक्स के बीच विधियों को सुरक्षित रूप से कॉल कर सकते हैं और डेटा तथा कॉलबैक का आदान-प्रदान कर सकते हैं
- ज्ञात एस्केप विधियों के पैच के साथ सक्रिय रूप से बनाए रखा गया (देखें [सुरक्षा अस्वीकरण](#important-security-disclaimer))
- ट्रांसपाइलर समर्थन
## यह कैसे काम करता है
- यह एक सुरक्षित संदर्भ बनाने के लिए आंतरिक 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) देखें।
## Node के vm और vm2 के बीच क्या अंतर है?
इसे स्वयं आज़माएँ:```js
import { runInNewContext } from "node:vm";
runInNewContext('this.constructor.constructor("return process")().exit()');
console.log('Never gets executed.');
मैं देख रहा हूँ कि आपने इनपुट प्रदान नहीं किया है। कृपया वह Markdown सामग्री भेजें जिसे आप अनुवाद करना चाहते हैं, और मैं इसे हिंदी में अनुवाद कर दूँगा।```js import { VM } from 'vm2';
new VM().run('this.constructor.constructor("return process")().exit()'); // Throws ReferenceError: process is not defined
## दस्तावेज़ीकरण
- [VM](#vm)
- [NodeVM](#nodevm)
- [VMScript](#vmscript)
- [त्रुटि प्रबंधन](#error-handling)
- [सैंडबॉक्स किए गए कोड की डिबगिंग](#debugging-a-sandboxed-code)
- [केवल-पठनीय ऑब्जेक्ट](#read-only-objects-experimental)
- [संरक्षित ऑब्जेक्ट](#protected-objects-experimental)
- [क्रॉस-सैंडबॉक्स संबंध](#cross-sandbox-relationships)
- [CLI](#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 के अंतर्निहित ऑब्जेक्ट और Node का `Buffer` उपलब्ध होता है। शेड्यूलिंग फ़ंक्शन (`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) में अविश्वसनीय कोड चलाने वाले एम्बेडर्स को स्तरित DoS रक्षा के हिस्से के रूप में एक सीमित कैप (जैसे `32 * 1024 * 1024`) चुनना चाहिए, उसी तरह जैसे वे `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
आप VM से भी मान प्राप्त कर सकते हैं।```js let number = vm.run('1337'); // returns 1337
**टिप**: अधिक उपयोग उदाहरणों के लिए परीक्षण देखें।
## NodeVM
`VM` के विपरीत, `NodeVM` आपको मॉड्यूल को उसी तरह require करने की अनुमति देता है जैसे आप नियमित 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` - `require` विधि सक्षम करने के लिए `true`, एक ऑब्जेक्ट या एक Resolver (डिफ़ॉल्ट: `false`)।
- `require.external` - मान `true`, अनुमत बाहरी मॉड्यूल की सरणी, या एक ऑब्जेक्ट हो सकते हैं (डिफ़ॉल्ट: `false`)। `/node_modules/${any_allowed_external_module}/(?!/node_modules/)` से मेल खाने वाले सभी पथ require करने की अनुमति है।
- `require.external.modules` - अनुमत बाहरी मॉड्यूल की सरणी। वाइल्डकार्ड का भी समर्थन करता है, इसलिए उदाहरण के लिए `['@scope/*-ver-??]` निर्दिष्ट करने से `@scope/something-ver-aa`, `@scope/other-ver-11`, आदि के रूप में नाम वाले सभी मॉड्यूल का उपयोग करने की अनुमति मिलेगी। `*` वाइल्डकार्ड पथ विभाजकों से मेल नहीं खाता।
- `require.external.transitive` - बूलियन जो इंगित करता है कि बाहरी मॉड्यूल की ट्रांज़िटिव निर्भरताएँ अनुमत हैं या नहीं (डिफ़ॉल्ट: `false`)। **चेतावनी**: जब कोई मॉड्यूल ट्रांज़िटिव रूप से require किया जाता है, तो कोई भी मॉड्यूल उसे सामान्य रूप से require कर सकता है, भले ही लोड होने से पहले यह संभव न हो।
- `require.builtin` - अनुमत बिल्ट-इन मॉड्यूल की सरणी, सभी के लिए ["\*"] स्वीकार करता है (डिफ़ॉल्ट: कोई नहीं)। **चेतावनी**: "\*" खतरनाक हो सकता है क्योंकि नए बिल्ट-इन जोड़े जा सकते हैं।
- `require.root` - प्रतिबंधित पथ जहाँ स्थानीय मॉड्यूल require किए जा सकते हैं (डिफ़ॉल्ट: हर पथ)।
- `require.mock` - मॉक मॉड्यूल का संग्रह (बाहरी या बिल्ट-इन दोनों)।
- `require.context` - होस्ट में मॉड्यूल require करने और उन्हें सैंडबॉक्स में प्रॉक्सी करने के लिए `host` (डिफ़ॉल्ट)। सैंडबॉक्स में मॉड्यूल लोड, संकलित और require करने के लिए `sandbox`। प्रति मॉड्यूल संदर्भ को गतिशील रूप से चुनने के लिए `callback(moduleFilename, ext)`। यदि कुछ भी निर्दिष्ट नहीं है तो डिफ़ॉल्ट सैंडबॉक्स होगा। `events` को छोड़कर, बिल्ट-इन मॉड्यूल हमेशा होस्ट में require किए जाते हैं और सैंडबॉक्स में प्रॉक्सी किए जाते हैं।
- `require.import` - स्टार्ट पर NodeVM में लोड किए जाने वाले मॉड्यूल की सरणी।
- `require.resolve` - एक अतिरिक्त लुकअप फ़ंक्शन यदि कोई मॉड्यूल पारंपरिक node लुकअप पथों में से किसी में नहीं मिला।
- `require.customRequire` - होस्ट से मॉड्यूल लोड करने के लिए `require` फ़ंक्शन के बजाय उपयोग करें।
- `require.strict` - require द्वारा लोड किए गए मॉड्यूल पर सख्त मोड लागू न करने के लिए `false` (डिफ़ॉल्ट: `true`)।
- `require.fs` - कस्टम फ़ाइल सिस्टम कार्यान्वयन।
- `nesting` - **चेतावनी**: इसे अनुमति देना एक सुरक्षा जोखिम है क्योंकि स्क्रिप्ट एक NodeVM बना सकती हैं जो किसी भी होस्ट मॉड्यूल को require कर सकती है। VM नेस्टिंग सक्षम करने के लिए `true` (डिफ़ॉल्ट: `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);
**टिप**: अधिक उपयोग उदाहरणों के लिए परीक्षण देखें।
### सापेक्ष पथ द्वारा मॉड्यूल लोड करना
सापेक्ष पथ द्वारा मॉड्यूल लोड करने के लिए, यदि स्क्रिप्ट एक स्ट्रिंग है, तो आपको vm के `run` विधि में दूसरे तर्क के रूप में चलाए जा रहे स्क्रिप्ट का पूरा पथ पास करना होगा। फिर फ़ाइलनाम स्क्रिप्ट द्वारा उत्पन्न किसी भी स्टैक ट्रेस में प्रदर्शित होता है।```js
vm.run('require("foobar")', '/data/myvmscript.js');
यदि आप जो स्क्रिप्ट चला रहे हैं वह एक VMScript है, तो पथ VMScript कंस्ट्रक्टर में दिया गया है।```js const script = new VMScript('require("foobar")', { filename: '/data/myvmscript.js' }); vm.run(script);
### रिज़ॉल्वर
एक रिज़ॉल्वर को `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));
यह `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 TypeScript के transpileModule() API के माध्यम से ट्रांसपाइल करता है। TypeScript 7 ने इसे पैकेज के एंट्री पॉइंट से हटा दिया — वहाँ require('typescript') केवल { version, versionMajorMinor } को हल करता है, और प्रतिस्थापन API स्पष्ट रूप से अस्थिर typescript/unstable/* सबपाथ के पीछे है, जिनमें से कोई भी सिंगल-फ़ाइल ट्रांसपाइल के समकक्ष प्रदान नहीं करता। इसलिए vm2 के पास 7.x पर वापस गिरने के लिए कुछ भी नहीं है।
TypeScript 7 इंस्टॉल होने पर compiler: 'typescript' चुनने से 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 }.
या तो `typescript@6` पिन करें, या अपना खुद का ट्रांसपाइलर प्रदान करें — कोई भी फ़ंक्शन जो जावास्क्रिप्ट लौटाता है वह काम करता है, इसलिए TypeScript 7 का `tsc`, 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 सोर्स लौटाना होता है। यह होस्ट रियल्म में, सैंडबॉक्सिंग से पहले चलता है — इसे विश्वसनीय कोड मानें और कभी भी अविश्वसनीय इनपुट से इसे न बनाएं।
CoffeeScript
coffee-script इंस्टॉल होना आवश्यक है। { header: false, bare: true } के साथ कंपाइल किया गया; आपके द्वारा पास किए गए कोई भी compilerOptions उन पर मर्ज किए जाते हैं।
त्रुटि प्रबंधन
कोड कंपाइलेशन और सिंक्रोनस कोड निष्पादन में त्रुटियों को try-catch द्वारा संभाला जा सकता है। एसिंक्रोनस कोड निष्पादन में त्रुटियों को Node के process पर uncaughtException इवेंट हैंडलर जोड़कर संभाला जा सकता है।```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); });
## सैंडबॉक्स किए गए कोड की डिबगिंग
आप सैंडबॉक्स में चल रहे कोड को डिबग या निरीक्षण कर सकते हैं, जैसे कि यह एक सामान्य प्रक्रिया में चल रहा हो।
- आप ब्रेकपॉइंट का उपयोग कर सकते हैं (जिसके लिए आपको एक स्क्रिप्ट फ़ाइल नाम निर्दिष्ट करना होगा)
- आप `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;
## रीड-ओनली ऑब्जेक्ट्स (प्रयोगात्मक)
सैंडबॉक्स किए गए स्क्रिप्ट्स को प्रॉक्सी किए गए ऑब्जेक्ट्स से प्रॉपर्टीज़ जोड़ने, बदलने, या हटाने से रोकने के लिए, आप ऑब्जेक्ट को रीड-ओनली बनाने के लिए `freeze` मेथड्स का उपयोग कर सकते हैं। यह केवल VM के अंदर प्रभावी है। फ्रोज़न ऑब्जेक्ट्स गहराई से प्रभावित होते हैं। प्रिमिटिव टाइप्स को फ्रोज़ नहीं किया जा सकता।
**`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
**महत्वपूर्ण:** उन ऑब्जेक्ट्स को फ्रीज़ करना संभव नहीं है जिन्हें पहले ही VM में प्रॉक्सी किया जा चुका है।
## संरक्षित ऑब्जेक्ट्स (प्रयोगात्मक)
`freeze` के विपरीत, यह विधि सैंडबॉक्स्ड स्क्रिप्ट्स को ऑब्जेक्ट्स पर प्रॉपर्टीज़ जोड़ने, बदलने या हटाने की अनुमति देती है, एक अपवाद के साथ - फ़ंक्शन संलग्न करना संभव नहीं है। इसलिए सैंडबॉक्स्ड स्क्रिप्ट्स `toJSON`, `toString` या `inspect` जैसे मेथड्स को संशोधित करने में सक्षम नहीं हैं।
**महत्वपूर्ण:** उन ऑब्जेक्ट्स को संरक्षित करना संभव नहीं है जिन्हें पहले ही VM में प्रॉक्सी किया जा चुका है।
## क्रॉस-सैंडबॉक्स संबंध```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
## हार्डनिंग अनुशंसाएँ
vm2 सैंडबॉक्स एस्केप (अविश्वसनीय कोड द्वारा होस्ट रियल्म एक्सेस प्राप्त करना) को रोकता है। यह अपने आप में, संसाधन क्षय या डिनायल-ऑफ-सर्विस के हर रूप को नहीं रोकता है। अविश्वसनीय कोड चलाने वाले एम्बेडर्स को सैंडबॉक्स के चारों ओर निम्नलिखित स्तरित सुरक्षा उपाय जोड़ने चाहिए।
### 1. `bufferAllocLimit` के साथ मेमोरी आवंटन को सीमित करें
हमलावर-नियंत्रित `N` के साथ एक एकल `Buffer.alloc(N)` कॉल एक सिंक्रोनस होस्ट C++ आवंटन के रूप में चलती है जिसे V8 का `timeout` बाधित नहीं कर सकता। मेमोरी-प्रतिबंधित वातावरण में, ~100-बाइट का सैंडबॉक्स पेलोड 100 MB+ होस्ट RSS में वृद्धि कर सकता है और OOM के माध्यम से होस्ट प्रक्रिया को क्रैश कर सकता है। व्यक्तिगत आवंटन को सीमित करने के लिए `bufferAllocLimit` (जैसे `32 * 1024 * 1024`) सेट करें:```js
const vm = new VM({
timeout: 1000,
bufferAllocLimit: 32 * 1024 * 1024,
allowAsync: false,
});
यह कैप deprecated 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 के माध्यम से बनाता है, जो vm2 के Promise सबक्लास रैप को बायपास करता है, इसलिए रिजेक्शन होस्ट तक 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); });
यदि आपके एप्लिकेशन में अनहैंडल्ड रिजेक्शन का कोई अन्य स्रोत नहीं है, तो एक सामान्य स्वॉलो + लॉग स्वीकार्य है:```js
process.on('unhandledRejection', reason => {
yourLogger.warn('swallowed sandbox rejection', reason);
});
एक स्कोप्ड फिक्स भविष्य के माइनर रिलीज़ में एक ऑप्ट-इन swallowSandboxUnhandledRejections फ्लैग के पीछे आ सकता है; तब तक, होस्ट-साइड हैंडलर ही अनुशंसित शमन है।
3. प्रोसेस-स्तरीय मेमोरी कैप के साथ चलाएँ
bufferAllocLimit सेट होने पर भी, होस्ट प्रोसेस को वर्कलोड के अनुरूप --max-old-space-size (या एक समकक्ष कंटेनर मेमोरी सीमा) के साथ चलाएँ। कैप सिंगल-एलोकेशन प्रिमिटिव से सुरक्षा करता है; OS-स्तरीय सीमा समग्र थकावट और किसी भी भविष्य के एलोकेशन प्रिमिटिव से सुरक्षा करती है जिसे vm2 ने अभी तक कैप नहीं किया है।
4. require.builtin: ['*'] को एक गैर-सैंडबॉक्स कॉन्फ़िगरेशन के रूप में मानें
'*' वाइल्डकार्ड अधिकांश Node बिल्ट-इन्स तक विस्तारित होता है, जिसमें child_process, fs, dgram, net, http, और dns शामिल हैं। ये पूर्ण होस्ट-क्षमता वाले प्रिमिटिव हैं — require('child_process').execSync('id') '*' के अंतर्गत सैंडबॉक्स से पहुँचा जा सकता है। vm2 के '*' सेमेन्टिक्स जानबूझकर हैं (कुछ एम्बेडर विश्वसनीय-लेकिन-पृथक कोड चलाते हैं), लेकिन इसे अविश्वसनीय कोड के लिए डिफ़ॉल्ट के रूप में उपयोग नहीं किया जाना चाहिए। अपने सैंडबॉक्स को वास्तव में जिन मॉड्यूल्स की आवश्यकता है, उनके सबसे छोटे सेट की एक स्पष्ट अनुमतिसूची (allowlist) को प्राथमिकता दें।
5. nesting: true एक एस्केप हैच है
nesting: true सैंडबॉक्स कोड को require('vm2') करने और नेस्टेड NodeVMs बनाने की अनुमति देता है। नेस्टेड VM का require कॉन्फ़िग उस सैंडबॉक्स कोड द्वारा चुना जाता है जो इसे बनाता है, न कि बाहरी 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);
यदि आप `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')` कर सकता है लेकिन और कुछ नहीं, जो कि बिना किसी वैध उपयोग के एक शुद्ध एस्केप प्रिमिटिव है। सभी requires को अस्वीकार करने के लिए, `nesting: true` हटा दें। नेस्टेड VM की अनुमति देने के लिए, एक स्पष्ट `require` कॉन्फ़िग प्रदान करें ताकि कॉल साइट पर ट्रेड-ऑफ़ दिखाई दे।
## ज्ञात समस्याएँ
- ऐसी क्लास को परिभाषित करना संभव नहीं है जो प्रॉक्सी की गई क्लास का विस्तार करती है। इसमें `Object.create` में प्रॉक्सी की गई क्लास का उपयोग करना शामिल है।
- डायरेक्ट eval काम नहीं करता है।
- सैंडबॉक्स ऐरे को लॉग करने से प्रॉपर्टीज़ में ऐरे भाग की पुनरावृत्ति होगी।
- सोर्स कोड ट्रांसफ़ॉर्मेशन के परिणामस्वरूप किसी फ़ंक्शन के लिए एक अलग सोर्स स्ट्रिंग हो सकती है।
- सैंडबॉक्स के अंदर से node प्रक्रिया को क्रैश करने के तरीके हैं। [हार्डनिंग अनुशंसाएँ](#hardening-recommendations) देखें।
- बिल्ट-इन `typescript` कंपाइलर TypeScript 7 या उससे नए संस्करण के साथ काम नहीं करता है, जिसने vm2 द्वारा उपयोग किए जाने वाले `transpileModule()` API को हटा दिया है। `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