You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测页面是否通过CSP禁止外部脚本运行,提示书签工具无法使用?

如何提前检测页面CSP是否阻止特定脚本加载

有两种可靠的方法可以提前检测页面的CSP限制,从而提示用户书签工具无法使用:


方法1:直接测试脚本加载(推荐)

这种方法不需要手动解析复杂的CSP规则,而是通过实际尝试加载目标脚本,根据结果判断是否被限制,准确性更高。

具体实现代码如下:

function checkScriptAllowed(src) {
  return new Promise((resolve, reject) => {
    const testScript = document.createElement('script');
    testScript.src = src;
    // 加载成功说明CSP允许
    testScript.onload = () => {
      testScript.remove();
      resolve(true);
    };
    // 加载失败说明CSP阻止
    testScript.onerror = () => {
      testScript.remove();
      reject();
    };
    document.head.appendChild(testScript);
  });
}

// 在你的书签工具开头调用
checkScriptAllowed('https://cdn.jsdelivr.net/npm/jquery')
  .then(() => {
    // 执行Scheme REPL的正常逻辑
    console.log('脚本加载允许,启动REPL');
  })
  .catch(() => {
    alert('当前页面的内容安全策略限制了必要脚本的加载,该书签工具无法在此页面使用');
  });

优势

  • 无需处理CSP规则的各种复杂格式(比如通配符、关键字组合、fallback逻辑),直接反映实际限制情况
  • 兼容所有CSP生效方式(响应头或meta标签)

方法2:解析页面的CSP规则

如果不想实际加载脚本,可以手动解析页面的CSP配置,判断目标源是否在允许列表中。

步骤:

  1. 获取CSP规则

    • 从meta标签获取:
      const metaCSP = document.querySelector('meta[http-equiv="Content-Security-Policy"]');
      const cspPolicy = metaCSP?.content;
      
    • 从响应头获取(注意:跨域页面无法通过这种方式拿到响应头):
      const navEntry = performance.getEntriesByType('navigation')[0];
      const responseHeaders = navEntry?.responseHeaders;
      const cspHeader = responseHeaders?.find(h => h.name.toLowerCase() === 'content-security-policy')?.value;
      
  2. 解析script-src指令
    需要拆分CSP规则,找到script-src(如果script-src-elem未设置则用它)的允许源列表,然后检查目标源是否匹配。

    示例解析逻辑(简化版,需处理更多细节比如通配符、'self'、子域名匹配等):

    function isScriptAllowed(cspPolicy, targetSrc) {
      if (!cspPolicy) return true; // 无CSP限制
      // 拆分规则到各个指令
      const directives = cspPolicy.split(';').map(dir => dir.trim()).filter(dir => dir);
      let scriptSrcs = [];
      // 优先找script-src-elem,没有则找script-src
      for (const dir of directives) {
        if (dir.startsWith('script-src-elem ')) {
          scriptSrcs = dir.slice('script-src-elem '.length).split(' ');
          break;
        }
      }
      if (scriptSrcs.length === 0) {
        for (const dir of directives) {
          if (dir.startsWith('script-src ')) {
            scriptSrcs = dir.slice('script-src '.length).split(' ');
            break;
          }
        }
      }
      if (scriptSrcs.length === 0) return true; // 无script-src限制
      // 检查目标源是否匹配允许的规则(简化实现,需扩展处理通配符等)
      const targetOrigin = new URL(targetSrc).origin;
      return scriptSrcs.some(src => {
        if (src === '*') return true;
        if (src === "'self'") return targetOrigin === window.location.origin;
        return src === targetOrigin || src === targetSrc;
      });
    }
    

注意事项

  • CSP规则的解析非常复杂,需要处理通配符(*.example.com)、路径匹配、关键字(unsafe-inline、unsafe-eval)等多种情况,容易出现遗漏
  • 跨域页面无法通过performance API获取响应头,只能依赖meta标签的CSP

内容的提问来源于stack exchange,提问作者jcubic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 14:10:33