Comment les attaquants détournent Google Tag Manager, et comment une CSP stricte le contient
CentralCSP Team ·
Dernière mise à jour:
Google Tag Manager (GTM) existe pour injecter des scripts dans vos pages sans déploiement de code. C'est la fonctionnalité, et c'est aussi le risque : celui qui contrôle le conteneur peut livrer du JavaScript arbitraire sur chaque page qui le charge. Un compte compromis, un éditeur malveillant ou un tag tiers détourné peut transformer votre propre outillage d'analytics en canal de livraison pour un skimmer de formjacking. Une politique de sécurité du contenu (CSP) stricte, un header de réponse HTTP qui indique au navigateur quels scripts peuvent s'exécuter, plus un inventaire de scripts et des alertes de changement, voilà comment vous le contenez et le détectez.
C'est le complément sécurité et menaces de CSP pour Google Analytics et Tag Manager, qui couvre la mécanique pour autoriser GTM sous un nonce. Ici la question est différente : qu'est-ce qui peut mal tourner via GTM, et qu'est-ce qui limite les dégâts.
GTM est un canal d'injection de scripts par conception
Quand vous ajoutez le snippet GTM à une page, vous confiez à une configuration distante la capacité de charger et d'exécuter du code dans votre origine. Quiconque peut publier une version de conteneur, via l'interface GTM ou l'API, décide quel JavaScript s'exécute sur chaque page portant ce conteneur. Les tags tournent avec un accès complet à la page : le DOM, les champs de formulaire, les cookies qui ne sont pas HttpOnly, et tout ce qu'un script côté client peut atteindre.
C'est exactement ce que vous voulez pour des tags légitimes d'analytics et de marketing. C'est aussi exactement ce qu'un attaquant veut. La capacité ne distingue pas un pixel de conversion d'un skimmer de carte.
D'où vient l'abus
Trois chemins transforment cette capacité en incident.
- Un compte GTM compromis. Des identifiants hameçonnés ou réutilisés sur un compte avec droits de publication permettent à un attaquant de pousser une version de conteneur malveillante. Aucun changement ne touche votre code ni vos serveurs, donc vos propres CI, revue de code et logs de déploiement ne le voient jamais.
- Un éditeur trop permissionné. Un prestataire ou un utilisateur marketing avec accès en publication, ou un compte obsolète qui aurait dû être supprimé, peut livrer un tag, par erreur ou à dessein, qu'aucun ingénieur ne relit.
- Un tag tiers détourné. Un tag qui charge le script d'un fournisseur signifie que ce fournisseur (ou quiconque le compromet) peut changer ce qui s'exécute sur votre page à tout moment. Le risque de supply-chain s'étend à chaque host depuis lequel vos tags tirent du contenu.
Dans chaque cas, le code malveillant arrive de la même façon que les tags légitimes, c'est pourquoi les défenses côté serveur ne le voient pas. Un pare-feu applicatif inspecte le trafic vers votre origine ; il ne voit pas ce que gtm.js injecte dans le navigateur après le chargement de la page.
Pourquoi allowlister GTM élargit votre périmètre de confiance
La façon courante d'« autoriser » GTM dans une CSP est de lister googletagmanager.com et compagnie dans script-src. Cette allowlist fait confiance à chaque script que ces hosts peuvent servir, y compris tout ce que votre conteneur est configuré pour charger maintenant ou à l'avenir. Vous ne faites pas confiance à un ensemble de code fixe ; vous faites confiance à une configuration mutable contrôlée hors de votre dépôt.
Les allowlists de hosts sont faibles pour une deuxième raison. Toute redirection ouverte, endpoint JSONP ou chemin contrôlé par l'utilisateur sur un host autorisé peut devenir un contournement qui exécute du code choisi par l'attaquant tout en satisfaisant la politique. De larges wildcards Google dans script-src élargissent considérablement cette surface.
Comment une politique stricte à nonce plus strict-dynamic le contient
Une CSP stricte ne fait pas confiance aux hosts. Elle fait confiance à un nonce par requête et utilise 'strict-dynamic' pour étendre cette confiance aux scripts qu'un script porteur de nonce charge. Vous mettez le nonce sur l'amorçage GTM, et le navigateur fait alors confiance à gtm.js et aux tags que GTM injecte parce qu'ils en descendent.
Content-Security-Policy:
script-src 'self' 'nonce-{SERVER-GENERATED-NONCE}' 'strict-dynamic';
object-src 'none';
base-uri 'none';
report-to csp-endpointCela n'empêche pas GTM d'injecter ce que le conteneur est configuré pour injecter ; rien côté client ne le peut, parce que ce code descend de votre amorçage de confiance. Ce que cela fait, c'est réduire le rayon d'impact autour de GTM. Un attaquant qui trouve une injection ailleurs sur la page (une XSS réfléchie, un fournisseur non-GTM compromis) ne peut pas exécuter de script, parce qu'il ne peut pas deviner le nonce, et 'strict-dynamic' signifie qu'une allowlist de hosts égarée ne le sauvera pas non plus. La politique garde la confiance étroite : seulement ce que GTM charge, pas tout ce qu'un host autorisé pourrait servir.
Cela rend aussi une classe d'abus de GTM plus bruyante. Les tags qui ont besoin de 'unsafe-eval', comme les variables JavaScript personnalisées, échoueront sous une politique stricte au lieu de tourner silencieusement, ce qui force ces schémas à sortir au grand jour où vous pouvez les relire.
La détection est l'autre moitié : inventaire et alertes
Le confinement limite les dégâts. La détection vous dit quand un conteneur a changé. Parce qu'une compromission de GTM ne touche jamais votre code, le seul endroit pour la voir est dans le navigateur, dans ce qui a réellement tourné sur la page.
Un inventaire de scripts enregistre chaque script s'exécutant sur chaque page, construit à partir du reporting de hash CSP, avec la technologie, la version et les CVE connues derrière chacun. Quand GTM injecte un nouveau tag, un nouveau script apparaît dans l'inventaire. Les alertes de changement se déclenchent quand l'ensemble des scripts d'une page sensible change : une nouvelle origine, un nouveau bloc inline, un script qui n'était pas là hier. Sur une page de paiement, un nouveau script inattendu est le signal précoce d'un skimmer de type Magecart, le même signal que les exigences côté client de PCI DSS v4 vous demandent de surveiller.
C'est le workflow pour lequel CentralCSP est fait. Il ingère vos reports de violation et de hash CSP, inventorie les scripts que GTM et tout le reste chargent, et alerte sur les changements, pour qu'une version de conteneur malveillante remonte sous forme d'alerte « nouveau script sur la page de paiement » plutôt que sous forme de rapport de rétrofacturation des semaines plus tard. Vous pouvez évaluer une politique pour des faiblesses comme une large allowlist de hosts Google d'abord, puis démarrer un essai gratuit et pointer un header Report-Only dessus pour voir ce que votre conteneur charge réellement.

