class CspReportsController < ActionController::API
def create
Rails.logger.warn({
event: 'csp_report',
report: params.to_unsafe_h,
ip: request.remote_ip,
import crypto from 'crypto';
import helmet from 'helmet';
import type { Express, Request, Response, NextFunction } from 'express';
function cspNonce(req: Request, res: Response, next: NextFunction): void {
res.locals.cspNonce = crypto.randomBytes(16).toString('base64');
Rails.application.config.content_security_policy do |policy|
policy.default_src :self
policy.font_src :self, :https, :data
policy.img_src :self, :https, :data, "https://cdn.example.com"
policy.object_src :none
policy.script_src :self, :https
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'nonce-$request_id'; style-src 'self' https://fonts.googleapis.com 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com data:; connect-src 'self' https://api.example.com; frame-ancestors 'none'; base-uri 'self'; object-src 'none'" always;
import { randomBytes } from 'crypto';
import { Request, Response, NextFunction } from 'express';
interface CspOptions {
reportOnly?: boolean;
reportUri?: string;