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

JavaScript中能否彻底阻止对象及全局变量的删除与篡改?

如何彻底保护全局对象不被删除、覆盖及属性篡改

核心结论

可以通过锁定全局属性的可配置性+递归冻结整个对象树,在所有标准宿主环境(Node.js、浏览器、Deno)中实现对目标对象的全面保护,包括阻止:

  • 全局变量被删除/覆盖
  • 对象属性(含Symbol键)被添加、删除、修改
  • 原型链被篡改
  • 子对象(包括无原型对象)的属性篡改

分步实现方案

1. 锁定全局属性,阻止删除与覆盖

全局作用域中直接声明的变量默认是configurable: true的,可被delete删除或直接赋值覆盖。要阻止这种行为,需用Object.defineProperty将其定义为globalThis的不可配置、不可写属性:

// 先构建并冻结对象树,再绑定到全局
const secretData = deepFreeze(buildSecretTree());

// 定义不可删除、不可覆盖的全局属性
Object.defineProperty(globalThis, 'secretTree', {
  value: secretData,
  configurable: false, // 阻止删除属性、修改属性描述符
  writable: false,     // 阻止直接赋值覆盖(如secretTree = {})
  enumerable: true     // 可选:控制是否能被for...in遍历
});

2. 递归冻结对象树,保护所有子属性

Object.freeze是浅冻结,仅作用于当前对象的直接属性。要保护嵌套对象(包括无原型对象),需递归遍历所有自有属性(含Symbol键)并冻结:

// 带循环引用处理的深度冻结函数
function deepFreeze(obj, frozenCache = new WeakSet()) {
  // 基本类型直接返回
  if (obj === null || typeof obj !== 'object') return obj;
  
  // 避免循环引用导致无限递归
  if (frozenCache.has(obj)) return obj;
  frozenCache.add(obj);

  // 冻结当前对象:阻止添加/删除属性、修改属性值与描述符
  Object.freeze(obj);

  // 获取所有自有属性(字符串键 + Symbol键)
  const allPropertyKeys = [
    ...Object.getOwnPropertyNames(obj),
    ...Object.getOwnPropertySymbols(obj)
  ];

  // 递归冻结每个子属性
  allPropertyKeys.forEach(key => {
    deepFreeze(obj[key], frozenCache);
  });

  return obj;
}

// 示例:构建包含无原型对象、Symbol属性的秘密对象树
function buildSecretTree() {
  const secretSymbol = Symbol('hiddenKey');
  const nullProtoObj = Object.create(null); // 无原型对象
  nullProtoObj.confidential = 'top-secret-data';

  return {
    user: {
      id: 123,
      password: 'encrypted-pass',
      [secretSymbol]: 'symbol-only-secret'
    },
    system: nullProtoObj
  };
}

3. 额外防护:锁定原型链

如果对象不是无原型的,可通过以下方式阻止原型链篡改:

  • 创建对象时直接使用Object.create(null)(无原型,彻底避免原型链攻击)
  • 若必须保留原型,冻结原型对象并锁定__proto__属性:
    const obj = { a: 1 };
    // 冻结原型
    Object.freeze(Object.getPrototypeOf(obj));
    // 锁定__proto__属性,阻止修改原型
    Object.defineProperty(obj, '__proto__', {
      configurable: false,
      writable: false
    });
    

验证防护效果

执行以下操作均会失败(严格模式下抛出错误,非严格模式下静默失败):

// 尝试删除全局属性
delete globalThis.secretTree; // 无效

// 尝试覆盖全局变量
globalThis.secretTree = {}; // 无效

// 尝试修改属性值
secretTree.user.password = 'hacked'; // 无效

// 尝试添加新属性
secretTree.user.newKey = 'test'; // 无效

// 尝试删除属性
delete secretTree.user.id; // 无效

// 尝试修改无原型对象的属性
secretTree.system.confidential = 'hacked'; // 无效

// 尝试修改Symbol属性
secretTree.user[Symbol('hiddenKey')] = 'hacked'; // 无效(注意:这里是新Symbol,原Symbol属性无法修改)

局限性说明

  • 无法阻止读取属性值(这是正常需求,若需隐藏敏感数据需额外加密)
  • 若对象包含函数,冻结后函数本身不可被替换,但函数内部依赖的外部变量仍可能被修改(需确保函数内部无外部依赖或依赖也被保护)
  • 循环引用需通过缓存集合处理,否则会导致无限递归

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 02:45:18