Skip to content

Security

Dashboard hardening

Restrict access with middleware

By default, the dashboard uses ['web', 'auth'] middleware — any authenticated user can view it. For production, restrict access further:

config/crontinel.php
'middleware' => ['web', 'auth', 'can:viewCrontinel'],

Define the viewCrontinel gate in a service provider:

Gate::define('viewCrontinel', function ($user) {
return in_array($user->email, explode(',', env('CRONTINEL_ADMIN_EMAILS', '')));
});

Or use a role check if you have a role system:

Gate::define('viewCrontinel', fn ($user) => $user->hasRole('admin'));

Move the dashboard path

Change the default /crontinel path to something less predictable:

CRONTINEL_PATH=internal/ops/monitor

The dashboard is then at /internal/ops/monitor. Security through obscurity alone isn’t sufficient — always require authentication — but an unusual path reduces automated scanning.

HTTPS only

The dashboard exposes operational data (job names, queue depths, failure rates). Always serve it over HTTPS in production. In Laravel, force HTTPS by setting APP_URL to an https:// URL and using URL::forceScheme('https') in a service provider if your server terminates TLS upstream.


What data the package captures

Crontinel records the following from your Laravel application:

Data typeWhat’s capturedWhat’s NOT captured
Cron runsCommand name, status, duration, exit codeCommand arguments (see note)
QueueQueue name, depth count, failed countJob payloads, job class arguments
HorizonStatus, supervisor count, failed/min rateJob data, worker logs

No user data, no request data, no environment variables, and no application secrets are captured.

Note on command arguments: The package resolves the scheduled task’s command string via Laravel’s Command class, which includes arguments passed to the Artisan command. If your scheduled task commands contain secrets (API keys, passwords) as arguments, those values will be recorded. Avoid passing secrets as command arguments in scheduled tasks.

Note on output: When a scheduled task fails, the exception message is stored as output. If the exception message contains sensitive data, it will be captured.

Job output can optionally be captured if 'capture_output' => true is set in config/crontinel.php, but this is disabled by default and should only be enabled if your job output contains no sensitive data.


What data is sent to the SaaS

Nothing is sent unless CRONTINEL_API_KEY is set in your environment.

When the key is present, the package sends the data types listed above (cron summaries, queue snapshots, Horizon status) to app.crontinel.com over HTTPS. Data is transmitted as JSON in the request body.

If you operate in an air-gapped or restricted environment, omit CRONTINEL_API_KEY entirely. The local dashboard works without it.


Webhook HMAC signing

When Crontinel fires an outbound webhook alert, it signs the request body with HMAC-SHA256 using a secret you define. This lets your endpoint verify the request came from Crontinel and wasn’t tampered with.

Configuring the secret

CRONTINEL_WEBHOOK_SECRET=your-signing-secret
config/crontinel.php
'webhook' => [
'url' => env('CRONTINEL_WEBHOOK_URL'),
'secret' => env('CRONTINEL_WEBHOOK_SECRET'),
],

Verifying the signature

Crontinel adds an X-Crontinel-Signature header to every webhook request:

X-Crontinel-Signature: sha256=<hex_digest>

Verify it in your endpoint:

$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_CRONTINEL_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $payload, env('CRONTINEL_WEBHOOK_SECRET'));
if (! hash_equals($expected, $signature)) {
http_response_code(401);
exit('Invalid signature');
}

Use hash_equals() to prevent timing attacks.


Additional recommendations

  • Rotate CRONTINEL_API_KEY regularly if you use the SaaS. Revoke and reissue from the app dashboard under Settings → API Keys.
  • Use a dedicated alert email address (alerts@your-company.com) rather than a personal inbox — this makes it easier to audit who receives operational alerts.
  • Audit team members on your Crontinel account periodically. Access is managed per-team; remove former employees from the dashboard team as part of your offboarding checklist.