Broken Object Level Authorization

Broken Object Level Authorization in Laravel [Apr 2026] [CVE-2026-34456]

[Updated Apr 2026] Updated CVE-2026-34456

Overview

The real-world impact of Broken Object Level Authorization (BOLA) in Laravel-based apps can be severe when OAuth or social login flows are tied to user accounts by weak identifiers. CVE-2026-34456 describes a vulnerability in Reviactyl, a Laravel-based open-source game server management panel, where the OAuth authentication flow automatically linked social accounts based solely on matching email addresses. An attacker could create or control a social account (Google, GitHub, Discord, etc.) using a victim’s email and gain full access to the victim’s account without any password or prior authentication, resulting in complete account takeover. The vulnerability was fixed in version 26.2.0-beta.5. This class of vulnerability manifests in Laravel when the application logic uses user emails as the primary means to fuse OAuth identities with application users, effectively bypassing ownership verification. If the code creates or locates a user by email and immediately associates the social provider identity to that user, an attacker who can produce an orphaned or controlled social identity with the victim’s email can hijack the account. The fix requires decoupling social identity linkage from a non-authenticated email match, and instead tying OAuth identities to an authenticated user session or requiring explicit verification for new accounts. In practice, Laravel developers should implement authentication-aware linking: only link a social provider to an account when the user is already authenticated, or require explicit user action plus email verification for new accounts. Ensure you first resolve whether a social account is already linked to any user (by provider_id), and avoid creating or linking via email alone. Add strong auditing/logging to detect unusual linking activity and test with scenarios where an attacker attempts to link via email to an existing account.

Affected Versions

26.2.0-beta.1 to < 26.2.0-beta.5 (i.e., 26.2.0-beta.1 through 26.2.0-beta.4)

Code Fix Example

Laravel API Security Remediation
<?php
use App\Models\User;
use App\Models\SocialAccount;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;

class OAuthController extends Controller {
    // Vulnerable pattern (for reference): links by email without ownership verification
    public function vulnerableCallback($provider, $socialUser) {
        $email = $socialUser->getEmail();
        $user = User::where('email', $email)->first();

        if (!$user) {
            $user = User::create([
                'name' => $socialUser->getName(),
                'email' => $email,
                'password' => bcrypt(Str::random(16)),
            ]);
        }

        // Automatically link the social account to the user found by email
        $user->socialAccounts()->create([
            'provider' => $provider,
            'provider_id' => $socialUser->getId(),
        ]);

        Auth::login($user);
        return redirect()->intended('/home');
    }

    // Secure pattern: authenticate before linking; do not link by email alone
    public function secureCallback($provider, $socialUser) {
        // If this social account is already linked to a user, log them in
        $account = SocialAccount::where('provider', $provider)
            ->where('provider_id', $socialUser->getId())
            ->first();

        if ($account) {
            Auth::login($account->user);
            return redirect()->intended('/home');
        }

        // If a user is already authenticated, allow linking to their account
        if (Auth::check()) {
            $user = Auth::user();

            // Prevent duplicate linking of the same provider/provider_id
            if (!$user->socialAccounts()->where('provider', $provider)
                ->where('provider_id', $socialUser->getId())
                ->exists()) {
                $user->socialAccounts()->create([
                    'provider' => $provider,
                    'provider_id' => $socialUser->getId(),
                    'email' => $socialUser->getEmail(),
                ]);
            }
            return redirect()->route('account')->with('status', 'Linked successfully');
        }

        // For new users, require explicit sign-up and email verification
        throw new \Exception('Email verification is required to create a new account via social login.');
    }
}
?>

CVE References

Choose which optional cookies to allow. You can change this any time.