如何修复移除unsafe-inline并添加nonce后的CSP内联事件错误
关于添加Nonce后出现CSP错误的排查与解决
问题背景
移除script-src中的'unsafe-inline'并添加指定nonce值后,页面触发CSP错误,相关配置与代码如下:
当前CSP配置
Content-Security-Policy: default-src 'none'; script-src 'self' 'unsafe-eval' 'nonce-b1967a39a02f45edbac95cbb4651bd12' 'unsafe-hashes'; frame-src 'self' 'nonce-b1967a39a02f45edbac95cbb4651bd12' 'unsafe-hashes'; connect-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; object-src 'self'; font-src 'self' data:;
页面代码
<html dir="ltr"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title> WebHelp Navigation Toolbar </title> <style> <!-- body {margin:0;} --> </style> <script nonce='b1967a39a02f45edbac95cbb4651bd12' src="whver.js" charset="utf-8"></script> <script nonce='b1967a39a02f45edbac95cbb4651bd12' src="whutils.js" charset="utf-8"></script> <script nonce='b1967a39a02f45edbac95cbb4651bd12' src="whmsg.js" charset="utf-8"></script> <script nonce='b1967a39a02f45edbac95cbb4651bd12' src="whproxy.js" charset="utf-8"></script> <script nonce='b1967a39a02f45edbac95cbb4651bd12' src="whmozemu.js" charset="utf-8"></script> <script nonce='b1967a39a02f45edbac95cbb4651bd12' src="whtbar.js" charset="utf-8"></script> <script nonce='b1967a39a02f45edbac95cbb4651bd12' type="text/javascript" language="JavaScript1.2"> //<![CDATA[ function printTopic() { var topicPane; if (top.frames[0].name == "ContentFrame") topicPane = top.frames[0].frames[1].frames[1]; else topicPane = top.frames[1].frames[1]; topicPane.focus(); var msg = new whMessage(WH_MSG_PRINT, 0, 0); notify(msg); } //]]> </script> </head> <body marginheight="0" marginwidth="0" bgcolor="#363f48" background="background.png" scroll="no"> <script nonce='b1967a39a02f45edbac95cbb4651bd12' language="javascript1.2"> <!-- if (window.gbWhTBar) { setButtonFont("toc","Arial","11pt","#a7abaf","Normal","Normal","none"); setButtonFont("toc","Arial","11pt","White","Normal","Normal","none", true); setButtonFont("idx","Arial","11pt","#a7abaf","Normal","Normal","none"); setButtonFont("idx","Arial","11pt","White","Normal","Normal","none", true); setButtonFont("fts","Arial","11pt","#a7abaf","Normal","Normal","none"); setButtonFont("fts","Arial","11pt","White","Normal","Normal","none", true); setButtonFont("glo","Arial","11pt","#a7abaf","Normal","Normal","none"); setButtonFont("glo","Arial","11pt","White","Normal","Normal","none", true); setButtonFont("searchform","Arial","11pt","#a7abaf","Normal","Normal","none"); setButtonFont("searchform","","","","","","", true); setButtonFont("banner","","","","","",""); setButtonFont("banner","","","","","","", true); setButtonFont("custom15160","Arial","11pt","#a7abaf","Normal","Normal","none"); setButtonFont("custom15160","Arial","11pt","White","Normal","Normal","none", true); gsIToc = "wht_toc_n.gif"; gsITocS = "wht_toc_h.gif"; gsIIndex = "wht_idx_n.gif"; gsIIndexS = "wht_idx_h.gif"; gsISearch = "wht_fts_n.gif"; gsISearchS = "wht_fts_h.gif"; gsIGlossary = "wht_glo_n.gif"; gsIGlossaryS = "wht_glo_h.gif"; gsIWebSearch = "wht_ws.gif"; gsIWebSearchD = "wht_ws_g.gif"; gsIBanner = "wht_logo1.gif"; gsIGo = "wht_go.gif"; setBackgroundcolor("#363f48"); setBackground("background.png"); setAlignment("left"); setGoImage("search-input-go.png"); if (!gsBgImage) { setButtonBgColor("toc", gsBgColor); setButtonBgColor("idx", gsBgColor); setButtonBgColor("fts", gsBgColor); setButtonBgColor("glo", gsBgColor); setButtonBgColor("toc", gsTBSelectedBgColor, true); setButtonBgColor("idx", gsTBSelectedBgColor, true); setButtonBgColor("fts", gsTBSelectedBgColor, true); setButtonBgColor("glo", gsTBSelectedBgColor, true); setButtonBgColor("toc","#363f48"); setButtonBgColor("idx","#363f48"); setButtonBgColor("fts","#363f48"); setButtonBgColor("glo","#363f48"); setButtonBgColor("searchform",""); setButtonBgColor("banner",""); setButtonBgColor("custom15160","#363f48"); } setButtonBgColor("toc","#363f48", true); setButtonBgColor("idx","#363f48", true); setButtonBgColor("fts","#363f48", true); setButtonBgColor("glo","#363f48", true); setButtonBgColor("searchform","", true); setButtonBgColor("banner","", true); setButtonBgColor("custom15160","#363f48", true); addButton("toc",BTN_TEXT|BTN_IMG,"Contents","","","","",0,0,"contents-unselected.png","contents-selected.png","","contents-selected.png","",""); addButton("fts",BTN_TEXT|BTN_IMG,"Search","","","","",0,0,"search-unselected.png","search-selected.png","","search-selected.png","",""); addButton("searchform",BTN_TEXT,"","","","","",0,0,"","","","","",""); addButton("custom15160",BTN_TEXT|BTN_IMG,"Print","","printTopic();","","",0,0,"print-unselected.png","print-selected.png","","print-selected.png","",""); addButton("blankblock"); writeStyle(false); ReSortToolbarButtons(); } else document.location.reload(); //--> </script> </body> </html>
排查与解决思路
- 验证Nonce一致性:确认CSP头中的nonce值与页面所有
<script>标签的nonce值完全匹配,包括大小写、特殊字符,当前配置已满足此要求。 - 检查框架内脚本授权:页面包含框架操作逻辑(
top.frames),需确保所有嵌套框架的页面脚本也添加了相同nonce值,框架内的脚本需独立满足自身的script-src规则。 - 排查
unsafe-hashes覆盖范围:'unsafe-hashes'仅授权特定哈希匹配的内联事件(如onclick属性),若页面存在未授权的内联事件,需添加对应哈希到CSP,或改用事件绑定方式替代属性内联代码。 - 查看控制台错误详情:打开浏览器开发者工具Console面板,CSP错误会明确指出被拦截的资源/脚本,根据提示针对性修复。
- 确认动态Nonce生成逻辑:若nonce为动态生成,需保证同一请求中CSP头与页面
<script>标签的nonce值完全一致,禁止硬编码固定值搭配动态生成的CSP头。
额外建议
- 在CSP头中添加
report-uri /csp-report(或report-to指令)收集违规报告,辅助定位问题。 - 逐步移除
'unsafe-eval'和'unsafe-hashes',优先通过nonce或哈希方式授权脚本,提升安全性。
内容的提问来源于stack exchange,提问作者Suparna
相关产品推荐
相关产品推荐

