带有内容安全策略的 Angular 12 CSS 优化内联事件处理程序

Posted

技术标签:

【中文标题】带有内容安全策略的 Angular 12 CSS 优化内联事件处理程序【英文标题】:Angular 12 CSS optimization inline event handler with Content Security Policy 【发布时间】:2021-08-06 11:44:44 【问题描述】:

升级到 Angular 12 后,我的内容安全策略会阻止样式正确加载。

Angular 12 devkit 似乎在 index.html 中的 CSS 包引用中添加了一个新的内联事件处理程序,示例如下。

<link rel="stylesheet" href="styles.5951e4ca367b697db091.css" crossorigin="anonymous" integrity="sha384-2031E8+oC87S0N7NzRGcF8fqx777KEJOgQ3KcUN4aX6xsR3BVaV5sh4fibR5joOc" media="print" onload="this.media='all'">

错误

Refused to execute inline event handler because it violates the following Content Security Policy directive...

这似乎与此 RFC:https://github.com/angular/angular-cli/issues/18730 有关,但我找不到有关如何将其与严格(无“不安全内联”)CSP 一起使用的更多信息。

【问题讨论】:

我认为目前最好的解决方案是为那个超级简单的脚本 this.media='all' 添加 sha256 哈希。见:github.com/angular/angular-cli/issues/… 【参考方案1】:

Angular 12 升级后我遇到了同样的问题。

我的解决方案是将工作区选项优化“inlineCritical”设置为 false。 inlineCritical 选项在 Angular 12 中更改为默认 true 以改进 First Contentful Paint,请参阅https://angular.io/guide/workspace-config#styles-optimization-options

这是一个示例工作区配置

"project": 
  "architect": 
    "build": 
      "configurations": 
        "production": 
          "optimization": 
            "scripts": true,
            "styles": 
              "minify": true,
              "inlineCritical": false
            ,
            "fonts": true
          
        
      
    
  
,

【讨论】:

太棒了!感谢您分享这个,它解决了@alex 描述的完全相同的问题 如果他们真的定义了“关键”的含义,那就太好了。例如,我有一些对预加载“/assets/preload/preload.css”至关重要的 css 那么为什么不内联呢? 非常感谢您的回答。这完全解决了我的问题。 感谢您的回答,解决了我非常相似的问题! 这应该被标记为正确答案。【参考方案2】:

注意! 答案已更新

更新答案(2021 年 7 月 16 日)

下面发布的原始解决方案破坏了 Safari (MacOS),因此我们不得不回滚并禁用 optimization.styles.inlineCritical

此外,正如下面masterfloda 所评论的那样,在大多数情况下(如果不是所有情况),选择应该是安全而不是性能。 我最初的想法是它很难被利用 (unsafe-hashes),但我还没有对此进行彻底的 InfoSec 风险评分。

在 Angular 存储库上有一张为此打开的票 - #20864。 我建议你暂时禁用optimization.styles.inlineCritical 并喜欢并订阅该问题。


原始答案(2021 年 6 月 9 日)

是的,这个问题是由 Angular v12 的 Styles optimization options (inlineCritical: true) 引入的,它向主样式表的链接标记添加了一个 onload 事件处理程序,如下所示:

&lt;link rel="stylesheet" href="styles.&lt;hash&gt;.css" media="all" onload="this.media='all'"&gt;

在CSP中不禁用inlineCritical或启用'unsafe-inline'即可解决,如下:

散列onload处理程序的内容:this.media='all' 报告 URI 有一个方便的工具:Script And Style Hasher 将哈希添加到 CSP 中的 script-src 指令 对于 Chrome(但不适用于 FF),您还需要将 'unsafe-hashes' 添加到 script-src 指令,否则它会在控制台中使用以下日志阻塞:请注意,哈希不适用于事件处理程序、样式属性和 javascript:导航,除非存在“不安全哈希”关键字

【讨论】:

出于安全原因,我认为这不是一个好的答案:我宁愿不针对 First Contentful Paint 进行优化,也不愿在我的 CSP 中允许 unsafe-hashes 感谢@masterfloda,你是对的,除非漏洞利用的可能性低到足以值得权衡(可能不是)。我已经更新了答案。 我对使用不安全哈希值进行了风险评分。虽然攻击的影响很大(例如由于泄露用户会话令牌而导致的会话劫持),但只要您有足够的 XSS 保护(例如 CSP 没有“不安全内联”、HTML 端码 + 对渲染进行清理),这种可能性就很低)。 XSS 注入漏洞必须存在并被攻击者发现,然后他们才能利用 unsafe-hash。 ***.com/a/69336136/1440240

以上是关于带有内容安全策略的 Angular 12 CSS 优化内联事件处理程序的主要内容,如果未能解决你的问题,请参考以下文章

Chrome 中的 Css 内联样式错误:“拒绝应用内联样式,因为它违反了以下内容安全策略指令……”

内容安全策略元标记“不安全内联”不起作用

由于内容安全策略指令,无法在生产中的 Angular 应用程序中保存 PDF 文件

Cordova Angular webView 错误拒绝应用内联样式,因为它违反了以下内容安全策略指令

拒绝加载样式表,因为它违反了内容安全策略

无法在重新加载页面上获取 /login Angular 8 - 拒绝加载图像“/favicon.ico”,因为它违反了以下内容安全策略