PHPackages                             craftcms/url-validator - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Validation &amp; Sanitization](/categories/validation)
4. /
5. craftcms/url-validator

ActiveLibrary[Validation &amp; Sanitization](/categories/validation)

craftcms/url-validator
======================

Validate URLs and IP addresses against SSRF, DNS rebinding, and cloud-metadata attacks.

1.1.0(3w ago)170.2k1MITPHPPHP ^8.0.2CI passing

Since Jun 15Pushed 3w agoCompare

[ Source](https://github.com/craftcms/url-validator)[ Packagist](https://packagist.org/packages/craftcms/url-validator)[ Docs](https://github.com/craftcms/url-validator)[ RSS](/packages/craftcms-url-validator/feed)WikiDiscussions main Synced 2w ago

READMEChangelogDependencies (4)Versions (4)Used By (1)

URL Validator
=============

[](#url-validator)

[![Latest Version on Packagist](https://camo.githubusercontent.com/51bf532d49c7b9c6be3f1935817d24077714c5600da79dddb53370826fed171d/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6372616674636d732f75726c2d76616c696461746f722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/craftcms/url-validator)[![GitHub Tests Action Status](https://camo.githubusercontent.com/29a3d486873e22bd3c0637cd95d0b9b68b1dba5c8681a63db0d7af65e688d249/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6372616674636d732f75726c2d76616c696461746f722f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/craftcms/url-validator/actions?query=workflow%3Arun-tests+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/47d7a652b489e1a04ad7be9d23babbdbedbb3b7be3bd1040ad4873c487c183a5/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6372616674636d732f75726c2d76616c696461746f722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/craftcms/url-validator)

Validate URLs and IP addresses before opening a connection, to guard against [Server-Side Request Forgery (SSRF)](https://owasp.org/www-community/attacks/Server_Side_Request_Forgery) and DNS rebinding.

By default, the validator rejects:

- Schemes other than `http` and `https` (blocking `file://`, `ftp://`, `gopher://`, etc.)
- Raw IP literals, hex-encoded hostnames, and well-known cloud-metadata domains (AWS, GCP, Kubernetes, …)
- Hostnames that resolve to a private, reserved, loopback, link-local, CGNAT, or cloud-metadata IP address
- IPv6 addresses that embed or tunnel an IPv4 address (IPv4-mapped, NAT64, 6to4, Teredo, …)

All checks happen *before* any connection is opened, and the validator returns the set of IP addresses the host resolved to so you can pin the eventual connection to them (preventing DNS rebinding between validation and download).

Installation
------------

[](#installation)

Install the package via Composer:

```
composer require craftcms/url-validator
```

Usage
-----

[](#usage)

```
use CraftCms\UrlValidator\UrlValidationException;
use CraftCms\UrlValidator\UrlValidator;

$validator = new UrlValidator();
$url = 'https://example.com/image.jpg';

try {
    // Returns the validated IP addresses the host resolves to.
    $ips = $validator->validate($url);
} catch (UrlValidationException $e) {
    // The URL, or an IP it resolves to, is disallowed.
    echo $e->getMessage();
}
```

Use the resolved IPs to pin the connection (e.g. with cURL’s `CURLOPT_RESOLVE`) so the hostname can’t be re-resolved to a different, internal address between validation and the request:

```
$parts = parse_url($url);
$host = $parts['host'];
$port = $parts['port'] ?? ($parts['scheme'] === 'https' ? 443 : 80);

$client = new \GuzzleHttp\Client();
$response = $client->get($url, [
    'curl' => [
        // Pin the hostname/port to the IPs we just validated.
        CURLOPT_RESOLVE => ["$host:$port:" . implode(',', $ips)],
    ],
]);
```

### Validating an IP address directly

[](#validating-an-ip-address-directly)

```
$validator = new UrlValidator();

$validator->validateIp('8.8.8.8'); // true
$validator->validateIp('169.254.169.254'); // false (AWS metadata IP)
$validator->validateIp('10.0.0.5'); // false (private range)
```

`validateScheme(string $url): bool` and `validateHostname(string $url): bool` are also exposed if you need to check those pieces individually.

### Customizing DNS resolution

[](#customizing-dns-resolution)

By default hostnames are resolved against the system DNS. You can pass a custom resolver to the constructor — useful for testing, or for plugging in a caching/alternate resolver:

```
$validator = new UrlValidator(fn(string $host): array => [
    // ...resolved IP addresses for $host
]);
```

### Customizing other options

[](#customizing-other-options)

The following options can also be configured by passing an array to the constructor as a second parameter. The following options are customizable:

- `allowedSchemes`
- `disallowedHostnames`
- `disallowedIpv4Addresses`
- `disallowedIpv4Ranges`
- `ipv4FilterFlags` (the `FILTER_FLAG_IPV4` will always be added automatically)
- `ipv6FilterFlags` (the `FILTER_FLAG_IPV6` will always be added automatically)

See the codebase for the default values and expected types.

```
// Allow private IP addresses but keep the reserved ranges disallowed
$validator = new UrlValidator(options: ['ipv4FilterFlags' => FILTER_FLAG_NO_RES_RANGE]);
```

Testing
-------

[](#testing)

```
composer test
```

```
composer analyse
```

```
composer format
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Security vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

Credits
-------

[](#credits)

- [Pixel &amp; Tonic](https://github.com/craftcms)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

48

—

FairBetter than 94% of packages

Maintenance95

Actively maintained with recent releases

Popularity35

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 70% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~21 days

Total

2

Last Release

24d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/3ccdf8b493035de2343c55bd889513e3af5c04d5823482a2b186ad16adb1c3e3?d=identicon)[brandonkelly](/maintainers/brandonkelly)

---

Top Contributors

[![brandonkelly](https://avatars.githubusercontent.com/u/47792?v=4)](https://github.com/brandonkelly "brandonkelly (7 commits)")[![i-just](https://avatars.githubusercontent.com/u/4500340?v=4)](https://github.com/i-just "i-just (2 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")

---

Tags

urlvalidationsecurityIPcraftcmsssrf

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/craftcms-url-validator/health.svg)

```
[![Health](https://phpackages.com/badges/craftcms-url-validator/health.svg)](https://phpackages.com/packages/craftcms-url-validator)
```

###  Alternatives

[karser/karser-recaptcha3-bundle

Google ReCAPTCHA v3 for Symfony

1872.6M16](/packages/karser-karser-recaptcha3-bundle)[siriusphp/validation

Data validation library. Validate arrays, array objects, domain models etc using a simple API. Easily add your own validators on top of the already dozens built-in validation rules

180773.7k14](/packages/siriusphp-validation)[olssonm/l5-zxcvbn

Implementation of the zxcvbn project by @dropbox for Laravel. Uses zxcvbn-php by @bjeavons.

29333.3k1](/packages/olssonm-l5-zxcvbn)[progsmile/request-validator

Simple PHP Request Validator

37114.5k1](/packages/progsmile-request-validator)[rebelinblue/laravel-zxcvbn

Service provider to use the zxcvbn project by @dropbox in Laravel 5.4 and above

1165.3k](/packages/rebelinblue-laravel-zxcvbn)[laravel-validation-rules/ip

Validate if an ip address is public or private.

1629.7k](/packages/laravel-validation-rules-ip)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
