Safeguard
Application Security•

ASVS 5.0 V3.4.7: Add a Violation Reporting Endpoint to Your CSP

ASVS V3.4.7 (Level 3) says your Content-Security-Policy must name a place to send violation reports. Setup with report-to, an endpoint sketch, and how to verify it.

Safeguard Security Team
2 min read

ASVS 5.0 requirement V3.4.7 says the Content-Security-Policy header must specify where the browser should report violations. In practice that means a report-to directive, with a matching Reporting-Endpoints header, or the older report-uri. It is a Level 3 requirement.

Why it matters

A policy that blocks things silently is hard to operate. Reports tell you three useful things: a legitimate page broke after a deploy, a third party script changed, or someone is probing for injection. The third case is the valuable one, because an attempted inline script on a page that should never have one is a live signal that an input is reflected somewhere.

How to implement it

Send both headers:

Reporting-Endpoints: csp-endpoint="https://reports.example.com/csp"
Content-Security-Policy: default-src 'self'; object-src 'none'; base-uri 'none'; report-to csp-endpoint

For browsers that do not support report-to, add report-uri /csp-report as well.

A minimal collection endpoint in Express:

app.post("/csp-report",
  express.json({ type: ["application/csp-report", "application/reports+json", "application/json"], limit: "10kb" }),
  (req, res) => {
    logger.warn({ csp: req.body }, "csp violation");
    res.status(204).end();
  });

Treat the endpoint as untrusted input: cap the body size, rate limit it, never render the content as HTML and never trust the fields. Expect noise from browser extensions, so group by blocked URI and directive before alerting.

How to test it

Use report only mode in staging, add an inline script without a nonce, load the page and watch your endpoint log. You can also post a sample payload to check the endpoint accepts it:

curl -si -X POST https://app.example.com/csp-report \
  -H "Content-Type: application/csp-report" \
  -d '{"csp-report":{"blocked-uri":"inline","violated-directive":"script-src"}}'

Expect a 204. Verify the response header carries report-to or report-uri.

Common mistakes

Header names mismatch. The report-to token must match a name in Reporting-Endpoints.

No rate limit. Reports can flood your endpoint.

Nobody reads them. Route them to a dashboard or alert.

Quick check

Do reports slow users down?

No. Browsers send them in the background.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.