Endpoint for Handling Helmet reportUri Messages?

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