Send signed outgoing webhooks
Fed by the records themselves, delivered only to public HTTPS addresses checked at every attempt, retried, and switched off after repeated failures. A submitter's details travel only to webhooks that opted into them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
52
app/Support/Webhooks/PublicEndpoint.php
Normal file
52
app/Support/Webhooks/PublicEndpoint.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Support\Webhooks;
|
||||
|
||||
use App\Services\Media\HostResolver;
|
||||
|
||||
/**
|
||||
* Whether a URL is somewhere this server may send a request to: HTTPS, and a
|
||||
* host whose every address is public.
|
||||
*
|
||||
* The same rule the image downloader follows, for the same reason — the
|
||||
* request leaves from inside the stack, and without it a webhook pointed at
|
||||
* `http://postgres:5432` or the cloud's metadata service would be a way of
|
||||
* reaching them.
|
||||
*/
|
||||
final class PublicEndpoint
|
||||
{
|
||||
public function __construct(protected HostResolver $resolver) {}
|
||||
|
||||
/**
|
||||
* The address to connect to, or why not: `https_only`, `unresolvable` or
|
||||
* `private`.
|
||||
*
|
||||
* @return array{0: ?string, 1: ?string} [address, reason]
|
||||
*/
|
||||
public function check(string $url): array
|
||||
{
|
||||
$parts = parse_url($url);
|
||||
$host = $parts['host'] ?? null;
|
||||
|
||||
if (($parts['scheme'] ?? null) !== 'https' || blank($host)) {
|
||||
return [null, 'https_only'];
|
||||
}
|
||||
|
||||
$host = trim((string) $host, '[]');
|
||||
$addresses = filter_var($host, FILTER_VALIDATE_IP) ? [$host] : $this->resolver->resolve($host);
|
||||
|
||||
if ($addresses === []) {
|
||||
return [null, 'unresolvable'];
|
||||
}
|
||||
|
||||
foreach ($addresses as $address) {
|
||||
if (! filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_GLOBAL_RANGE)) {
|
||||
return [null, 'private'];
|
||||
}
|
||||
}
|
||||
|
||||
return [$addresses[0], null];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user