mirror of
https://github.com/InvoiceShelf/InvoiceShelf.git
synced 2026-07-17 14:25:21 +00:00
v3 port. The Gotenberg PDF driver was missed when the SSRF guards were added to the AI, exchange-rate and file-disk drivers: gotenberg_host was validated only with 'url', and the driver POSTs the rendered HTML to it. Reuses the existing infrastructure (consistency with the other drivers): - Wires App\Rules\PublicHttpUrl into the gotenberg_host validation rule. - Adds PrivateNetworkGuard::assertAllowed() in GotenbergPdfDriver before the outbound call (covers env/seed/stale config + DNS rebinding). Adds a unit test asserting the gotenberg_host rule rejects private/loopback/ link-local addresses and allows a public one.
45 lines
1.4 KiB
PHP
45 lines
1.4 KiB
PHP
<?php
|
|
|
|
namespace App\Support\Pdf;
|
|
|
|
use App\Support\Net\BlockedUrlException;
|
|
use App\Support\Net\PrivateNetworkGuard;
|
|
use Gotenberg\Gotenberg;
|
|
use Gotenberg\Stream;
|
|
|
|
class GotenbergPdfDriver
|
|
{
|
|
public function loadView(string $viewname): GotenbergPdfResponse
|
|
{
|
|
$papersize = explode(' ', config('pdf.connections.gotenberg.papersize'));
|
|
if (count($papersize) != 2) {
|
|
throw new \InvalidArgumentException('Invalid Gotenberg Papersize specified');
|
|
}
|
|
|
|
$host = config('pdf.connections.gotenberg.host');
|
|
|
|
// SSRF guard: gotenberg_host is an admin-supplied URL the server POSTs
|
|
// the rendered HTML to. Block private/reserved/link-local targets even
|
|
// if set via env/seed/stale config or reachable through DNS rebinding.
|
|
try {
|
|
PrivateNetworkGuard::assertAllowed((string) $host);
|
|
} catch (BlockedUrlException $e) {
|
|
throw new \InvalidArgumentException('Invalid Gotenberg host: '.$e->getMessage());
|
|
}
|
|
|
|
$request = Gotenberg::chromium($host)
|
|
->pdf()
|
|
->margins(0, 0, 0, 0)
|
|
->paperSize($papersize[0], $papersize[1])
|
|
->html(
|
|
Stream::string(
|
|
'document.html',
|
|
view($viewname)->render(),
|
|
)
|
|
);
|
|
$result = Gotenberg::send($request);
|
|
|
|
return new GotenbergPdfResponse($result);
|
|
}
|
|
}
|