server/pages/index.js
function setUpCSP( req, res, next ) {
	const originalUrlPathname = req.originalUrl.split( '?' )[ 0 ];

	// We only setup CSP for /log-in* for now
	if ( ! /^\/log-in/.test( originalUrlPathname ) ) {
		next();
		return;
	}

	// This is calculated by taking the contents of the script text from between the tags,
	// and calculating SHA256 hash on it, encoded in base64, example:
	// `sha256-${ base64( sha256( 'window.AppBoot();' ) ) }` === sha256-3yiQswl88knA3EhjrG5tj5gmV6EUdLYFvn2dygc0xUQ
	// you can also just run it in Chrome, chrome will give you the hash of the violating scripts
	const inlineScripts = [
		'sha256-3yiQswl88knA3EhjrG5tj5gmV6EUdLYFvn2dygc0xUQ=',
		'sha256-ZKTuGaoyrLu2lwYpcyzib+xE4/2mCN8PKv31uXS3Eg4=',
	];

	req.context.inlineScriptNonce = crypto.randomBytes( 48 ).toString( 'hex' );

	const policy = {
		'default-src': [ "'self'" ],
		'script-src': [
			"'self'",
			"'report-sample'",
			"'unsafe-eval'",
			'stats.wp.com',
			'https://widgets.wp.com',
			'*.wordpress.com',
			'https://apis.google.com',
			`'nonce-${ req.context.inlineScriptNonce }'`,
			'www.google-analytics.com',
			...inlineScripts.map( hash => `'${ hash }'` ),
		],
		'base-uri': [ "'none'" ],
		'style-src': [ "'self'", '*.wp.com', 'https://fonts.googleapis.com' ],
		'form-action': [ "'self'" ],
		'object-src': [ "'none'" ],
		'img-src': [
			"'self'",
			'data',
			'*.wp.com',
			'*.files.wordpress.com',
			'*.gravatar.com',
			'https://www.google-analytics.com',
			'https://amplifypixel.outbrain.com',
			'https://img.youtube.com',
		],
		'frame-src': [ "'self'", 'https://public-api.wordpress.com', 'https://accounts.google.com/' ],
		'font-src': [
			"'self'",
			'*.wp.com',
			'https://fonts.gstatic.com',
			'data:', // should remove 'data:' ASAP
		],
		'media-src': [ "'self'" ],
		'connect-src': [ "'self'", 'https://*.wordpress.com/', 'https://*.wp.com' ],
		'report-uri': [ '/cspreport' ],
	};

	const policyString = Object.keys( policy )
		.map( key => `${ key } ${ policy[ key ].join( ' ' ) }` )
		.join( '; ' );

	// For now we're just logging policy violations and not blocking them
	// so we won't actually break anything, later we'll remove the 'Report-Only'
	// part so browsers will block violating content.
	res.set( { 'Content-Security-Policy-Report-Only': policyString } );
	next();
}
function setUpCSP( req, res, next ) {
	const originalUrlPathname = req.originalUrl.split( '?' )[ 0 ];

	// We only setup CSP for /log-in* for now
	if ( ! /^\/log-in/.test( originalUrlPathname ) ) {
		next();
		return;
	}

	// This is calculated by taking the contents of the script text from between the tags,
	// and calculating SHA256 hash on it, encoded in base64, example:
	// `sha256-${ base64( sha256( 'window.AppBoot();' ) ) }` === sha256-3yiQswl88knA3EhjrG5tj5gmV6EUdLYFvn2dygc0xUQ
	// you can also just run it in Chrome, chrome will give you the hash of the violating scripts
	const inlineScripts = [
		'sha256-3yiQswl88knA3EhjrG5tj5gmV6EUdLYFvn2dygc0xUQ=',
		'sha256-ZKTuGaoyrLu2lwYpcyzib+xE4/2mCN8PKv31uXS3Eg4=',
	];

	req.context.inlineScriptNonce = crypto.randomBytes( 48 ).toString( 'hex' );

	const policy = {
		'default-src': [ "'self'" ],
		'script-src': [
			"'self'",
			"'report-sample'",
			"'unsafe-eval'",
			'stats.wp.com',
			'https://widgets.wp.com',
			'*.wordpress.com',
			'https://apis.google.com',
			`'nonce-${ req.context.inlineScriptNonce }'`,
			'www.google-analytics.com',
			...inlineScripts.map( hash => `'${ hash }'` ),
		],
		'base-uri': [ "'none'" ],
		'style-src': [ "'self'", '*.wp.com', 'https://fonts.googleapis.com' ],
		'form-action': [ "'self'" ],
		'object-src': [ "'none'" ],
		'img-src': [
			"'self'",
			'data',
			'*.wp.com',
			'*.files.wordpress.com',
			'*.gravatar.com',
			'https://www.google-analytics.com',
			'https://amplifypixel.outbrain.com',
			'https://img.youtube.com',
		],
		'frame-src': [ "'self'", 'https://public-api.wordpress.com', 'https://accounts.google.com/' ],
		'font-src': [
			"'self'",
			'*.wp.com',
			'https://fonts.gstatic.com',
			'data:', // should remove 'data:' ASAP
		],
		'media-src': [ "'self'" ],
		'connect-src': [ "'self'", 'https://*.wordpress.com/', 'https://*.wp.com' ],
		'report-uri': [ '/cspreport' ],
	};

	const policyString = Object.keys( policy )
		.map( key => `${ key } ${ policy[ key ].join( ' ' ) }` )
		.join( '; ' );

	// For now we're just logging policy violations and not blocking them
	// so we won't actually break anything, later we'll remove the 'Report-Only'
	// part so browsers will block violating content.
	res.set( { 'Content-Security-Policy-Report-Only': policyString } );
	next();
}
function setUpCSP ( req , res , next ) { const originalUrlPathname = req . originalUrl . split ( '?' ) [ 0 ] ; // We only setup CSP for /log-in* for now if ( ! / ^\/log-in / . test ( originalUrlPathname ) ) { next ( ) ; return ; } // This is calculated by taking the contents of the script text from between the tags, // and calculating SHA256 hash on it, encoded in base64, example: // `sha256-${ base64( sha256( 'window.AppBoot();' ) ) }` === sha256-3yiQswl88knA3EhjrG5tj5gmV6EUdLYFvn2dygc0xUQ // you can also just run it in Chrome, chrome will give you the hash of the violating scripts const inlineScripts = [ 'sha256-3yiQswl88knA3EhjrG5tj5gmV6EUdLYFvn2dygc0xUQ=' , 'sha256-ZKTuGaoyrLu2lwYpcyzib+xE4/2mCN8PKv31uXS3Eg4=' , ] ; req . context . inlineScriptNonce = crypto . randomBytes ( 48 ) . toString ( 'hex' ) ; const policy = { 'default-src' : [ "'self'" ] , 'script-src' : [ "'self'" , "'report-sample'" , "'unsafe-eval'" , 'stats.wp.com' , 'https://widgets.wp.com' , '*.wordpress.com' , 'https://apis.google.com' , ` ${ req . context . inlineScriptNonce } ` , 'www.google-analytics.com' , ... inlineScripts . map ( hash => ` ${ hash } ` ) , ] , 'base-uri' : [ "'none'" ] , 'style-src' : [ "'self'" , '*.wp.com' , 'https://fonts.googleapis.com' ] , 'form-action' : [ "'self'" ] , 'object-src' : [ "'none'" ] , 'img-src' : [ "'self'" , 'data' , '*.wp.com' , '*.files.wordpress.com' , '*.gravatar.com' , 'https://www.google-analytics.com' , 'https://amplifypixel.outbrain.com' , 'https://img.youtube.com' , ] , 'frame-src' : [ "'self'" , 'https://public-api.wordpress.com' , 'https://accounts.google.com/' ] , 'font-src' : [ "'self'" , '*.wp.com' , 'https://fonts.gstatic.com' , 'data:' , // should remove 'data:' ASAP ] , 'media-src' : [ "'self'" ] , 'connect-src' : [ "'self'" , 'https://*.wordpress.com/' , 'https://*.wp.com' ] , 'report-uri' : [ '/cspreport' ] , } ; const policyString = Object . keys ( policy ) . map ( key => ` ${ key } ${ policy [ key ] . join ( ' ' ) } ` ) . join ( '; ' ) ; // For now we're just logging policy violations and not blocking them // so we won't actually break anything, later we'll remove the 'Report-Only' // part so browsers will block violating content. res . set ( { 'Content-Security-Policy-Report-Only' : policyString } ) ; next ( ) ; }
Sets up a Content Security Policy header
@see https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
@param {Object} req Express request object
@param {Object} res Express response object
@param {Function} next a callback to call when done
Sets up a Content Security Policy header