My Meteor app uses Helmet for implementing content security policy.
I’m using Helmet and getting one of these console.log messages:
:3000/:48 Refused to execute inline script because it violates the following Content Security Policy directive: “script-src …”
I’m trying to find out what script is being blocked.
I have Helmet initialized with these options:
const helmetOptions = {
crossOriginEmbedderPolicy: false,
contentSecurityPolicy: {
blockAllMixedContent: true,
directives: {
reportUri: '/report-violation',
defaultSrc: [self],
scriptSrc: [.....
The reportUri: '/report-violation'
setting gets Helmet to ping that endpoint on your server when a script doesn’t pass.
On my server, I have this set up to capture messages sent to ‘/report-violation’`:
WebApp.connectHandlers.use('/report-violation', function (req, res, next) {
debugger;
const report = req.body;
console.log('cp #2. Helmet CSP Violation:', report);
next();
});
The server function is being hit. req
is coming in with many key-value fields, but req.body
is undefined - here’s the server console.log:
cp #2. Helmet CSP Violation: undefined
cp #2. Helmet CSP Violation: undefined
Do I have the endpoint configured correctly?
This seems to be working:
WebApp.connectHandlers.use('/report-violation', (req, res, next) => {
// Check if the request method is POST
if (req.method === 'POST') {
let report = '';
req.on('data', chunk => {
report += chunk;
});
req.on('end', () => {
try {
// Attempt to parse the report as JSON
const parsedReport = JSON.parse(report);
try{
let violatedDirective = parsedReport["csp-report"]["violated-directive"]
let effectiveDirective = parsedReport["csp-report"]["effective-directive"]
let blockedUri = parsedReport["csp-report"]["blocked-uri"]
console.log('Helmet CSP Violation: ', blockedUri);
console.log('violated-directive: ', violatedDirective);
console.log('effective-directive: ', effectiveDirective);
console.log('-----');
}
catch (Exception){
console.log('No blockedUri was found.')
}
// Send a response indicating the method is allowed
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('POST method is allowed for this route.');
} catch (error) {
// Handle the case where the report is not valid JSON
console.error('Error parsing report as JSON:', error);
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end('Bad Request: Invalid JSON');
}
});
} else {
// If not POST, respond with a 405 status code and include the Allow header
res.writeHead(405, { 'Content-Type': 'text/plain', 'Allow': 'POST' });
res.end('Method Not Allowed');
}
// No need to call next() here since we're sending a response
});
Note: phind.com knew Meteor well enough to find this solution!
2 Likes