PHPackages                             synchro/laravel-violations - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. synchro/laravel-violations

ActiveLibrary[HTTP &amp; Networking](/categories/http)

synchro/laravel-violations
==========================

Client-side report handling for CSP and NEL for Laravel

v2.0.0(1mo ago)13[1 PRs](https://github.com/Synchro/laravel-violations/pulls)MITPHPPHP ^8.4CI passing

Since Jun 7Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/Synchro/laravel-violations)[ Packagist](https://packagist.org/packages/synchro/laravel-violations)[ Docs](https://github.com/synchro/laravel-violations)[ GitHub Sponsors]()[ RSS](/packages/synchro-laravel-violations/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (3)Dependencies (30)Versions (7)Used By (0)

Client-side report handling for Laravel
=======================================

[](#client-side-report-handling-for-laravel)

[![Latest Version on Packagist](https://camo.githubusercontent.com/5bfc7d06201f45e5cbc310316af73df9a1f8bddf2c20dd84b56d305c8490c818/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f73796e6368726f2f6c61726176656c2d76696f6c6174696f6e732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/synchro/laravel-violations)[![GitHub Tests Action Status](https://camo.githubusercontent.com/2a3bb75f6b5afed66b1a8f3b19d1161156a6dc2a55c45f893786b2e3ef4841bb/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f73796e6368726f2f6c61726176656c2d76696f6c6174696f6e732f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/synchro/laravel-violations/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/db25622f0c1e6193891781fd45a4736b02248852faed162899c155b57fe2b65c/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f73796e6368726f2f6c61726176656c2d76696f6c6174696f6e732f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/synchro/laravel-violations/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/e07e3a35097206ea25916049b283ded79bccda6bbeacefc49ec2a9d95203c945/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f73796e6368726f2f6c61726176656c2d76696f6c6174696f6e732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/synchro/laravel-violations)

This package provides a way to configure client-side reporting endpoint headers and handle the reports that they generate in Laravel.

Client-side errors can be reported by the `Content-Security-Policy` (CSP), Network Error Logging (`NEL`), `Permissions-Policy`, and several other mechanisms.

These headers make use of the `report-to` directive from CSP level 3, which targets a [named reporting endpoint](https://www.w3.org/TR/reporting-1/), and the deprecated `report-uri` directive from CSP level 2, which includes the reporting URL directly inside the CSP.

Aside from CSP2's `report-uri` directive, the URLs themselves are defined in a `Reporting-Endpoints` header, which can define one or more named endpoints to send reports to. The similar `Report-To` header was defined in an earlier revision of the standard, but has since been removed from the spec. However, some browsers implemented it, and the NEL header only works with `Report-To`, so this package supports both mechanisms by default.

Tip

You can find a good discussion of the differences between revisions of the Reporting API spec, and how to migrate between them on the [Chrome for developers blog](https://developer.chrome.com/blog/reporting-api-migration/).

This package can store the reports in the database and/or forward them to a report aggregation service, such as [report-uri.com](https://report-uri.com), allowing you to manage the enormous volumes of reports that are often generated without impacting the privacy of your users. Each report type has a DTO class that you can use to parse the report content.

It also generates events that you can listen for to take further action on the reports, such as logging or alerting.

While this package receives the reports, it doesn't do anything with them beyond store, parse, and forward them – anything more is up to you, but this may be all you need.

[Examples of some unusual but interesting CSP reports](https://github.com/nico3333fr/CSP-useful/blob/master/csp-wtf/explained.md).

Installation
------------

[](#installation)

This package requires PHP 8.4 and Laravel 12 or later.

Install the package with composer:

```
composer require synchro/laravel-violations
```

Publish the config file with:

```
php artisan vendor:publish --tag="violations-config"
```

Database support is optional; you may not want to keep the reports locally if you're forwarding them to an external report aggregation service. If you do want database support, set a table name in the config first, *then* publish and run the migration (or the migration will be ignored):

```
php artisan vendor:publish --tag="violations-migrations"
php artisan migrate
```

How reporting works
-------------------

[](#how-reporting-works)

It's worth reading [the docs on CSP violation reporting](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP#enabling_reporting).

There are two ways of defining target URLs to send reports to in CSP.

The preferred mechanism is [the `report-to` directive from CSP level 3](https://w3c.github.io/webappsec-csp/#directive-report-to) which targets a [named reporting endpoint](https://www.w3.org/TR/reporting-1/) from a `Reporting-Endpoints` or `Report-To` header, which can define one or more named endpoints to send reports to.

The second mechanism is [the deprecated `report-uri` directive defined in CSP level 2](https://www.w3.org/TR/CSP2/#directive-report-uri), which includes the reporting URL directly inside the CSP:

```
Content-Security-Policy: default-src 'self'; report-uri https://example.com/csp
```

One other difference is that `report-uri` can contain multiple URLs, whereas `report-to` can only contain a single target name. For compatibility with both at once, *this package only supports creating a single reporting URL per named endpoint*.

It's safe to define both directives; browsers that support `report-to` will ignore `report-uri` if it's also present, as per [the CSP level 3 spec](https://w3c.github.io/webappsec-csp/#directive-report-uri), and browsers that don't support `report-to` won't know what they're missing. The world is currently in a transition period where `report-uri` is deprecated, but support for `report-to` remains thin, so it's best to support both for now. Keep an eye on [caniuse.com](https://caniuse.com/mdn-http_headers_content-security-policy_report-to) for browser support updates.

Here's a complete example using both headers, along with CSP and NEL headers using them, along with a `report-uri` directive for CSP level 2:

```
Reporting-Endpoints: reports="https://example.com/report"
Report-To: {"group":"reports","max_age":86400,"endpoints":[{"url":"https://example.com/report"}]}, {"group":"nel","max_age":86400,"endpoints":[{"url":"https://example.com/nel"}]}
Content-Security-Policy: default-src 'self'; report-to reports; report-uri https://example.com/csp;
NEL: {"report-to": "nel"}
```

Creating reporting headers
--------------------------

[](#creating-reporting-headers)

This package provides a middleware that will add both the `Reporting-Endpoints` and deprecated `Report-To` headers to your responses, either of which is required for the `report-to` directive to work in either CSP3 or NEL. You can add this as global middleware (so it will be added to all responses) in `bootstrap/app.php`:

```
use \Synchro\Violation\Http\Middleware\AddReportingHeaders;
//...
->withMiddleware(function (Middleware $middleware) {
        $middleware->append(AddCspHeaders::class); //From Spatie's CSP package
        $middleware->append(AddReportingHeaders::class);
    })
```

You can also add it to specific routes or route groups if you only want it to apply to certain parts of your application.

Creating your CSP header
------------------------

[](#creating-your-csp-header)

This package does not generate your `Content-Security-Policy` header for you; create one manually, or using Spatie's [spatie/laravel-csp](https://packagist.org/packages/spatie/laravel-csp) package, and use this package to generate appropriate values to put in it.

### Building your own CSP

[](#building-your-own-csp)

You can set a CSP header manually on responses and use this package to generate the correct value for the directives you need. For example, to set the `report-to` directive, you can do something like this in your controller or middleware:

```
return response($content)
    ->header('Content-Security-Policy', 'default-src \'self\'; report-to '.Synchro\Violation\Violation::cspReportTo());
```

#### Enabling CSP hash reports

[](#enabling-csp-hash-reports)

If you want to enable [CSP hash reports](https://w3c.github.io/webappsec-csp/#reporting), add the `'report-sha256'` keyword (or `'report-sha384'` or `'report-sha512'` depending on which hash type you want to receive, and note that the single quotes around the values are required) to the `script-src` directive in your CSP header. With that in place, you will start receiving reports in the `csp-hash` format for *every script that your page loads*, sent to the same endpoint as your CSP reports. Note that this *only* works when you're using the CSP3 `report-to` directive, as no report format is defined for CSP2-style `report-uri` endpoints. Note that these reports are purely for usage monitoring, and do not represent a violation or error status; they are useful to help you keep track of exactly what software you are using. [Report-uri.com announced support for these reports in September 2025](https://scotthelme.co.uk/capture-javascript-integrity-metadata-using-csp/).

Tip

These reports do not have anything to do with SRI hashes used to spot unexpected changes to external scripts; they are simply a way to monitor which scripts are being loaded on your pages, useful for validating [SBOMs](https://www.cisa.gov/sbom) or dependency/vulnerability/compliance tracking.

### Using `spatie/laravel-csp`

[](#using-spatielaravel-csp)

[Spatie's CSP package for Laravel](https://github.com/spatie/laravel-csp) helps you build complex CSP headers using a nice fluent interface. While it supports the `report-uri` and `report-to` directives, you are expected to populate their values yourself; That's where this package can help out. In Spatie's CSP config file in `config/csp.php`, set the `report-to` and `report-uri` CSP directives to retrieve correctly formatted reporting endpoints that you defined in this package's config, using the helper functions, for example:

```
'report-uri' => \Synchro\Violation\Violation::cspReportUri(),
'report-to' => \Synchro\Violation\Violation::cspReportTo(),
```

There is also a `Spatie\Csp\Preset` class ready to use in `\Synchro\Violation\Support\AddReportingEndpointsPreset` which you can add to your Spatie CSP config to have it define the reporting directives for you.

Permissions-Policy reporting
----------------------------

[](#permissions-policy-reporting)

The `Permissions-Policy` header allows you to control the availability of various browser features on your site, such as geolocation, camera, microphone, etc. It also supports a `report-to` directive that works in much the same way as CSP's `report-to`, sending asynchronous violation reports when client-side code attempts to use a feature that has been disabled by the policy. Read [the official docs](https://www.w3.org/TR/permissions-policy/#reporting), and [this additional informative advice](https://github.com/w3c/webappsec-permissions-policy/blob/main/reporting.md). You can set up a `Permissions-Policy` header in your application that points at a named reporting endpoint defined in a `Reporting-Endpoints` or `Report-To` header, like this:

```
Permissions-Policy: geolocation=(); report-to=permissions, microphone=(); report-to=permissions

```

Unlike CSP, there is no global reporting endpoint for all directives, so you need to specify the `report-to` directive for every feature that you want to monitor, as you can see in the two features in the above example.

This package provides a DTO to parse inbound permissions policy violation reports, and can forward them just like other reports, but does nothing particular with them beyond that.

Network Error Logging (NEL)
---------------------------

[](#network-error-logging-nel)

This class also handles [Network Error Logging](https://www.w3.org/TR/network-error-logging/) reports. These are sent when a client-side network error occurs, such as a DNS lookup failure, TCP or TLS handshake failure (e.g. your CDN's certificate expired), or application-level HTTP events like forwarding loops or user aborts. You can set up an `NEL` header in your application that points at a named reporting endpoint defined in `Report-To` header, like this:

```
NEL: {"report-to": "nel"}

```

Just as for CSP, creating this header is left up to you, but note that the `report-to` target names and URLs *are* managed by this package, so use the same names.

Warning

NEL *only* supports endpoints defined with the `Report-To` header; the NEL spec does not know about `Reporting-Endpoints`, so it's not supported that way.

Tip

Be aware that NEL isn't very useful for site owners because it sends reports to the domain hosting the resource that failed to load, so if your site loads resources from third-party CDNs, it will send reports to them, not to you. You can only get reports for resources served from your own domain, which you would find out about from your own regular server logs anyway. It might be useful if you're operating a CDN, but not so much otherwise.

Receiving reports – routes and controllers
------------------------------------------

[](#receiving-reports--routes-and-controllers)

The package provides a route macro that you can use to define all the routes you need to receive reports. By default, it is configured to receive CSP level 3 and NEL reports (and any other `report-to`-compatible mechanism) at `/violations/reports`, and CSP level 2 reports at `/violations/csp`. You can change these by setting the prefix in your `.env` file, and configuring the suffixes in the endpoints defined in config – read the config file for more details. The short version is to add this line to your `web.php` route file:

```
Route::violations();
```

These routes point at a controller in `\Synchro\Violation\Http\Controllers\ViolationController` that provides a method to receive CSP2 reports called `csp()`, and one to handle CSP3, NEL, etc, called `reports()`.

Browsers will often send a preflight `OPTIONS` request to the reporting endpoint to check cross-origin permission (CORS) before sending the actual report; these routes are also set up for you, and also handled in the controller by the `options()` method.

Warning

None of these endpoints are intended to work directly in a browser; sending `GET` requests to reporting endpoints will result in `405 Method Not Allowed` errors.

When a report is received, it is parsed into a matching Data Transfer Object (DTO) built using Spatie's excellent [spatie/laravel-data](https://packagist.org/packages/spatie/laravel-data) package.

Be aware that the reporting mechanisms are deliberately designed to work "out of band" so that their traffic does not interfere with the performance of your site; the browser will accumulate reports and send them in batches after a delay, so you may receive multiple reports (possibly of multiple types) in a single request. The package will handle this for you and will parse each report individually, send events, store models, etc.

You can monitor the sending of reports in Chrome in its dev tools under the "Application" tab, then under the "Reporting API" section.

Tip

Chrome accumulates reports for up to one minute before bundling them and sending them to reporting endpoints. For privacy reasons, only reports sharing the same source URL will be included in a bundle, so 2 issues on `page1.html` might be sent together, but reports from `page1.html` and `page2.html` will always be sent separately, even if they occurred within the same minute.

### Trustworthy endpoints

[](#trustworthy-endpoints)

Testing report sending can be tricky because browsers are very picky about the circumstances under which they send reports. In particular, they will only send reports to TLS endpoints that conform to [a definition of "potentially trustworthy"](https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy), which may interfere with development practices, for example, it won't send reports to endpoints with self-signed certificates.

### Saving to the database

[](#saving-to-the-database)

If you have set a table name in the config (and run the associated migration, described above), reports will be saved in your database. There is a model defined in `\Synchro\Violation\Models\Violation` that you can use to query the reports stored in the database. The `report` field of this model contains the complete, unaltered report received from the client, and you can parse it using the provided DTO classes. Parsing and forwarding reports are independent of database storage – you don't have to store them, but if storage is not enabled, reports will be discarded if forwarding fails. See below for config.

### Events

[](#events)

On receiving a report, the package fires an event called `\Synchro\Violation\Events\Violation`, which you can listen for in your application to take further action, such as logging or alerting. The event carries a DTO for the report (not a model), so you can act on it directly.

### Forwarding

[](#forwarding)

For each reporting endpoint you define in the config file, you can provide a URL of an external service such as [report-uri.com](https://report-uri.com). These forwarded reports are sent by dispatching a queued job called `\Synchro\Violation\Jobs\ForwardReport` that will send the report to the configured endpoint. There is also a global on/off switch for forwarding in the `VIOLATIONS_FORWARD_ENABLED` env variable.

If database storage is not enabled, the report will be queued for forwarding, but if forwarding fails, the report will be discarded. If storage is enabled, the package will attempt to forward the report up to three times, but if all attempts fail, the report will still be available in the database. You can override the retry limit in your config in the `violations.max_forward_attempts` property, or the `VIOLATIONS_MAX_FORWARD_ATTEMPTS` env variable.

The package configures a kernel task to retry forwarding failed reports every hour using an artisan command called `violations:queue`.

Privacy concerns
----------------

[](#privacy-concerns)

While CSP and NEL reports are generally benign in content, they represent a privacy leak if you point them at a third-party aggregation service. Because reports are sent directly from the client's browser to the reporting service, it reveals the fact that someone is visiting your site, their IP, and their user-agent string, to the third-party site. Data leakage like this is flagged by [the Webbkoll privacy scanner](https://webbkoll.5july.net) for exactly this reason, and was one of the main reasons why I wrote this package.

When forwarding/proxying reports through this package to a reporting service, all reports will appear to originate from your server's IP addresses, not your clients' browsers. This means that things like geoIP country mapping will no longer work. It does, however, preserve user-agent strings, letting you spot issues relating to specific browser platforms and versions.

Another reason to proxy client-side reports is if your site is on a private network that has no external internet access. In that case you need to store the reports locally or forward them via a proxy service (such as this package provides), or you won't see the reports at all.

Testing
-------

[](#testing)

Tests are written using [pest](https://pestphp.com). You can run them with:

```
composer test
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Support open source development
-------------------------------

[](#support-open-source-development)

This package was written by Marcus Bointon, [@Synchro on GitHub](https://github.com/Synchro), and is released under the MIT open-source license. If you rely on it, please consider becoming [a GitHub Sponsor](https://github.com/sponsors/Synchro).

[![Report-uri.com](./report-uri-full.svg)](./report-uri-full.svg)Development of this package was supported by [report-uri.com](https://report-uri.com), a service that provides a simple way to aggregate and summarise vast volumes of client-side reports including CSP and NEL.

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

43

—

FairBetter than 91% of packages

Maintenance91

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity58

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 92.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~97 days

Total

4

Last Release

47d ago

Major Versions

v0.1.0 → v1.0.02025-11-24

v1.1.0 → v2.0.02026-03-26

### Community

Maintainers

![](https://www.gravatar.com/avatar/6e7028bcadbec2ee934da04d4d6232600481ac137b30b724ef116dfd55dbe9a9?d=identicon)[Synchro](/maintainers/Synchro)

---

Top Contributors

[![Synchro](https://avatars.githubusercontent.com/u/81561?v=4)](https://github.com/Synchro "Synchro (114 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (7 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (2 commits)")

---

Tags

laravelcspcontent-security-policyprivacypermissions-policynelMarcus Bointonlaravel-violationsNetwork Error Loggingreport-urireport-toReporting EndpointsReporting APIcsp-hash

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/synchro-laravel-violations/health.svg)

```
[![Health](https://phpackages.com/badges/synchro-laravel-violations/health.svg)](https://phpackages.com/packages/synchro-laravel-violations)
```

###  Alternatives

[bepsvpt/secure-headers

Add security related headers to HTTP response. The package includes Service Providers for easy Laravel integration.

5484.7M9](/packages/bepsvpt-secure-headers)[binaryk/laravel-restify

Laravel REST API helpers

651399.1k](/packages/binaryk-laravel-restify)[sunchayn/nimbus

A Laravel package providing an in-browser API client with automatic schema generation, live validation, and built-in authentication with a touch of Laravel-tailored magic for effortless API testing.

29428.0k](/packages/sunchayn-nimbus)[muhammadhuzaifa/telescope-guzzle-watcher

Telescope Guzzle Watcher provide a custom watcher for intercepting http requests made via guzzlehttp/guzzle php library. The package uses the on\_stats request option for extracting the request/response data. The watcher intercept and log the request into the Laravel Telescope HTTP Client Watcher.

98239.8k1](/packages/muhammadhuzaifa-telescope-guzzle-watcher)[vormkracht10/laravel-mails

Laravel Mails can collect everything you might want to track about the mails that has been sent by your Laravel app.

24149.7k](/packages/vormkracht10-laravel-mails)[pdphilip/cf-request

Cloudflare Laravel Request

2725.6k1](/packages/pdphilip-cf-request)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
