Download the PHP package securized/laravel-ssrf without Composer
On this page you can find all versions of the php package securized/laravel-ssrf. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download securized/laravel-ssrf
More information about securized/laravel-ssrf
Files in securized/laravel-ssrf
Package laravel-ssrf
Short Description SSRF prevention for Laravel. Protect Http::, Guzzle, and validate user-supplied URLs against server-side request forgery.
License MIT
Homepage https://github.com/securized/laravel-ssrf
Informations about the package laravel-ssrf
Laravel SSRF Prevention
SSRF (Server-Side Request Forgery) prevention for Laravel. Protect Http::, raw Guzzle, and user-supplied URLs from being weaponised to reach internal infrastructure, cloud metadata endpoints, or private networks.
The problem
Fetching a user-supplied URL is a normal thing to do. Webhooks, link previews, avatar imports, "import from URL" buttons. The code usually looks like this:
Your server will happily fetch whatever it's pointed at, from a network position your users don't have. So an attacker submits:
On unpatched EC2 (IMDSv1), that returns your instance's IAM credentials. The same trick reaches http://localhost:6379 (Redis), your internal admin panel, or a Kubernetes API on a private subnet. Anything your server can route to but the internet can't.
Blocking this properly is harder than it looks. 127.0.0.1 is also http://0177.0.0.1/, http://2130706433/, and http://[::1]/. A hostname that resolves to a public IP when you check it can resolve to 127.0.0.1 a second later when Guzzle connects. This package handles those cases and validates every URL before the request leaves your application.
Installation
Publish the config file:
Quick Start
That's it. Requests to private IPs, localhost, link-local addresses (including cloud metadata endpoints), and non-HTTP(S) schemes are blocked out of the box.
Features
- Laravel HTTP Client macro:
Http::ssrf()andHttp::withSsrfProtection() - Raw Guzzle middleware: drop into any
HandlerStack - Validation rule:
new SsrfSafeUrl()for form/API input validation - Facade:
Ssrf::validate($url),Ssrf::isSafe($url),Ssrf::safeUrl($url) - IPv4 + IPv6: blocks private ranges for both address families
- DNS pinning: prevents DNS rebinding attacks
- Configurable: whitelist/blacklist for IPs, ports, domains, and schemes
- Immutable options: safe in long-running processes (Octane, RoadRunner)
Usage
Laravel HTTP Client
The ssrf() and withSsrfProtection() macros return a PendingRequest and chain normally with all other HTTP client methods:
Blocked requests throw a \GuzzleHttp\Exception\RequestException (the same exception Guzzle throws for failed requests), so your existing error handling works without changes.
Global Protection
To protect every outgoing Http:: request automatically, set auto_protect in your .env:
Or in config/ssrf.php:
Raw Guzzle
Use the static factory to add SSRF protection to any Guzzle client without the Laravel container:
Validation Rule
Validate user-supplied URLs in form requests or controllers:
The validation error message deliberately does not expose internal network details to end users.
Facade
Configuration
After publishing, edit config/ssrf.php:
Whitelist semantics
An empty whitelist for a type means "allow all" (subject to the blacklist). A non-empty whitelist means only the listed values are permitted. The blacklist always takes precedence.
Domain patterns
Domain entries are literal hostnames with * as a wildcard, matched
case-insensitively:
Dots are literal, so a pattern never matches more hosts than it appears to.
api.example.com matches that host and nothing else. Regex syntax is not
supported; characters like . and ( are matched literally.
IP ranges
IP entries support CIDR notation for both IPv4 and IPv6:
Per-Request Options
Override the global config for a single request using SsrfOptions:
SsrfOptions is immutable. Each method returns a new instance, so customising per-request never affects shared state.
DNS Pinning
DNS rebinding is an attack where a hostname initially resolves to a public IP (passing validation) but then re-resolves to a private IP for the actual request. Enabling pin_dns prevents this by resolving the hostname once, validating the IP, and then replacing the hostname in the URL with that IP for the actual request. The original Host header is preserved.
Note: DNS pinning may affect SSL certificate validation in some configurations.
What this does not protect against
Worth knowing before you rely on it:
- Second-order requests are your responsibility. Redirects are covered, as Guzzle re-enters the middleware for each hop, so a
302tohttp://169.254.169.254/is blocked (there are tests for this). But if you fetch a page, parse a URL out of the body, and request it yourself, that second request needs its own validation. - TOCTOU without DNS pinning. With
pin_dnsdisabled, the hostname is resolved once for validation and again by Guzzle when it connects. An attacker controlling the DNS response can return a public IP for the first lookup and a private one for the second. Enablepin_dnsto close this. - Blocked hosts are still distinguishable. Timing and error differences let an attacker infer which internal hosts exist. This is a port scan with a very narrow oracle, not data exfiltration, but it is not nothing.
- The blacklist covers documented ranges, not your network. If your internal services live on public IPs, add them to the blacklist yourself, nothing here can infer that.
Exception Hierarchy
All SSRF exceptions extend \Securized\Ssrf\Exceptions\SsrfException (itself a RuntimeException):
Catch SsrfException to handle any SSRF failure, or catch specific subclasses for fine-grained handling:
Testing
Changelog
Please see CHANGELOG for more information on what has changed recently.
Credits
The threat model and much of the test suite structure come from SSRF vs. Developers: A Study of SSRF-Defenses in PHP Applications (USENIX Security '24) by Malte Wessels, Simon Koch, Giancarlo Pellegrino and Martin Johns, of TU Braunschweig and CISPA Helmholtz Center for Information Security.
Their Table 2 enumerates the three ways a URL validation layer gets evaded, and this package defends against each:
| Evasion | Fix | Here |
|---|---|---|
| URL parser confusion | Well-established, hardened parser | Guzzle's PSR-7 Uri, plus parser differential tests |
| DNS rebinding | IP pinning | pin_dns |
| Redirects | Recheck on each redirect | Middleware runs per hop |
The paper describes IP pinning as "the only reliable defense against attacks targeting local resources without unduly restricting the versatility of the SSR feature".
Security Vulnerabilities
If you find a security issue in this package, please email [email protected] rather than opening a public issue.
License
The MIT License (MIT). Please see License File for more information.
All versions of laravel-ssrf with dependencies
spatie/laravel-package-tools Version ^1.16
illuminate/contracts Version ^11.0||^12.0||^13.0
guzzlehttp/guzzle Version ^7.0