jeffersongoncalves/laravel-ssrf-guard
Composer 安装命令:
composer require jeffersongoncalves/laravel-ssrf-guard
包简介
A Laravel package that protects outbound HTTP requests from SSRF (Server-Side Request Forgery): it validates that a URL's host resolves only to public IPs (denying private, reserved, loopback and link-local ranges by default), pins the connection to the validated IP to close the DNS-rebinding TOCTOU
README 文档
README
Laravel SSRF Guard
Whenever your application fetches a URL that came from a user — an avatar URL, a webhook target, a link preview, an imported og:image — it can be tricked into reaching internal services instead: http://localhost, http://10.0.0.1, or the cloud metadata endpoint http://169.254.169.254. That is Server-Side Request Forgery (SSRF).
Laravel SSRF Guard makes fetching untrusted URLs safe. It:
- validates that a URL's host resolves only to public IP addresses, denying private, reserved, loopback and link-local ranges by default (both IPv4
Aand IPv6AAAArecords); - pins the connection to the validated IP via curl's
CURLOPT_RESOLVE, closing the DNS-rebinding (TOCTOU) window where a domain flips to an internal IP between validation and connection; - performs a safe
GETthat follows redirects but re-validates every hop, so a public host cannot302you into an internal one.
Installation
You can install the package via composer:
composer require jeffersongoncalves/laravel-ssrf-guard
You can publish the config file with:
php artisan vendor:publish --tag="ssrf-guard-config"
This is the published config file:
return [ 'timeout' => (int) env('SSRF_GUARD_TIMEOUT', 8), 'max_redirects' => (int) env('SSRF_GUARD_MAX_REDIRECTS', 3), 'allowed_schemes' => ['http', 'https'], 'allow_private' => (bool) env('SSRF_GUARD_ALLOW_PRIVATE', false), ];
Usage
Resolve the guard from the container (it is registered as a singleton) or instantiate it directly.
Check whether a URL is safe to fetch
use JeffersonGoncalves\SsrfGuard\SsrfGuard; $guard = app(SsrfGuard::class); $guard->isPublicUrl('https://example.com'); // true $guard->isPublicUrl('http://127.0.0.1'); // false (loopback) $guard->isPublicUrl('http://10.0.0.1'); // false (private) $guard->isPublicUrl('http://169.254.169.254'); // false (link-local / metadata) $guard->isPublicUrl('ftp://example.com'); // false (scheme not allowed)
Use it to validate user input before storing or fetching it:
if (! app(SsrfGuard::class)->isPublicUrl($request->input('webhook_url'))) { abort(422, 'The URL must point to a public host.'); }
Fetch a URL safely
safeGet() performs the pinned, redirect-re-validating request and returns a standard Illuminate\Http\Client\Response. It throws JeffersonGoncalves\SsrfGuard\Exceptions\BlockedHostException if the URL — or any redirect hop — is not public:
use JeffersonGoncalves\SsrfGuard\SsrfGuard; use JeffersonGoncalves\SsrfGuard\Exceptions\BlockedHostException; try { $response = app(SsrfGuard::class)->safeGet($untrustedUrl); $body = $response->body(); } catch (BlockedHostException $e) { report($e); // The URL pointed at a non-public host — refuse to proxy it. }
You can pass extra HTTP Client options; they are merged over the safe defaults:
$response = app(SsrfGuard::class)->safeGet($url, [ 'headers' => ['Accept' => 'image/*'], ]);
Important
safeGet() guarantees the transport is not pointed at an internal host. It does not validate the response body. If you re-serve fetched content from your own origin (images, HTML), still validate the Content-Type and sanitize/transform the body to avoid stored XSS.
Getting the curl resolve pin
If you build your own request and just want the validated CURLOPT_RESOLVE entries, call resolveEntries() — it returns null for any non-public/unsupported URL:
$resolve = app(SsrfGuard::class)->resolveEntries('https://example.com'); // ['example.com:443:93.184.216.34'] (or null if not public)
Configuration
| Key | Default | Description |
|---|---|---|
timeout |
8 |
Maximum seconds a safeGet() request may run. |
max_redirects |
3 |
How many redirect hops to follow — each one is re-validated. |
allowed_schemes |
['http', 'https'] |
Schemes considered valid; everything else is rejected. |
allow_private |
false |
DANGER — when true, skips the private/reserved/loopback/link-local check. For local development only; never enable in production. |
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 1
- 点击次数: 1
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-20
