Security Tip: Scoping Bindings

[Tip#23] Because who doesn't love to scope their bindings?

Security Tip: Scoping Bindings

If you use Laravel’s Implicit Route Bindings, you’ll most likely end up with a route that looks like this:

Route::get(
    '/projects/{project}/plans/{plan}', 
    function (Project $project, Plan $plan) {
        abort_unless($plan->project()->is($project), 404);

        // ...
    }
);

While it's easy to validate that the Plan is owned by the Project, you still need to remember to add it to your action, and it can look a bit ugly...

💡
Most all of the vulnerabilities I’ve discovered have come about because the developer forgot to include a single line of code to perform authentication, authorisation, or validation. Usually with the exact line required already written for another action in the same controller.

Luckily for us, Laravel has our backs (yet again). There is a handy little method in Laravel’s Routing system called scopeBindings(), which we can use to tell Laravel to automatically scope implicitly bound models.

Check it out:

Route::get(
    '/projects/{project}/plans/{plan}', 
    function (Project $project, Plan $plan) {
        // ...
    }
)->scopeBindings();

Laravel will automatically attempt to load the “child” binding from a relationship on the “parent” binding listed before it. In other words, in our example it will look for a matching Plan model from the plans relationship on the Project model. If the child binding isn’t found, it’ll throw a 404.

This is the same behaviour as our code above, but without that ugly abort_unless().

The best bit is, since it’s a route method we can use it in groups too! This solves the “forgetting to add it” problem, since you’ll typically group your routes and automatically add them into our scoped group.

Route::scopeBindings()
    ->group(function () {
        Route::get('/projects/{project}/plans/{plan}', ...);
        Route::get('/projects/{project}/plans/{plan}/edit', ...);
        Route::get('/projects/{project}/plans/{plan}/export', ...);
        // ...
});

Nice and simple, just the way we love it in Laravel!


👉 Looking to dive deeper into Laravel security? Check out Practical Laravel Security, my hands-on security course that uses interactive hacking challenges to teach you about how vulnerabilities work, so you can avoid them in your own code! 🕵️

👉 When was your last security audit or penetration test? Book in a Laravel Security Audit and Penetration Test today! 🕵️