Secure a Laravel Application: OWASP Risks and Practical Defences

4 min readUpdated on

Secure a Laravel Application: OWASP Risks and Practical Defences

Laravel gives you secure primitives; it cannot decide who may access an invoice, which URL a server may fetch, or what a browser is allowed to load. Security is a set of explicit boundaries, tested at the same level as business behaviour.

Authorize on the server

Use policies for model actions and gates for capabilities. The controller invokes authorization before it reads or mutates data.

php
<?php

declare(strict_types=1);

namespace App\Policies;

use App\Models\User;

final class UserPolicy
{
    public function viewAny(User $user): bool
    {
        return $user->hasPermissionTo('users.view');
    }
}

For a super-admin escape hatch, put the rule in one reviewable place:

php
Gate::before(fn (User $user): ?bool => $user->isSuperAdmin() ? true : null);

On Laravel 11+, controller middleware is declared with HasMiddleware; constructor $this->middleware() is not the current pattern.

php
final class AdminUserController extends Controller implements HasMiddleware
{
    public static function middleware(): array
    {
        return ['auth', 'can:viewAny,'.User::class];
    }
}

Client-side hiding is UX, never authorization. Feature-test a denied user for every sensitive route.

Validate, bind and encode

Form Requests are the HTTP boundary. Use $request->validated(), not $request->only(), so unvalidated fields cannot slip into mass assignment. Eloquent and the query builder parameterize values; never concatenate input into SQL, shell commands or dynamic column names. Escape output by default and sanitize deliberately if user HTML is a product feature.

Credentials and sessions

Passwords use Laravel’s hashed cast or Hash::make()—hashes are not recoverable. API token systems should store token secrets hashed at rest; show the plaintext token only once. Encrypt reversible integration credentials with an encrypted cast, protect APP_KEY, and rotate secrets with an overlap plan.

Use Sanctum for first-party SPAs and personal access tokens when its model fits. Give tokens narrow abilities, revoke them on compromise, rate-limit login and reset endpoints, and enable email verification/MFA where the risk warrants it. Never log Authorization headers, cookies or reset URLs.

Browser and deployment boundaries

Serve only public/, set APP_DEBUG=false, use HTTPS and secure cookie settings. Add security headers deliberately: a Content-Security-Policy tailored to actual scripts, X-Content-Type-Options: nosniff, clickjacking protection, a strict referrer policy and HSTS after HTTPS is stable. Start CSP in report-only mode, inspect violations, then enforce it; copying a permissive policy defeats its purpose.

Audit Composer and npm dependencies in CI, pin intentional upgrades, and remove unused packages. composer audit reports known advisories; it is not a complete application security review.

SSRF, uploads and external input

An endpoint that fetches a user-provided URL can reach internal infrastructure. Parse and allow-list intended hosts, resolve DNS defensively, reject loopback, link-local and private address ranges, disable redirect surprises, set short timeouts and restrict egress at the network layer. A hostname regex alone is not protection.

Validate upload MIME type and size, store uploads outside the public root, generate server-side names and scan high-risk files. Signed URLs are useful for time-limited access, not a substitute for checking authorization.

Observe and rehearse

Log failed authentication and authorization with minimal identifiers; report unexpected exceptions to your error tracker without secrets or personal payloads. Queue listeners and webhooks must be idempotent. Security work is complete only when a test proves the bad path is rejected and an operator can investigate it safely.

Production checklist

  • Policies/Gates cover every sensitive action and are feature-tested.
  • Requests use validated data; database and shell input is never concatenated.
  • Tokens are scoped and hashed; secrets are encrypted or environment-owned.
  • HTTPS, debug settings, public web root and headers are reviewed per environment.
  • SSRF, upload and webhook boundaries have explicit tests and operational limits.

Related articles

Existing system support

Need help with a live application?

I help companies improve live systems, clean up delivery workflows, and ship new features without adding avoidable complexity.

Comments (0)
Sign in to leave a comment

You need to be signed in to add a comment.

Login

Need someone to take responsibility for the next step?

Let’s talk about your project and define a scope that actually makes sense for your goals.