new.target 是防止异步构造函数被恶意劫持的关键防线之一,可阻断非 new 调用、识别真实实例化目标、支持抽象基类校验,但需配合参数校验、私有字段等机制应对 reflect.construct 绕过等场景。

new.target 本身不能“完美防止”异步构造函数被恶意劫持,但它可作为关键防线之一,配合其他机制共同加固。核心加密类若含敏感逻辑(如密钥派生、初始化向量生成),仅靠 new.target 不足以抵御主动攻击,但它是阻止最基础误用和初级绕过的可靠起点。
确保构造必须走 new 调用路径
恶意调用者常尝试绕过 new 直接执行构造逻辑(如 Encryptor()),以获取未绑定上下文的原始返回或触发副作用。利用 new.target 可立即终止该行为:
- 在构造函数首行检查
if (!new.target) throw new TypeError('Encryptor is not callable without new') - 此判断在严格模式与非严格模式下均有效,且不依赖
this instanceof Encryptor(后者可被伪造) - 即使攻击者重写
Encryptor.prototype.constructor,new.target 的值仍由实际 new 调用链决定,不可篡改
识别真实实例化目标,阻断继承链滥用
若加密类设计为抽象基类(如 BaseCrypto),需禁止直接 new,只允许特定子类(如 AES256GCM)实例化:
- 在基类 constructor 中写
if (new.target === BaseCrypto) throw new Error('BaseCrypto is abstract') - 当攻击者试图
new BaseCrypto()或篡改原型链伪造调用时,new.target 仍精确指向BaseCrypto,条件成立即报错 - 子类调用
super()时,父类中 new.target 自动为子类名,天然支持白名单校验
与异步初始化分离,避免 new 过程暴露敏感操作
new.target 只在构造函数同步执行阶段有效,而“核心加密异步构造”本质是矛盾表述——new 是同步操作,所谓“异步构造”实为构造后立即调用异步初始化方法(如 await instance.init())。正确做法是:
- 构造函数内仅做轻量同步准备(如参数校验、空对象创建),不触发任何密钥生成或网络请求
- 将耗时/敏感的异步逻辑封装为独立方法(如
init()),并要求显式调用 - 可在
init()中二次校验:检查this._initialized !== true和Object.getPrototypeOf(this).constructor.name === 'AES256GCM',防止单例复用或原型污染
注意边界:new.target 不是银弹
它无法防御以下场景,需额外措施:
- 攻击者通过
Reflect.construct(Encryptor, args)绕过 new.target 检查(此时 new.target 仍为 Encryptor,合法)→ 应配合白名单参数校验或环境锁(如检查process.env.NODE_ENV === 'production') - 内存泄漏或调试器注入 → 需结合代码混淆、私有字段(#key)、以及运行时完整性检测
- 箭头函数中不可用 new.target → 所有加密逻辑必须放在普通函数或 class constructor 内,禁用箭头函数作为构造入口