Une checklist de confinement pratique
- Faites confiance à GTM via un nonce et
'strict-dynamic', pas une allowlist de hosts dansscript-src. - Gardez les hosts Google dans
connect-src,img-srcetframe-src, où se produisent les requêtes non-script, pas dansscript-src. - Verrouillez le compte GTM : droits de publication minimaux, MFA, et une revue régulière qui supprime les éditeurs obsolètes.
- Évitez les tags qui forcent
'unsafe-eval'; reconstruisez les variables JavaScript personnalisées en Custom Templates sandboxés. - Inventoriez les scripts sur chaque page sensible et alertez sur le changement, pour qu'une modification de conteneur que vous n'attendiez pas soit visible immédiatement.
Questions fréquentes
Google Tag Manager peut-il être un risque de sécurité ?
Oui. GTM injecte des scripts dans vos pages depuis une configuration distante, donc un compte compromis, un éditeur trop permissionné ou un tag tiers détourné peut exécuter du JavaScript arbitraire sur chaque page qui charge le conteneur. Le risque est inhérent à ce que GTM fait.
GTM contourne-t-il ma CSP ?
Si vous allowlistez des hosts Google dans script-src, GTM et tout ce qu'il charge tournent sous cette allowlist, donc un tag malveillant tourne aussi. Une politique stricte à nonce plus 'strict-dynamic' ne bloque pas GTM (vous lui faites confiance délibérément), mais elle garde la confiance étroite et empêche les injections non liées de s'exécuter.
Comment détecter un tag GTM malveillant ?
Surveillez les scripts qui s'exécutent réellement dans le navigateur. Un inventaire de scripts construit à partir du reporting de hash CSP liste chaque script de chaque page, et les alertes de changement se déclenchent quand un script nouveau ou inattendu apparaît, ce qui est la façon dont une version de conteneur malveillante remonte sans toucher votre code.
GTM est-il un risque Magecart sur les pages de paiement ?
Il peut l'être. Un skimmer livré via un conteneur compromis s'injecte sur la page de paiement comme n'importe quel autre tag. Contenir GTM avec une CSP stricte et surveiller la page de paiement pour les changements de scripts, c'est de cela que parlent les exigences côté client de PCI DSS v4.
À retenir
GTM est un canal d'injection de scripts délibéré, donc sa sécurité se résume à deux choses : limiter ce qu'une injection peut faire, et détecter quand le conteneur change. Une CSP stricte qui fait confiance à un nonce et 'strict-dynamic' plutôt qu'à des allowlists de hosts Google garde le périmètre de confiance serré, et un inventaire de scripts avec alertes de changement vous dit quand un tag apparaît que personne dans votre équipe n'a livré. Ensemble, ils transforment un changement côté client invisible en quelque chose que vous pouvez voir et contenir.
Pour aller plus loin : OWASP sur la sécurité côté client et le Top 10 OWASP et les recommandations de sécurité GTM de Google.
Sources
- Google, utiliser une CSP avec Tag Manager
- OWASP, Top 10 des risques de sécurité des applications web
- W3C, Content Security Policy Level 3