Added nonce & implemented GTM and CSP changes (#1661)

* Added nonce & implemented GTM and CSP changes
This commit is contained in:
Mavis Ou 2022-12-01 10:23:17 -08:00 коммит произвёл GitHub
Родитель f16b984068
Коммит 81b7d8c3aa
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 89 добавлений и 69 удалений

Просмотреть файл

@ -50,25 +50,7 @@ if (checkDoNotTrack() === false) {
return identifier;
};
const GA_ID = getIdentifier(`ga`);
const GTM_ID = getIdentifier(`gtm`);
if (GA_ID) {
ReactGA.initialize(GA_ID);
}
if (GTM_ID) {
(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;
f.parentNode.insertBefore(j, f);
})(window, document, "script", "dataLayer", GTM_ID);
}
ReactGA.initialize(getIdentifier(`ga`));
},
};
}

Просмотреть файл

@ -1,47 +1,54 @@
import url from "url";
import { env } from "./env-server";
export default {
directives: {
defaultSrc: [`'none'`],
scriptSrc: [
`'self'`,
`https://*.google-analytics.com`,
`https://platform.twitter.com/widgets.js`,
`https://www.googletagmanager.com/gtm.js`,
`https://www.googletagmanager.com/debug/bootstrap`,
`https://www.google.com/recaptcha/api.js`,
`https://www.gstatic.com/recaptcha/releases/`,
],
fontSrc: [
`'self'`,
`https://code.cdn.mozilla.net`,
`https://fonts.gstatic.com`,
],
frameSrc: [`https://www.google.com/`, `https://platform.twitter.com/`],
styleSrc: [
`'self'`,
`'unsafe-inline'`,
`https://code.cdn.mozilla.net`,
`https://fonts.googleapis.com`,
],
imgSrc: [`'self'`, `data:`, `https:`, `http:`],
connectSrc: [
`'self'`,
url.parse(env.PULSE_API).host ||
`https://network-pulse-api-staging.herokuapp.com/`,
`https://www.mozilla.org/en-US/newsletter/`,
`https://www.google.com/recaptcha/api.js`,
`https://www.gstatic.com/recaptcha/releases/`,
`https://www.google-analytics.com/j/collect`,
],
childSrc: [
`https://syndication.twitter.com`,
`https://platform.twitter.com`,
],
frameAncestors: [`'none'`],
manifestSrc: [`'self'`],
},
reportOnly: false,
browserSniff: false,
};
export default function (cspNonce) {
return {
directives: {
defaultSrc: [`'none'`],
scriptSrc: [
`'self'`,
`'nonce-${cspNonce}'`,
`https://www.google-analytics.com`,
`https://platform.twitter.com/widgets.js`,
`https://*.googletagmanager.com`,
`https://www.google.com/recaptcha/api.js`,
`https://www.gstatic.com/recaptcha/releases/`,
`https://tagmanager.google.com`,
],
fontSrc: [
`'self'`,
`https://code.cdn.mozilla.net`,
`https://fonts.gstatic.com`,
`data:`,
],
frameSrc: [`https://www.google.com/`, `https://platform.twitter.com/`],
styleSrc: [
`'self'`,
`'unsafe-inline'`,
`https://code.cdn.mozilla.net`,
`https://fonts.googleapis.com`,
`https://tagmanager.google.com`,
],
imgSrc: [`'self'`, `data:`, `https:`, `http:`],
connectSrc: [
`'self'`,
url.parse(env.PULSE_API).host ||
`https://network-pulse-api-staging.herokuapp.com/`,
`https://www.mozilla.org/en-US/newsletter/`,
`https://www.google.com/recaptcha/api.js`,
`https://www.gstatic.com/recaptcha/releases/`,
`https://*.google-analytics.com`,
`https://*.analytics.google.com`,
`https://*.googletagmanager.com`,
],
childSrc: [
`https://syndication.twitter.com`,
`https://platform.twitter.com`,
],
frameAncestors: [`'none'`],
manifestSrc: [`'self'`],
},
reportOnly: false,
browserSniff: false,
};
}

Просмотреть файл

@ -9,6 +9,10 @@ import { StaticRouter } from "react-router";
import Main from "./main.jsx";
import securityHeaders from "./js/security-headers";
import { envUtilities, env } from "./js/env-server";
import crypto from "crypto";
const GA_ID = `UA-87658599-4`;
const GTM_ID = `GTM-KHLX47C`;
const app = express();
@ -39,8 +43,19 @@ const hstsMiddleware = helmet.hsts({
// disable x-powered-by
app.disable(`x-powered-by`);
// Some app security settings
app.use(helmet.contentSecurityPolicy(securityHeaders));
// app security settings
app.use((req, res, next) => {
// generate unique nonce for every response
res.locals.cspNonce = crypto.randomBytes(16).toString("hex");
// pass the same nonce to CSP
const cspMiddleware = helmet.contentSecurityPolicy(
securityHeaders(res.locals.cspNonce)
);
cspMiddleware(res, res, next);
});
app.use(
helmet.xssFilter({
@ -98,7 +113,7 @@ if (NODE_ENV !== `development`) {
});
}
function renderPage(appHtml, reactHelmet, canonicalUrl) {
function renderPage(appHtml, reactHelmet, canonicalUrl, cspNonce) {
const meta = {
url: canonicalUrl,
title: `Mozilla Pulse`,
@ -167,14 +182,28 @@ function renderPage(appHtml, reactHelmet, canonicalUrl) {
``
)}rss/latest">
${reactHelmet.title.toString()}
<meta name="ga-identifier" content="UA-87658599-4">
<meta name="gtm-identifier" content="GTM-KHLX47C">
<meta name="ga-identifier" content="${GA_ID}">
<meta name="gtm-identifier" content="${GTM_ID}">
${recaptcha}
</head>
<body>
<div id="app">${appHtml}</div>
<script type="application/json" id="environment-variables">${envUtilities.serializeSafeEnvAsJSON()}</script>
<script src="/bundle.js"></script>
<script nonce="${cspNonce}">
(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", "${GTM_ID}");
</script>
</body>
</html>`;
}
@ -197,7 +226,9 @@ app.get(`*`, (req, res) => {
res
.status(context.pageNotFound ? 404 : 200)
.send(renderPage(appHtml, reactHelmet, canonicalUrl));
.send(
renderPage(appHtml, reactHelmet, canonicalUrl, res.locals.cspNonce)
);
}
});