Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8920

JavaScriptで比較的安全にeval()する

$
0
0
evalって? 文字列をJavaScriptのコードとして評価してくれます。 一見便利だけど、めっちゃ危険だから通常使うことはありません。 使ったらESLintにも怒られます。 でも、外部からコードを注入できるのはとても拡張性が高いので、クローズドなBotとかの開発に使いたい場面はあります。 eval的なやつ eval()が一番有名だと思うけど、実は他にも同じようなことができる方法があります。 具体的には、グローバルオブジェクトのFunction()と、Node.jsのVMです。 eval ( ) Function ( ) Node.js VM 安全性としては、たぶんeval() <<< Function() << Node.js VMなんだけれど、VMはちょっと敷居が高そうだったので、この記事ではFunction()を使った方法について紹介します。 ちなみに、npmにsafe-evalっていうNode.js VMのラッパーがあったので、使ってみてもいいかも。 hacksparrow/safe-eval Function()の使い方 基本はeval()と同じです。 const greeting = Function('console.log("hello.")') greeting() // hello. けど、ローカルスコープに閉じ込められてるので、eval()と比べるとかなり安全。 実行するコードを渡すとこんな感じ。 const runCode = (code) => Function(code)() const code = 'return new Date()' console.log(runCode(code)) // 2021-07-21T16:41:19.389Z ただし、ローカルスコープで評価されているので、グローバルに定義した関数はもちろん呼び出せない。 以下のコードはエラーになります。 const greeting = (name) => `hello, ${name}.` const runCode = (code) => Function(code)() const code = 'return greeting("michinosuke")' console.log(runCode(code)) // greeting is not defined じゃあどうするかというと、ちょっと複雑だけど、こんな感じにします。 const greeting = (name) => `hello, ${name}.` const runCode = (code) => Function(`return (greeting) => {${code}}`)()(greeting) const code = 'return greeting("michinosuke")' console.log(runCode(code)) // hello, michinosuke. awaitするコードを実行したいときは次のようにかきます。 const runCode = (code) => Function(`return async (fetch) => {${code}}`)()(fetch) const runCodeAndPrint = async (code) => { console.log(await runCode(code)) } runCodeAndPrint(` const html = await fetch("https://example.com/").then(res => res.text()) return html.match(/<title>.+/)[0] `) // <title>Example Domain</title> 非同期なFunction() 一応、非同期関数もコンストラクタで生成できます。 const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor AsyncFunction('return "async hello"')().then(str => console.log(str)) AsyncFunction まとめ 紹介したFunction()は、ローカルスコープで評価されるとはいえ、悪意のある人物なら容易に悪用できるので、不特定多数に公開するサービスでの使用はやめた方がいいと思います。

Viewing all articles
Browse latest Browse all 8920

Trending Articles