The HTML meta tag approach has several limitations compared to HTTP headers. Be aware of these before choosing this method:
Content-Security-Policy-Report-Only equivalent. Violations will be blocked immediately.report-uri or report-to - reporting directives are ignored in meta-delivered CSP, and a meta tag can’t send the companion Reporting-Endpoints header that report-to needs. If you paste a policy from the editor, drop the report-to csp-endpoint part - it does nothing here. Use the JavaScript workaround below to forward violations to CSP Warden (see Step 2), or switch to HTTP headers.frame-ancestors or sandbox - these directives are also ignored when delivered via a meta tag.<head> and should appear as early as possible, before any scripts or stylesheets load.For full reporting, report-only mode, and all directives, use HTTP headers instead.
Place a <meta> tag inside your <head> as early as possible - before any scripts or stylesheets:
<!DOCTYPE html>
<html lang="en">
<head>
<!-- CSP meta tag - place as early as possible -->
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;">
<meta charset="UTF-8">
<title>Your Page</title>
</head>
<body>
<!-- Your content -->
</body>
</html>This enforces the policy immediately - any resources violating it will be blocked. Start with a permissive policy and tighten it gradually as you review violations.
Since report-uri is ignored in meta tags, add a small JavaScript snippet to capture violations and forward them to CSP Warden. The browser fires a securitypolicyviolation event for every blocked resource:
<!-- Save as csp-report.js and load via <script src="csp-report.js"></script> -->
<script>
document.addEventListener("securitypolicyviolation", function(e) {
var report = {
"csp-report": {
"document-uri": e.documentURI,
"blocked-uri": e.blockedURI,
"violated-directive": e.violatedDirective,
"effective-directive": e.effectiveDirective,
"original-policy": e.originalPolicy,
"referrer": e.referrer,
"source-file": e.sourceFile,
"line-number": e.lineNumber,
"column-number": e.columnNumber
}
};
fetch("https://cspwarden.com/api/v1/csp-report/YOUR-DOMAIN-TOKEN/", {
method: "POST",
headers: { "Content-Type": "application/csp-report" },
body: JSON.stringify(report),
keepalive: true
}).catch(function() {});
});
</script>script-src 'self', save the code as an external .js file hosted on the same origin. If you inline it, add a sha256 hash of the script to your script-src directive.Open your page in the browser and verify everything is working:
F12) and check the Console tab for CSP violation messagescspwarden.comTip: Start with a permissive policy like default-src 'self' https: and gradually tighten it as you review violations in your dashboard.
Add the meta tag to your site's base template so it applies to every page:
_layouts/default.html)layouts/partials/head.html or your base templategatsby-ssr.js onRenderBody API or react-helmet_document.tsx or the Head component<head><head> and appears before any resources it should govern. Meta tags in <body> are ignored by browsers.