使用带脚本nonce的CSP时如何记录非异步资产的加载错误
CSP nonce模式下script加载错误的处理方案
以下方案均符合CSP nonce安全策略要求,无需调整现有nonce配置:
全局error事件监听(通用方案,覆盖同步、异步所有script场景)
CSP仅禁用标签上的内联onerror属性,不会禁用全局事件监听。你可以在页面所有script加载之前,在最顶部注册全局捕获事件:// 这段代码要放在页面最头部,确保在所有script加载前执行 window.addEventListener('error', (e) => { // 过滤出script资源加载错误 if (e.target.tagName === 'SCRIPT') { const failedSrc = e.target.src; // 此处添加你的错误上报逻辑 console.error('script加载失败:', failedSrc); } }, true);注意:第三个参数必须设为
true开启捕获模式,因为资源加载错误不会向上冒泡,默认的冒泡模式无法监听到这类事件。同步加载script专属兜底方案
针对你提到的非异步加载script场景,还可以用标记位校验的方案,完全不依赖事件系统,稳定性更高:
每个需要监控的同步script后紧跟一段带nonce的内联脚本,标记该script已加载完成,所有同步script加载完毕后统一校验标记位即可:<!-- 加载业务script --> <script nonce="你的合法nonce值" src="a.js"></script> <script nonce="你的合法nonce值"> window.__scriptLoadFlag = window.__scriptLoadFlag || {}; window.__scriptLoadFlag.a = true; </script> <script nonce="你的合法nonce值" src="b.js"></script> <script nonce="你的合法nonce值"> window.__scriptLoadFlag.b = true; </script> <!-- 所有同步script加载完成后统一校验 --> <script nonce="你的合法nonce值"> const toCheckList = ['a', 'b']; toCheckList.forEach(scriptName => { if (!window.__scriptLoadFlag?.[scriptName]) { // 此处添加对应script加载失败的上报逻辑 console.error(`${scriptName}.js 加载失败`); } }); // 清理全局变量避免污染 delete window.__scriptLoadFlag; </script>动态创建script场景补充方案
如果存在js动态创建插入的script,直接通过addEventListener绑定error事件即可,不要使用内联属性:const script = document.createElement('script'); script.nonce = '你的合法nonce值'; script.src = '动态加载的script地址'; script.addEventListener('error', () => { // 错误上报逻辑 console.error('动态script加载失败'); }); document.body.appendChild(script);
优先推荐使用全局事件监听方案,侵入性最低,适配所有场景。
内容的提问来源于stack exchange,提问作者RyanCheu
相关产品推荐
相关产品推荐

