加了sandbox即全锁死:脚本不执行、表单不提交、弹窗拦截、localstorage不可读写,仅postmessage可用;必须静态设置sandbox="allow-scripts"才能解禁外链脚本,内联事件、eval、onclick等仍被静默屏蔽。

加了 sandbox 就脚本不执行,不是 JS 写错了,是它被硬性关死了——空值或仅 sandbox 属性即全禁用,allow-scripts 是唯一能解禁脚本的白名单项,且必须静态写死。
为什么写了 sandbox 却连 alert(1) 都不弹
浏览器把 <iframe sandbox></iframe> 当作“零权限容器”:所有脚本解析行为被跳过,包括 <script>alert(1)</script>、onclick="alert(1)"、javascript:void(0)、eval()、setTimeout("alert(1)")。控制台不会报错,console.log 也不输出,Network 面板里甚至看不到脚本请求。
-
sandbox=""、sandbox=" "、sandbox(无值)三者等效,全部锁死 - 动态设置
iframe.sandbox = "allow-scripts"无效,DOM 插入后改属性不生效 - 验证当前生效权限:在控制台执行
document.querySelector('iframe').sandbox,返回空DOMTokenList []表示没开任何权限
allow-scripts 能跑什么、不能跑什么
allow-scripts 只放行通过 <script src="..."></script> 加载的外部脚本,且该资源需满足 CORS 或同源;它不恢复任何内联执行能力。
- ✅ 可运行:
<script src="https://trusted.example/widget.js"></script>(服务端需返回Access-Control-Allow-Origin) - ❌ 不可运行:
<script>alert(1)</script>(内联 script 标签静默忽略) - ❌ 不可运行:
<button onclick="fetch('/api')">click</button>(内联事件处理器完全失效) - ❌ 不可运行:
data:text/javascript,alert(1)(data: 协议默认被拦,除非加allow-same-origin,但极危险) - ⚠️ 注意:
allow-scripts不递归授权——外链脚本里再document.write("<script>...</script>")仍被禁止
常见误配组合与真实风险
很多人堆砌 token 图省事,结果等于撤掉沙箱。生产环境尤其要避开这些典型错误。
-
sandbox="allow-scripts allow-same-origin":仅当src真同源(协议+域名+端口全一致)时才生效;若src="https://third-party.com/widget.html"却硬加,既得不到权限,又暴露配置疏忽 -
sandbox="allow-scripts allow-popups allow-forms allow-downloads":功能看似完整,但攻击面陡增;比如allow-popups后新开窗口不继承 sandbox,拥有完整权限 -
sandbox="allow-scripts allow-top-navigation":允许 iframe 直接跳转整个页面,极易用于钓鱼,应改用更安全的allow-top-navigation-by-user-activation - 绝对不要给第三方内容加
allow-same-origin——它让 iframe 获得读写自身localStorage和发起同源fetch()的能力,一旦外链脚本被劫持,后果严重
实时预览场景下怎么让用户写的 HTML 真正跑起来
直接用 sandbox="allow-scripts" 加载用户 HTML 字符串(如 srcdoc 或 data: URL)依然会失败,因为内联脚本和事件仍被拦。可靠做法是转成 Blob URL。
- 用
new Blob([htmlString], { type: 'text/html' })创建 blob 对象 - 调用
URL.createObjectURL(blob)得到blob:协议地址 - 设
iframe.src为该地址,并静态写死sandbox="allow-scripts" - 避免
src="data:text/html,...":data: URL 在部分浏览器中无法触发allow-scripts授权,且 origin 处理不一致 - 注意:
localStorage在 blob URL 沙箱中不可持久化,刷新即丢,DevTools 里常标为 “(inactive)”
最易被忽略的一点:sandbox 的 DOM 隔离是硬边界,无论你怎么配 token,window.parent、document、top 都不可访问——这不是 bug,是设计底线。需要通信,只能靠 postMessage,且父页必须校验 event.origin。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











