Laravel Agent
NoDisrupt can tell from the outside that a site is a Laravel application, but it cannot tell which version of Laravel or which Composer packages it is running - a Laravel app exposes no version header, generator tag or feed. And on managed hosting such as Laravel Cloud, Vapor or Forge there is no server to install the host agent on.
The Laravel agent closes that gap. It is a small Composer package that runs inside your app, reads what Composer actually installed, and reports the package list to NoDisrupt - once shortly after the app starts, and then daily. Each package is matched against known vulnerability advisories, and anything affected shows up on the monitor's vulnerabilities view. No host access is required.
How it works
- NoDisrupt's remote check fingerprints the site as Laravel (passively, from the response it already fetches) and creates one unversioned Laravel component.
- The agent supplies the detail the outside world cannot see: the name and resolved version of every installed Composer package.
- It sends that inventory shortly after the app boots and then on your app's own scheduler, so there is no inbound connection to open and no credentials for NoDisrupt to hold.
Requirements
- Laravel 10, 11, 12 or 13, on PHP 8.1 or newer.
- The app's scheduler running -
php artisan schedule:runevery minute, or your platform's scheduler. On Laravel Cloud and Vapor this is on by default. - Outbound HTTPS access to
api.production.nodisrupt.com.
Install
composer require nodisrupt/laravel-agent
The package self-registers through Laravel's package discovery - there is no service provider to add by hand.
Next, generate a key in NoDisrupt under Monitor -> Vulnerabilities -> Add the package, and set the two values it gives you in your environment:
NODISRUPT_KEY=your-key
NODISRUPT_MONITOR_ID=your-monitor-id
NODISRUPT_KEY is a live credential. On Laravel Cloud, Vapor or Forge, set it
in the platform's environment settings - don't commit it to your repository or
bake it into a Docker image.
That is the whole setup. The agent reports on its own shortly after the app next serves a request (so a fresh install or deploy shows up in seconds), and then daily; nothing else needs wiring up. The boot report runs after the response is sent, so it never slows a request, and is throttled to at most once per deploy.
Report now
You do not normally need to - installing or deploying triggers the first report. To send one immediately, to confirm the setup or after changing dependencies, run:
php artisan nodisrupt:report-inventory
A successful run prints NoDisrupt: dependency inventory reported. If the key
or monitor id is missing it prints a warning instead and sends nothing (see
Troubleshooting).
Configuration
The defaults suit most apps. To change the reporting cadence, publish the config file:
php artisan vendor:publish --tag=nodisrupt-config
This writes config/nodisrupt.php, which reads the following environment
values:
- NODISRUPT_KEY - the per-monitor credential minted in NoDisrupt. Required.
- NODISRUPT_MONITOR_ID - the id of the monitor the inventory is attached to. Required.
- NODISRUPT_API_BASE - the API endpoint the agent reports to. Defaults to
https://api.production.nodisrupt.com. - NODISRUPT_SCHEDULE - how often the scheduled report runs:
hourly,twiceDaily,dailyorweekly. Defaults todaily; an unrecognised value falls back todailyso a typo can't silently stop reporting. - NODISRUPT_REPORT_ON_BOOT - whether to also report shortly after the app
boots (throttled to at most once per deploy). Defaults to
true; set itfalseto rely on the schedule alone. Uses your cache store for the throttle.
Daily is the right cadence for almost everyone - a dependency list only changes
when you deploy. Reach for hourly only if you deploy many times a day and want
new packages matched sooner.
What it sends
On each run the agent reads Composer's runtime InstalledVersions and posts the
name and resolved version of every installed package, with development
dependencies flagged. Versions are normalised (a leading v is stripped) and
the list is de-duplicated and sorted.
That is all it sends. No source code, no environment variables, no secrets - only the package-and-version list needed to match against advisories.
It is a single POST to NODISRUPT_API_BASE/v1/agent/inventory, authenticated
with the key in an X-Agent-Authorization header:
{
"monitorId": 4821,
"ecosystem": "composer",
"packages": [
{ "name": "laravel/framework", "version": "11.9.2", "dev": false },
{ "name": "guzzlehttp/guzzle", "version": "7.8.1", "dev": false },
{ "name": "phpunit/phpunit", "version": "11.2.5", "dev": true }
]
}
Troubleshooting
"inventory not reported" when you run the command
The key or monitor id isn't set, or isn't visible to the process running the
command. Confirm NODISRUPT_KEY and NODISRUPT_MONITOR_ID are present in the
environment - on Laravel Cloud, Vapor or Forge, set them in the platform's
dashboard and redeploy so the running app picks them up.
No data appears after installing
The scheduled report only runs if the app's scheduler is running. Check the
command is registered with php artisan schedule:list - you should see
nodisrupt:report-inventory - and that php artisan schedule:run is wired to
cron (or that your platform's scheduler is enabled). To confirm the agent itself
works, run php artisan nodisrupt:report-inventory by hand.
The report sends but the monitor shows nothing matched
That is the healthy case - it means none of your installed packages match a known advisory. New advisories are matched against your latest reported inventory as they are published, so a clean result today can change without you reporting again.
Uninstall
Remove the package and delete the two environment values:
composer remove nodisrupt/laravel-agent
The remote Laravel fingerprint stays in place; only the Composer inventory stops being reported.