17370845950

JavaScript eval函数是什么_它有什么安全风险
eval() 几乎不该被使用,因其将字符串当作代码执行,易受用户输入等不可信源攻击,导致XSS、凭证窃取等安全问题,且阻碍代码优化与调试;应改用JSON.parse()、方括号属性访问、mathjs等安全替代方案。

eval() 是 JavaScript 中一个能执行字符串代码的函数,但它在现代开发中几乎不该被使用——不是因为它不能用,而是因为风险远大于收益。

eval() 的基本行为和典型误用场景

它接收一个字符串参数,将其当作 JavaScript 代码解析并执行,返回最后一条语句的值(或 undefined)。

常见误用包括:动态拼接对象属性名、从后端取 JSON 字符串后直接 eval() 解析、实现简易表达式计算器等。

  • 它不区分“数据”和“代码”,任何传入的字符串都会被完整执行
  • 作用域继承自调用位置(非全局),但依然可访问闭包内变量和外部函数
  • 无法被 JS 引擎静态分析,影响压缩、混淆、Tree-shaking 和 DevTools 调试

为什么 eval() 容易引发严重安全问题

核心在于:一旦字符串内容来自用户输入、URL 参数、localStorage、第三方 API 或未严格校验的配置项,就等于把执行权交给了攻击者。

立即学习“Java免费学习笔记(深入)”;

例如,某页面通过 URL 的 callback 参数构造回调:

eval('handle(' + location.search.match(/callback=([^&]+)/)[1] + ')');
攻击者只需访问 https://site.com/?callback=alert(1)// 即可弹窗;更进一步,callback=console.log(document.cookie)// 就可能窃取凭证。

  • 绕过 CSP(Content Security Policy)策略:即使禁用了 unsafe-eval,某些旧版浏览器或配置疏漏仍可能让 eval() 生效
  • 无法做语法沙箱隔离:不像 Web Workersiframe sandboxeval() 运行在当前上下文,拥有全部权限
  • 错误堆栈模糊:报错时指向 eval 调用处,而非真实出错的字符串内部位置

有哪些更安全的替代方案

绝大多数 eval() 使用场景都有标准、可控的替代方式。

  • 解析 JSON:永远用 JSON.parse(),它只接受合法 JSON 格式,拒绝执行任意代码
  • 动态访问对象属性:用方括号语法 obj[propertyName],配合白名单校验(如 if (['name', 'email'].includes(key)) { ... }
  • 执行数学表达式:用专门库如 mathjs.eval() 或正则+运算符分步解析,避免全字符串求值
  • 模板渲染:用 template literalsHandlebars 等模板引擎,它们默认转义输出且不执行逻辑代码

如果真要保留 eval()(极少数遗留系统),至少做到三点

这不是推荐做法,而是给无法立即重构的系统兜底的最低防线。

  • 确保输入字符串完全由可信源生成(如硬编码常量、构建时生成的配置),且不含任何运行时拼接
  • 用正则提前过滤危险模式:比如禁止出现 ;functionreturndocumentevalnew Function 等关键词
  • try/catch 中包裹调用,并限制超时(需配合 WorkersetTimeout 模拟,原生 eval 不支持中断)

真正难的不是写一行 eval(),而是判断字符串里有没有隐藏的 __proto__.constructor.constructor 链式调用——这种细节在代码审查中极易被忽略。