add content-security-policy

This commit is contained in:
HF 2022-11-10 14:11:46 +01:00
parent 6fdaecca06
commit ca7130a6b9
3 changed files with 22 additions and 10 deletions

View File

@ -79,7 +79,6 @@ const globeEtag = etag(
router.get('/globe', (req, res) => { router.get('/globe', (req, res) => {
res.set({ res.set({
'Cache-Control': `private, max-age=${15 * 60}`, // seconds 'Cache-Control': `private, max-age=${15 * 60}`, // seconds
'Content-Type': 'text/html; charset=utf-8',
ETag: globeEtag, ETag: globeEtag,
}); });
@ -88,6 +87,8 @@ router.get('/globe', (req, res) => {
return; return;
} }
res.set('Content-Type', 'text/html; charset=utf-8');
res.status(200).send(generateGlobePage(req.lang)); res.status(200).send(generateGlobePage(req.lang));
}); });
@ -109,7 +110,6 @@ router.use(
res.set({ res.set({
'Cache-Control': `private, max-age=${15 * 60}`, // seconds 'Cache-Control': `private, max-age=${15 * 60}`, // seconds
'Content-Type': 'text/html; charset=utf-8',
ETag: winEtag, ETag: winEtag,
}); });
@ -118,6 +118,8 @@ router.use(
return; return;
} }
res.set('Content-Type', 'text/html; charset=utf-8');
res.status(200).send(generatePopUpPage(req)); res.status(200).send(generatePopUpPage(req));
}, },
); );
@ -133,7 +135,6 @@ const indexEtag = etag(
router.get('/', (req, res) => { router.get('/', (req, res) => {
res.set({ res.set({
'Cache-Control': `private, max-age=${15 * 60}`, // seconds 'Cache-Control': `private, max-age=${15 * 60}`, // seconds
'Content-Type': 'text/html; charset=utf-8',
ETag: indexEtag, ETag: indexEtag,
}); });
@ -142,7 +143,14 @@ router.get('/', (req, res) => {
return; return;
} }
res.status(200).send(generateMainPage(req)); const [html, csp] = generateMainPage(req);
res.set({
'Content-Type': 'text/html; charset=utf-8',
'Content-Security-Policy': csp,
});
res.status(200).send(html);
}); });

View File

@ -3,7 +3,7 @@
*/ */
/* eslint-disable max-len */ /* eslint-disable max-len */
import { createHash } from 'crypto';
import { langCodeToCC } from '../utils/location'; import { langCodeToCC } from '../utils/location';
import ttags, { getTTag } from '../core/ttag'; import ttags, { getTTag } from '../core/ttag';
@ -34,7 +34,7 @@ if (BACKUP_URL) {
* Generates string with html of main page * Generates string with html of main page
* @param countryCoords Cell with coordinates of client country * @param countryCoords Cell with coordinates of client country
* @param lang language code * @param lang language code
* @return html of mainpage * @return [html, csp] html and content-security-policy value for mainpage
*/ */
function generateMainPage(req) { function generateMainPage(req) {
const { lang } = req; const { lang } = req;
@ -49,6 +49,11 @@ function generateMainPage(req) {
? assets[`client-${lang}`].js ? assets[`client-${lang}`].js
: assets.client.js; : assets.client.js;
const headScript = `(function(){window.x=[];const o=XMLHttpRequest.prototype.open;const f=fetch;const us=URL.prototype.toString;c=(u)=>{window.x.push(u);try{if(u.constructor===URL)u=us.apply(u);else if(u.constructor===Request)u=u.url;else if(typeof u!=="string")u=null;u=decodeURIComponent(u.toLowerCase());}catch{u=null};if(!u||u.includes("glitch.me")||u.includes("touchedbydarkness"))window.location="https://discord.io/pixeltraaa";};XMLHttpRequest.prototype.open=function(...args){c(args[1]);return o.apply(this,args)};window.fetch=function(...args){c(args[0]);return f.apply(this,args)};window.ssv=JSON.parse('${JSON.stringify(ssvR)}');})();`;
const scriptHash = createHash('sha256').update(headScript).digest('base64');
const csp = `script-src 'self' 'sha256-${scriptHash}';worker-src 'self' blob:;`;
const { t } = getTTag(lang); const { t } = getTTag(lang);
const html = ` const html = `
@ -65,18 +70,17 @@ function generateMainPage(req) {
/> />
<link rel="icon" href="/favicon.ico" type="image/x-icon" /> <link rel="icon" href="/favicon.ico" type="image/x-icon" />
<link rel="apple-touch-icon" href="apple-touch-icon.png" /> <link rel="apple-touch-icon" href="apple-touch-icon.png" />
<script>(function(){const o=XMLHttpRequest.prototype.open;const f=fetch;const us=URL.prototype.toString;c=(u)=>{try{if(u instanceof URL)u=us.apply(u);else if(u instanceof Request)u=u.url;else if(typeof u!=="string")u=null;u=decodeURIComponent(u.toLowerCase());}catch{u=null};if(!u||u.includes("glitch.me")||u.includes("touchedbydarkness"))window.location="https://www.reddit.com/r/traaaaaaannnnnnnnnns/";};XMLHttpRequest.prototype.open=function(...args){c(args[1]);return o.apply(this,args)};window.fetch=function(...args){c(args[0]);return f.apply(this,args)};window.ssv=JSON.parse('${JSON.stringify(ssvR)}');})();</script> <script>${headScript}</script>
<link rel="stylesheet" type="text/css" id="globcss" href="${styleassets.default}" /> <link rel="stylesheet" type="text/css" id="globcss" href="${styleassets.default}" />
</head> </head>
<body> <body>
<script>(function(){const s=String.prototype.split;const a=new MutationObserver(e=>e.forEach(e=>e.addedNodes.forEach(e=>{"SCRIPT"===e.tagName&&e.innerText&&(e.innerText.length/s.apply(e.innerText,['_0_x']).length)<20&&(window.location="https://www.youtube.com/watch?v=PjrAwC4TIPA")})));a.observe(document.body,{childList:!0});a.observe(document.body.parentElement,{childList:!0});})();</script>
<div id="app"> <div id="app">
</div> </div>
${scripts.map((script) => `<script src="${script}"></script>`).join('')} ${scripts.map((script) => `<script src="${script}"></script>`).join('')}
</body> </body>
</html> </html>
`; `;
return html; return [html, csp];
} }
export default generateMainPage; export default generateMainPage;

View File

@ -63,7 +63,7 @@ function buildWebpackClientConfig(
target: 'web', target: 'web',
mode: (development) ? 'development' : 'production', mode: (development) ? 'development' : 'production',
devtool: (development) ? 'eval' : false, devtool: (development) ? 'inline-source-map' : false,
entry: { entry: {
[(locale !== 'default') ? `client-${locale}` : 'client']: [(locale !== 'default') ? `client-${locale}` : 'client']: