fix: comment scripts bypass cookie consent (#1308)

* fix: comment scripts bypass cookie consent

When GDPR cookie consent is enabled, the comments container is simply
hidden with CSS. However, this still allows all third-party script
tags within the container to be evaluated and downloaded by the
browser.

This PR uses the <template> tag which stops inner scripts from evaluating.
Once consent is granted, the template content is cloned and inserted
into the container, and the scripts are manually loaded in order.

* refactor(comments): move consent-gated loader to TS asset

* fix(comments): add integrity attribute to comments consent script

* style: align comments consent docs and naming

* refactor(comments): simplify script handling

---------

Co-authored-by: Jimmy Cai <jimmy@cai.im>
This commit is contained in:
powerfullz
2026-04-26 18:51:22 +02:00
committed by GitHub
co-authored by Jimmy Cai
parent 55340540b5
commit 0fc8264927
3 changed files with 155 additions and 32 deletions
+13 -32
View File
@@ -1,3 +1,8 @@
{{/*
Comments include entry.
- If functional cookie consent is required, render a placeholder + template and load commentsConsent.ts.
- Otherwise, render provider partial directly.
*/}}
{{ if .Site.Params.comments.enabled }}
{{- $needsConsent := and .Site.Params.cookies.enabled .Site.Params.cookies.categories.functional -}}
{{- if $needsConsent -}}
@@ -8,40 +13,16 @@
{{ T "cookies.managePreferences" }}
</button>
</div>
<div id="comments-container" style="display: none;">
<div id="comments-container" style="display: none;"></div>
<template id="comments-template">
{{ partial (printf "comments/provider/%s" .Site.Params.comments.provider) . }}
</div>
<script>
(function() {
var placeholder = document.getElementById('comments-consent-placeholder');
var container = document.getElementById('comments-container');
function showComments() {
if (placeholder) placeholder.style.display = 'none';
if (container) container.style.display = 'block';
}
function hideComments() {
if (placeholder) placeholder.style.display = 'block';
if (container) container.style.display = 'none';
}
window.addEventListener('onCookieConsentChange', function(e) {
if (e.detail && e.detail.functional) {
showComments();
} else {
hideComments();
}
});
// Check if already consented
if (window.cookieConsent && window.cookieConsent.hasConsent('functional')) {
showComments();
}
})();
</script>
</template>
{{- $opts := dict "minify" hugo.IsProduction -}}
{{/* commentsConsent.ts is intentionally built and loaded here as an independent entry */}}
{{- $commentsScript := resources.Get "ts/commentsConsent.ts" | js.Build $opts | fingerprint -}}
<script type="text/javascript" src="{{ $commentsScript.RelPermalink }}" integrity="{{ $commentsScript.Data.Integrity }}" defer></script>
{{- else -}}
{{/* No consent required - load comments normally */}}
{{ partial (printf "comments/provider/%s" .Site.Params.comments.provider) . }}
{{- end -}}
{{ end }}
{{ end }}