今回は、Node.jsサンドボックス環境を使用する手順について詳しく説明します。Node.jsサンドボックス環境を使用する際の注意事項は何ですか?実際の事例を見てみましょう。
Node の公式ドキュメントには、ノードの vm モジュールを使用してサンドボックス環境でコードを実行し、コードのコンテキストを分離できると記載されています。一般的な使用例は、サンドボックス環境でコードを実行することです。サンドボックス コードは、コードの残りの部分とは異なるグローバル オブジェクトを持つことを意味します。まず例を見てみましょう。サンドボックス環境で実行されるコードは、新しく宣言された変数 b であっても、再割り当てされた変数 a であっても、外部コードには影響を与えません。 コードの最後の行はデフォルトで return キーワードを使用して追加されるため、手動で追加する必要はありません。追加すると無視されることはありませんが、エラーが報告されます。const vm = require('vm'); let a = 1; var result = vm.runInNewContext('var b = 2; a = 3; a + b;', {a}); console.log(result); // 5 console.log(a); // 1 console.log(typeof b); // undefinedログイン後にコピー
const vm = require('vm'); let a = 1; var result = vm.runInNewContext('var b = 2; a = 3; return a + b;', {a}); console.log(result); console.log(a); console.log(typeof b);
以下に示すように
evalmachine.<anonymous>:1 var b = 2; a = 3; return a + b; ^^^^^^ SyntaxError: Illegal return statement at new Script (vm.js:74:7) at createScript (vm.js:246:10) at Object.runInNewContext (vm.js:291:10) at Object.<anonymous> (/Users/xiji/workspace/learn/script.js:3:17) at Module._compile (internal/modules/cjs/loader.js:678:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:689:10) at Module.load (internal/modules/cjs/loader.js:589:32) at tryModuleLoad (internal/modules/cjs/loader.js:528:12) at Function.Module._load (internal/modules/cjs/loader.js:520:3) at Function.Module.runMain (internal/modules/cjs/loader.js:719:10)
runInNewContext に加えて、vm には runInThisContext と runInContext という 2 つのメソッドも用意されており、どちらもコードの実行に使用できます。 runInThisContext ではコンテキストを指定できません
const vm = require('vm'); let localVar = 'initial value'; const vmResult = vm.runInThisContext('localVar += "vm";'); console.log('vmResult:', vmResult); console.log('localVar:', localVar); console.log(global.localVar);
ローカル スコープにはアクセスできないため、現在のものはグローバルオブジェクトにアクセスできるため、上記のコードはlocalValが見つからないためエラーを報告します
evalmachine.<anonymous>:1 localVar += "vm"; ^ ReferenceError: localVar is not defined at evalmachine.<anonymous>:1:1 at Script.runInThisContext (vm.js:91:20) at Object.runInThisContext (vm.js:298:38) at Object.<anonymous> (/Users/xiji/workspace/learn/script.js:3:21) at Module._compile (internal/modules/cjs/loader.js:678:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:689:10) at Module.load (internal/modules/cjs/loader.js:589:32) at tryModuleLoad (internal/modules/cjs/loader.js:528:12) at Function.Module._load (internal/modules/cjs/loader.js:520:3) at Function.Module.runMain (internal/modules/cjs/loader.js:719:10)
実行するコードを直接代入に変更すると正常に実行されますが、グローバル汚染も引き起こします( global localVar 変数)
const vm = require('vm'); let localVar = 'initial value'; const vmResult = vm.runInThisContext('localVar = "vm";'); console.log('vmResult:', vmResult); // vm console.log('localVar:', localVar); // initial value console.log(global.localVar); // vm
runInContext は、渡される context パラメーターにおいて runInNewContext とは異なります。 runInContext によって渡される context オブジェクトは空ではないため、vm.createContext() によって処理する必要があります。それ以外の場合は、エラーが報告されます。 runInNewContext の context パラメータはオプションであり、vm.createContext によって処理される必要はありません。 runInNewContext と runInContext には指定されたコンテキストがあるため、runInThisContext のようなグローバルな汚染を引き起こすことはありません (グローバルな localVar 変数は生成されません)
const vm = require('vm'); let localVar = 'initial value'; const vmResult = vm.runInNewContext('localVar = "vm";'); console.log('vmResult:', vmResult); // vm console.log('localVar:', localVar); // initial value console.log(global.localVar); // undefined
複数のスクリプト フラグメントを実行するためにサンドボックス環境が必要な場合、 runInContext メソッドを複数回呼び出すことができます。同じ vm.createContext() 戻り値の実装を渡します。
タイムアウト制御とエラーキャプチャ
vmは、タイムアウトパラメータを指定することで、例としてInThisContextを実行できますtry catch
const vm = require('vm'); let localVar = 'initial value'; const vmResult = vm.runInThisContext('while(true) { 1 }; localVar = "vm";', { timeout: 1000});
vm を実行するには、コードをすぐに実行するだけでなく、最初にコードをコンパイルして、しばらくしてから実行することもできます。これには、vm.Script を指定する必要があります。実際、runInNewContext、runInThisContext、または runInThisContext のいずれであっても、実際にはその背後で Script が作成されていることがわかります。次に、vm.Script を使用してこの記事の冒頭の例を書き直しますvm.js:91
return super.runInThisContext(...args);
^
Error: Script execution timed out.
at Script.runInThisContext (vm.js:91:20)
at Object.runInThisContext (vm.js:298:38)
at Object.<anonymous> (/Users/xiji/workspace/learn/script.js:3:21)
at Module._compile (internal/modules/cjs/loader.js:678:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:689:10)
at Module.load (internal/modules/cjs/loader.js:589:32)
at tryModuleLoad (internal/modules/cjs/loader.js:528:12)
at Function.Module._load (internal/modules/cjs/loader.js:520:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:719:10)
at startup (internal/bootstrap/node.js:228:19)
const vm = require('vm'); let localVar = 'initial value'; try { const vmResult = vm.runInThisContext('while(true) { 1 }; localVar = "vm";', { timeout: 1000 }); } catch(e) { console.error('executed code timeout'); }
vm をサンドボックス環境 としてサポートすることは安全ですか?
vm は現在のコンテキストを分離するため eval より安全ですが、それでも標準の JS API とグローバル NodeJS 環境にアクセスできるため、vm は安全ではありません。これは公式ドキュメントに記載されています。 vm モジュールはセキュリティ機構ではありません。信頼できないコードの実行には使用しないでください以下の例を参照してくださいconst vm = require('vm');
let a = 1;
var script = new vm.Script('var b = 2; a = 3; a + b;');
setTimeout(() => {
let result = script.runInNewContext({a});
console.log(result); // 5
console.log(a); // 1
console.log(typeof b); // undefined
}, 300);
node --experimental-vm-module index.js
ネイティブvmのこの問題を考慮して、上記の問題を回避できるvm2パッケージを開発された方がいらっしゃいますが、必ずしもvm2が安全とは言えません
const vm = require('vm'); vm.runInNewContext("this.constructor.constructor('return process')().exit()") console.log("The app goes on...") // 永远不会输出
上記コードの実行には問題ありませんが、 to vm2 タイムアウトは非同期コードには影響しないため、以下のコードは実行を終了しません。Promise を再定義して Promise を無効にしたい場合でも、バイパスすることができますlet ctx = Object.create(null); ctx.a = 1; // ctx上不能包含引用类型的属性 vm.runInNewContext("this.constructor.constructor('return process')().exit()", ctx);ログイン後にコピー
const {VM} = require('vm2'); new VM().run('this.constructor.constructor("return process")().exit()');
この記事の事例を読んだ後は、方法を習得したと思います。さらに興味深い情報については、他の関連記事に注目してください。 PHP中国語ウェブサイトです!
推奨読書:
Vue プロジェクト Webpack をパッケージ化してデプロイするときに Tomcat によって報告される 404 エラーに対処するにはどうすればよいですか?
以上がNode.jsサンドボックス環境の利用手順を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。