We have a NodeJS Application where a User can input Javascript code. The JS code needs to be run in the same environment using eval
.
Now, as it has been recommended almost everywhere to avoid using eval
(especially on User Input), so initially I tried creating my own Parser (using Peg.JS). But, this is a difficult task (especially for people like me who have limited exposure to things like Parsers, AST, grammar, etc).
Then, I got to know that we can use Babel Parser to create AST of a piece of Code. So, I created a small piece of code to simulate the same and validate each Node using Babel Traverse. It "seems" to be working fine:
const parser = require("@babel/parser");
const _traverse = require("@babel/traverse");
// Traverse issue: Thanks to: https://github.com/babel/babel/issues/13855#issuecomment-945123514
const traverse = _traverse.default;
const unsafeMethods = ["require", "eval"];
const sourceCode = `var a = 123;
var b = 456;
require("fs");
// Commented require("fs");
console.log("Sum of " + a + " and " + b + " is " + (a+b));
var c = function(message){
console.log(">>> " + message);
};
c("Finished. Bye.");`;
const ast = parser.parse(sourceCode);
var unsafe = false;
traverse(ast, {
enter(path) {
if (path.node.type === "Identifier" && unsafeMethods.indexOf(path.node.name) != -1) {
unsafe = true;
}
},
});
if (unsafe) {
console.log("Code is Unsafe.");
} else {
console.log("Code is Safe.");
}
But, I'm in doubt whether the approach is legit or not. Also, if I need to make it more secure, what else should I add to the same?
Few References that I came across related to this:
- Using ast and whitelists to make python's eval() safe?
- Restricting eval() to a narrow scope
- calling eval() in particular context
- Running JS code in limited context
- AST Explorer where I was trying: https://astexplorer.net/#/gist/c0a93ae3582d5fb023e04c4db87d83ac/aad578c834339d3a6f8bac5207e0123b7c19d834