Skip to content

Cookbook

Cookbook

Deliver a webhook safely

use Illuminate\Support\Facades\Http;
use Cbox\Ssrf\Exceptions\BlockedUrl;

try {
    $response = Http::ssrf($endpoint->url)
        ->timeout(10)
        ->withHeaders(['X-Signature' => $signature])
        ->post($endpoint->url, $payload);
} catch (BlockedUrl) {
    $endpoint->markUndeliverable('destination is not a public address');
    return;
}

The connection is pinned and redirects are disabled, so a customer can't point a webhook at 169.254.169.254 — nor rebind DNS after registration.

Validate at registration and at delivery

Validate when the URL is saved (fast feedback) and again immediately before each delivery (a host's DNS can change). The macro does the delivery-time check for you; add the rule for the save-time one:

$request->validate(['url' => ['required', 'url', new PublicUrl]]);

Use your own HTTP client

If you don't want the macro, pull the pinned options and merge them yourself:

$guard = app(\Cbox\Ssrf\Contracts\UrlGuard::class);
$guard->assertSafe($url);

$response = Http::withOptions($guard->pinnedOptions($url))->get($url);

Validate an OAuth authorize URL (handed to the browser)

A redirect target the browser fetches is validated without a DNS lookup, so a legitimate corp-only IdP still saves:

$guard->assertSafeRedirect($connection->authorize_url);

Allow internal hosts on a single-tenant install

On-prem deployments that legitimately deliver to internal hosts can relax IP enforcement while keeping scheme/credential/host-block checks:

SSRF_ENFORCE=false

Add your own blocked ranges

Publish the config and extend blocked_cidrs / blocked_hosts — e.g. to block your own management subnet:

'blocked_cidrs' => [
    ...Symfony\Component\HttpFoundation\IpUtils::PRIVATE_SUBNETS,
    '203.0.113.0/24',
    '10.20.0.0/16', // internal management network
],