2011-09-16 37 views
33

在node.js中安全地運行(可能是惡意的)用戶提交的腳本有哪些選項?即在阻止代碼訪問敏感數據和API的環境中?如何在node.js沙箱中安全地運行用戶提交的腳本?

vm.runInNewContext(userScript, {})是一個誘人的起點...但它似乎有known issues那裏。

sandbox module看起來很有趣,但也使用runInNewContext(),所以我有點懷疑它。

+0

我推薦使用'vm',因爲它是節點核心的一部分。並且由於節點核心傾向於修復它的錯誤,所以假設問題將被修復 – Raynos

+0

@Raynos它不是一個錯誤。文檔說這隻適用於已知好的代碼。 – thejh

+0

@thejh - true,但是API確實適合相當合理的信念,即代碼在完全不同的上下文中執行,這意味着所述代碼不應該能夠訪問當前上下文。我期望API的* intent *就是 - 提供一個運行腳本的沙箱。 所以......我認爲這是一個很好記錄的錯誤。 :) – broofa

回答

29

您應該始終在單獨的進程中運行不受信任的代碼,這正是沙箱模塊所做的。一個簡單的原因是會凍結節點。

它首先生成一個單獨的進程,稍後將結果序列化爲JSON的stdout。無論孩子做什麼,父進程都會繼續執行,並可能觸發超時。

然後將不可信代碼封裝在strict mode(在常規JavaScript中,您可以使用arguments.callee.caller訪問範圍之外的數據)。最後,傳遞一個非常有限的global對象來阻止訪問節點的API。不受信任的代碼只能進行基本計算,並且無法訪問文件或套接字。

雖然你應該閱讀沙箱的代碼作爲靈感,我不建議使用它作爲是:

  • 的代碼是老了,連續7個月一直沒有更新。
  • 節點中的子進程模塊已經提供了您需要的大部分功能,特別是child_process.fork()
  • child_process.fork提供的IPC通道可能具有更好的性能。

爲了提高安全性,你還可以考慮使用setuid-sandbox。這是Google Chrome用來防止標籤進程訪問文件系統的代碼。你將不得不做一個本地模塊,但這個example似乎很簡單。

+3

'vm'模塊中的方法現在支持'timeout'參數,它可以讓您安全地執行'while(true){}'。它顯然沒有解決安全問題,但它確實解決了無限循環。 –

+0

@AndrewPaprocki你能鏈接到超時時間顯示的文檔嗎? –

+0

@RobFox這是在v0.11,http://nodejs.org/docs/v0.11.13/api/vm.html –