Security Tip: Validating (Secure) URLs!
[Tip #90] Did you know Laravel's URL validator lets you control which protocols you accept? Here's my recommendation...
Laravel's Validator is an essential piece to preventing unexpected and malicious inputs from making their way into our apps. It includes a long list of built-in validation rules that handle most common scenarios, with options to tweak these rules to refine the validation needed.
Today, we're taking a look at the url
validator, which verifies input fields contain valid URLs, and lets you define the allowed protocols for the URLs provided.
By default, the url
validator allows anything that looks like a URL:
Validator::make(
['link' => "https://evilhacker.dev"], // input
['link' => 'url'] // rule
)->passes();
// => TRUE
Validator::make(
['link' => "steam://evilhacker.dev"], // input
['link' => 'url'] // rule
)->passes();
// => TRUE
While this may not be an issue in some cases, there are many situations where the user would not expect to click on a user-submitted link in your app and be redirected to some external app.
To get around this, you can tell the validator what protocols are allowed by the validator, for example, we can require http
and https
URLs like this:
// INVALID LINK
Validator::make(
['link' => "steam://evilhacker.dev"], // input
['link' => 'url:http,https'] // rule
)->passes();
// => FALSE
// VALID LINK
Validator::make(
['link' => 'http://evilhacker.dev'], // input
['link' => 'url:http,https'] // rule
)->passes();
// => TRUE
My recommendation is to take it a step further, and require HTTPS URLs for all user input, if possible.
This will have the benefit of ensuring all user-submitted links are for secure (i.e. encrypted) sites, and will keep any your users safe from Downgrade attacks, etc. This may be incredibly important if your app deals with sensitive or private information (i.e. PII, PHI, etc), and needs to send users to external sites that also need to interact with this data.
// INVALID LINK
Validator::make(
['link' => "http://evilhacker.dev"], // input
['link' => 'url:https'] // rule
)->passes();
// => FALSE
// VALID LINK
Validator::make(
['link' => 'https://evilhacker.dev'], // input
['link' => 'url:https'] // rule
)->passes();
// => TRUE