GTM 不将随机数传播到自定义 HTML 标签

问题描述 投票:0回答:4

为了实现内容安全策略,我需要将

nonce
传递给 GTM 以允许标签。 使用nonce-aware版本的GTM代码片段适用于除自定义HTML之外的所有标签类型。

有没有办法将

nonce
传递给 自定义 HTML 并允许自定义脚本,而不使用
unsafe-inline

google-tag-manager content-security-policy
4个回答
14
投票

为了将

nonce
属性添加到自定义 HTML 脚本中,必须首先将其定义为 GTM 变量:

  1. id="gtmScript"
    添加到 GTM 片段的随机数感知版本 - 这将用于定位元素并捕获
    nonce
<script id="gtmScript" nonce="{GENERATED_NONCE}">
  // GTM function
</script>
  1. 在 GTM 中,创建一个新变量来捕获随机数。 使用 DOM Element 类型,然后选择 GTM 代码段的 ID。


现在

nonce
变量在 GTM 中可用,请将其添加到自定义 HTML 脚本中。

<script nonce="{{nonce}}">
  console.log("CSP-allowed script with nonce:", "{{nonce}}");
</script>

如果标签未触发,请检查支持 document.write。这可能是单页应用程序中的关键一步。 GTM 自定义 HTML 脚本现在已被允许并按预期触发。 当然,现在需要在 CSP 标头中允许此脚本使用的任何资产。


脚本中的脚本

许多跟踪脚本都在自身内部创建和触发其他脚本。 这些也将作为内联脚本被阻止。 找出它们是在哪里以及如何创建的,并向它们添加

nonce

通常,代码看起来与此类似:

var script = document.createElement("script");
script.type = "text/javascript";
script.async = true;
script.src = "https://tracking.js";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(script, s);

编辑这部分代码并插入

nonce
变量,以相同的方式以及其他属性。

script.nonce = "{{nonce}}";

再次注意,并将现在被此新允许的脚本阻止的任何必要资产列入白名单。

就是这样 - 自定义 HTML 脚本现在完全允许 CSP。


来源和免责声明:我是 expanded dev.toguide

的作者

0
投票

我在 Matija Mrkaic 提出的原始解决方案中发现了与其他人相同的问题。他的文章非常有用,但我发现

nonce
数据属性返回空白值。

为了解决这个问题,我在 GTM 脚本中添加了一个

data-nonce
属性,并在标签管理器中使用一个变量来提取随机数值(类似于 Matija Mrkaic。这个新变量称为
data-nonce
)。然后,我在 GTM 中添加了一个自定义 HTML 标记,该标记在加载后会删除
data-nonce
属性。

GTM代码:

<script id="gtmScript" nonce='{{csp_nonce}}' data-nonce='{{csp_nonce}}'>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;var n=d.querySelector('[nonce]');
n&&j.setAttribute('nonce',n.nonce||n.getAttribute('nonce'));f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','{{GOOGLE_TAG_MANAGER_ID}}');</script>

GTM 自定义 HTML 标记可在加载后删除随机数值:

<script nonce="{{data-nonce}}">
    console.log("Inline script to remove data-nonce.");
    document.getElementById("gtmScript").removeAttribute("data-nonce");
</script>

这个解决方案远非完美,但到目前为止我还无法找到将“秘密”传递给 GTM 的方法。不建议在 DOM 中公开随机数值,这种“临时”解决方案背后的理论是仅在短时间内公开它,直到加载到 Google 跟踪代码管理器变量中为止。

欢迎评论/建议,非常感谢。


0
投票

对于任何遇到 Chrome 隐藏随机数属性问题的人(Keyhan 和 Dan 在 https://stackoverflow.com/a/65100705/3370010 中指出),我发现 Google 跟踪代码管理器有一个设置可以从中获取变量全局“JavaScript 变量”。

您只需要先设置该全局变量即可。如果您动态添加 Google 跟踪代码管理器,则可以在 Google 跟踪代码管理器脚本之前进行设置。

window.nonceForCustomScripts = nonce;

如果您只是将代码插入 Google 标签管理器脚本中,它看起来会像这样

(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
            new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
            j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
            'https://www.googletagmanager.com/gtm.js?id='+i+dl;var n=d.querySelector('[nonce]');
            n&&j.setAttribute('nonce',n.nonce||n.getAttribute('nonce'));
// Added code
w.nonceForCustomScripts = n.nonce||n.getAttribute('nonce');
// End added code
            f.parentNode.insertBefore(j,f);
            })(window,document,'script','dataLayer','your-gtm-id');

这比添加 data-nonce 属性更安全,因为它可以防止基于 CSS 的攻击,例如 https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/nonce 中列出的攻击


0
投票

有一种更简单、更安全的方法来解决 GTM 不将随机数传播到自定义 HTML 标签的问题。

  1. 确保您已在 GTM 脚本标记中包含 nonce 属性,如官方文档中所述:
<!-- Google Tag Manager -->
<script nonce='{SERVER-GENERATED-NONCE}'>
  1. 接下来,将“strict-dynamic”附加到内容安全策略 (CSP) 标头的 script-src 部分,如下所示。 “严格动态”简化了基于随机数或哈希值实现 CSP 的过程,因为它会自动允许执行由先前受信任的脚本生成的脚本。此操作还有助于使用各种第三方 JavaScript 库和小部件,包括 GTM。
Content-Security-Policy:
  script-src 'nonce-{SERVER-GENERATED-NONCE}' 'strict-dynamic';
  img-src www.googletagmanager.com;
  object-src 'none';
  base-uri 'none';

此外,明智的做法是阻止

object-src
以防止使用 Flash 和
base-uri
等潜在危险插件,以防止攻击者更改从相对 URL 加载的脚本的位置。

使用此解决方案,无需添加不安全的

data-nonce
属性。并且无需更改 GTM 自定义脚本中的任何内容。

© www.soinside.com 2019 - 2024. All rights reserved.