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

AngularJS中安全接收HTML输入并防范插值注入漏洞求助

解决AngularJS $interpolate 编译用户模板时的XSS注入问题

我明白你遇到的头疼问题了——本来以为用了$sanitize就能安全处理用户输入的HTML模板,结果输入{{constructor.constructor('alert(1)')()}}居然触发了弹窗,这说明你的安全防护还漏了关键一环。

问题根源

$sanitize的作用是过滤HTML中的危险标签(比如<script>、<iframe>这类),但它管不到Angular插值表达式{{}}里的代码逻辑。$interpolate在编译表达式时,默认会让表达式访问全局上下文(比如浏览器的window对象),而constructor.constructor其实是拿到了全局的Function构造函数,通过它可以动态创建并执行任意代码,这就直接导致了XSS漏洞。

正确的解决方案

要解决这个问题,核心是限制插值表达式能访问的上下文范围,彻底切断它对全局对象或危险原型属性的访问。这里有两种可靠的实现方式:

方式一:使用无原型的上下文对象

创建一个没有原型链的纯净对象,只把业务需要的属性传入,从根源上阻止表达式访问全局和原型属性:

let $interpolate = this.$injector.get('$interpolate');
let $sanitize = this.$injector.get('$sanitize');
let html = $sanitize(toReturnStyles.cellTemplate);

// 创建无原型的上下文,避免访问Object.prototype的属性
const safeContext = Object.create(null);
// 只复制你允许用户访问的属性,比如params里的name、value等
Object.assign(safeContext, {
  name: params.name,
  value: params.value
  // 这里只放业务必需的属性,不要直接传入整个params
});

// 用安全上下文执行插值
el = $interpolate(html)(safeContext);

方式二:用Proxy拦截危险属性访问

如果需要保留原params的结构,又要阻止危险属性的访问,可以用ES6的Proxy来做拦截:

let $interpolate = this.$injector.get('$interpolate');
let $sanitize = this.$injector.get('$sanitize');
let html = $sanitize(toReturnStyles.cellTemplate);

// 创建Proxy拦截器,禁止访问危险属性
const safeContext = new Proxy(params, {
  get(target, prop) {
    // 拦截constructor、__proto__、prototype等危险属性
    const forbiddenProps = ['constructor', '__proto__', 'prototype', 'eval', 'Function'];
    if (forbiddenProps.includes(prop)) {
      return undefined;
    }
    return target[prop];
  }
});

// 用拦截后的上下文执行插值
el = $interpolate(html)(safeContext);

额外注意事项

  • 永远不要让用户输入的模板包含Angular指令(比如ng-click、ng-bind),如果必须允许,一定要用$compile配合严格的SCE校验,但这风险更高,尽量避免。
  • 只暴露业务必需的属性给插值上下文,遵循最小权限原则,不要把整个params对象直接传入,减少攻击面。

内容的提问来源于stack exchange,提问作者Ganesh Nemade

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:51:25