Laravel Open Redirect: How to Validate Redirect URLs and Prevent Phishing Attacks

Redirects using unvalidated user input let attackers craft links that appear to come from your domain but redirect victims to malicious sites.

High severity Application Security Updated 2026-05-01

The Problem

An open redirect occurs when your application redirects users to a URL taken from request input without validating that the URL is safe. Attackers exploit this by sending victims links like yourdomain.com/login?redirect=https://evil-site.com. Because the link starts with your trusted domain, users and email filters trust it. After login, the victim is redirected to the attacker's phishing page. This is commonly used in credential harvesting attacks.

How to Fix

  1. 1

    Validate redirect URLs against an allowlist

    Never redirect to arbitrary user-supplied URLs:

    // DANGEROUS
    return redirect($request->input('redirect'));
    // SAFE — validate against your own domain
    $url = $request->input('redirect', '/');
    if (!Str::startsWith($url, '/') || Str::startsWith($url, '//')) {
        $url = '/';
    }
    return redirect($url);
    // SAFEST — use named routes
    $allowed = ['dashboard', 'profile', 'settings'];
    $route = $request->input('redirect', 'dashboard');
    if (!in_array($route, $allowed)) {
        $route = 'dashboard';
    }
    return redirect()->route($route);
  2. 2

    Use Laravel's intended() for post-login redirects

    Laravel provides a built-in safe redirect mechanism for post-authentication flows:

    return redirect()->intended('/dashboard');

    This redirects to the URL the user originally requested (stored in the session by the auth middleware), falling back to /dashboard. Since the URL comes from the session (not user input), it cannot be manipulated by attackers.

  3. 3

    Audit all redirect() calls that use request input

    Search your codebase for potentially unsafe redirects:

    grep -rn 'redirect(.*request\|redirect(.*\$_GET\|redirect(.*input' app/ routes/ --include='*.php'
    Also check for:
    - header('Location: ' . $userInput)
    - Response::redirectTo($userInput)
    - redirect()->away($userInput) — this explicitly bypasses domain validation

    Every occurrence needs validation.

How to Verify

Test with an external URL:

curl -v 'https://yourapp.com/login?redirect=https://evil-site.com'

After login, the redirect should go to your default page (like /dashboard), not to the external URL. Also test protocol-relative URLs:

curl -v 'https://yourapp.com/login?redirect=//evil-site.com'

Run php artisan stackshield:scan --check=SS041 to verify.

Prevention

Only accept relative paths (starting with / but not //) for redirect parameters. Use Laravel's redirect()->intended() for auth flows. Never use redirect()->away() with user input. Add redirect validation to your code review checklist.

Frequently Asked Questions

Is Str::startsWith($url, '/') sufficient validation?

Not alone. The URL //evil-site.com starts with / but is a protocol-relative URL that redirects to an external domain. Always check for both: must start with / AND must not start with //.

Can open redirects lead to more than phishing?

Yes. Open redirects can be chained with other vulnerabilities: OAuth token theft (redirect authorization codes to attacker), SSRF (server-side request forgery), and bypassing URL-based security controls. Many bug bounty programs accept open redirect reports.

Related Security Terms

Detect This Automatically with StackShield

StackShield continuously monitors your Laravel application from the outside and alerts you when security issues are found. No installation required.

Start Free Trial