jquery.min.js 违反了 inline-style 的 CSP

jquery.min.js violates CSP for inline-style

我想将 CSP header 添加到网络服务器。我不想添加 'unsafe-inline'。我已经使用 'nonce' 将所需的内联脚本和样式列入白名单,这似乎工作正常。但是,local jquery.min.js 似乎存在一些问题,因为它显示了许多内联样式的 CSP 违规错误。检查 Chrome 调试器 window 中的错误后,它指向 jquery.min.js 的以下行:

a.innerHTML = u[1] + S.htmlPrefilter(o) + u[2],

我不确定这有什么关系。有没有办法在不添加 'unsafe-inline' 的情况下消除 jquery.min.js 的这些 CSP 违规错误?

详情:

jquery.min.js 版本 => v3.5.1

CSP 政策 => default-src 'self' 'nonce-XXXX'; frame-ancestors 'self'; form-action 'self';

Jquery与此无关。当您调用 .html() / .append() / .prepend() 方法将 HTML 代码插入 DOM.[=33= 时,将使用 a.innerHTML = u[1] + S.htmlPrefilter(o) + u[2] 构造]

由于这会导致 CSP 违规,这意味着您插入 HTML 包含内联样式的代码:<tag style='...'<style>...</style>。您有 2 个选择:

  • 重构 JS 代码以摆脱这种内联样式插入。
  • 使用 this hackstyle=<style>...</style> 替换为与 CSP 兼容的等效项。
    黑客的想法是覆盖 htmlPrefilter() 方法,默认情况下它是 empty 并打算根据您的需要重新定义。

如果 style= 导致 CSP 违规,您可以使用类似的东西:

$.htmlPrefilter = function( html ) {
  // Really it have to be more complicated for replacing a tag's attributes only,
  // not just plain text replacement:
  return ( html + '' ).replace( / style=/gi, ' data-style=' );
  };

那么当使用 .html() / .append() / .prepend() 方法时,所有 style=inline_styles_here 属性将被替换为 data-style='inline_styles_here' 属性。

为了 CSP 安全,将真正的 CSS 样式应用于标签,您可以使用这样的脚本:

$(function() {   // On page loads
  var tags = document.querySelectorAll('[data-style]');
  for (var tag of tags) {
    var attr = tag.getAttribute('data-style')
    var arr = attr.split(';').map( (el, index) => el.trim() );
    for (var i=0, tmp; i < arr.length; ++i) {
      if (! /:/.test(arr[i]) ) continue;        // Empty or wrong style
      tmp = arr[i].split(':').map( (el, index) => el.trim() );
      tag.style[ camelize(tmp[0]) ] = tmp[1];
      }
    }

  function camelize(str) {
    return str
      .split('-')
      .map( (word, index) => index == 0 ? word : word[0].toUpperCase() + word.slice(1) )
      .join('');
    }

)}

Javascript 不是我的强项,重写上面的脚本以使用原生 jquery 调用。

如果 <style>...</style> 导致 CSP 违规,您可以重新定义 htmlPrefilter() 以将 <style> 替换为 <style nonce='value'>,但您必须以某种方式传递 'nonce' 到脚本。