You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Babel验证AST实现用户输入代码的安全eval执行?

处理用户输入JS代码的安全验证方案分析

我们有一个Node.js应用,允许用户输入JavaScript代码并在同一环境中用eval执行。众所周知直接用eval处理用户输入风险极高,最初尝试用Peg.js自定义解析器做安全校验,但因为对解析器、AST、语法相关知识了解有限,没能实现。后来了解到可以用Babel Parser生成代码的AST,再通过Babel Traverse遍历节点做安全验证,写了一段测试代码(如下),目前看起来能正常工作,但不确定这个方案是否合规,同时想知道怎么进一步提升安全性。

测试代码

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.");
}

方案合规性判断

你的思路方向是对的:通过AST做静态分析拦截危险代码,比直接用eval安全得多,是业内处理这类场景的常见方案之一,本身合规。但当前实现存在明显漏洞:

  • 仅检查标识符名称,攻击者可以通过global.require、this.require或字符串拼接(比如a['requ'+'ire'])等方式绕过检测
  • 未区分注释节点,会误判注释里的require为危险代码

提升安全性的具体措施

1. 优化AST遍历规则

  • 覆盖更多危险调用场景:不要只检查Identifier节点,要针对CallExpression、MemberExpression等节点做校验,比如判断调用的方法是否是危险API的直接或间接引用
  • 跳过注释节点:遍历AST时通过path.isComment()判断,直接跳过注释内容,避免误报
  • 优先使用白名单:比起黑名单(拦截危险方法),白名单(只允许指定安全API)更可靠,比如只允许console.log、数学运算相关方法,减少遗漏风险

2. 隔离执行上下文

即使AST校验通过,执行用户代码时也要做上下文隔离:

  • 使用Node.js内置的vm模块创建隔离环境,避免用户代码访问全局危险API:
    const vm = require('vm');
    // 只提供允许的API给用户代码
    const safeContext = {
      console: { log: console.log },
      Math: Math
    };
    vm.createContext(safeContext);
    // 限制执行时间,防止死循环
    try {
      vm.runInContext(userCode, safeContext, { timeout: 5000 });
    } catch (err) {
      console.error('代码执行超时或出错:', err);
    }
    
  • 避免直接用eval,vm模块的隔离性更强,能有效阻止用户代码访问Node.js的核心模块和全局对象

3. 补充防护措施

  • 限制用户输入代码的长度,避免过大代码占用过多内存
  • 给代码执行设置超时时间,防止死循环或长时间运行的代码耗尽资源
  • 记录所有用户输入的代码和执行日志,方便安全事件溯源

内容的提问来源于stack exchange,提问作者Ankur Thakur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 00:55:06