必须服务端鉴权文件操作——前端拦截无效,原型污染可绕过权限判断;应冻结关键原型、内联白名单校验,并在服务端校验资源级权限与文件元数据。
不能靠前端拦截文件读写操作来防绕过——所有客户端的“禁止上传”“禁用下载按钮”都只是界面提示,真正的控制权必须落在服务端。攻击者根本不需要动原型链,直接在控制台调用 fetch 或 XMLHttpRequest 就能绕过任何前端限制。原型链相关风险,主要集中在污染导致逻辑误判或方法失效,而非直接打开文件系统权限。
如果前端用了类似 if (user.hasFileAccess()) 或 canRead(file.type) 这类 JS 判断,并把它当作是否允许发起请求的依据,那攻击者就可能通过污染 Object.prototype 或 Array.prototype 让这些函数始终返回 true:
Object.prototype:执行 Object.prototype.hasFileAccess = () => true,让所有对象都“自带权限”Array.prototype.includes:让白名单校验(如 ['pdf', 'txt'].includes(ext))永远返回 true
String.prototype.endsWith:使 filename.endsWith('.jpg') 对任意后缀都返回 true
在页面加载最早期(<script> 标签顶部、第三方脚本之前)执行:
Object.freeze(Object.prototype)Object.freeze(Array.prototype)Object.freeze(String.prototype)Object.freeze(Function.prototype)同时,所有与文件类型、扩展名、MIME 类型相关的校验逻辑,不要写成可被覆盖的方法调用,而应使用内联表达式或硬编码白名单,例如:
✅ 推荐const allowed = ['pdf', 'docx', 'xlsx'];<br>return allowed.some(ext => filename.toLowerCase().endsWith('.' + ext));
return filename.endsWith('.pdf') || filename.endsWith('.docx');(易被劫持)前端只负责收集用户意图(如点击“下载报告”),不决定能否执行。每次请求都需携带明确上下文:
/api/files/abc123/download)abc123 是否有读权限(非角色判断,而是具体资源级授权)可在关键操作前加一次快速校验,不阻断流程但可告警:
String.prototype.endsWith 是否仍为原生函数:typeof ''.endsWith === 'function'
includes 行为:[].includes.call(['a'], 'a') === true