DEV Community

Chathura Rathnayaka
Chathura Rathnayaka

Posted on Originally published at backendrecipes.com

Patching CVE-2026-114509: Laravel TokenGuard API Authentication Bypass

A critical authentication bypass vulnerability tracked as CVE-2026-114509 (GHSA-f9x3-7vq9-cph6) affects Laravel applications running versions prior to 12.68.0 and 13.29.0.

When a route is protected by Laravel's standard token-based API guard (TokenGuard), the guard fails to validate that incoming credentials are strictly strings before passing them to the database query builder. Under common MySQL and MariaDB configurations, an unauthenticated attacker can supply a crafted non-string payload to bypass token verification and hijack an existing user account.


Vulnerability Summary & Affected Versions

Field Details
CVE Identifier CVE-2026-114509 / GHSA-f9x3-7vq9-cph6
Weakness Type CWE-1287 (Improper Type Validation) & CWE-287 (Improper Authentication)
Affected Versions laravel/framework < 12.68.0 and >= 13.0.0, < 13.29.0
Patched Versions Laravel 12.68.0+ and Laravel 13.29.0+
Impacted Component Illuminate\Auth\TokenGuard (driver => 'token' in config/auth.php)

How the Exploit Works (Type Coercion in MySQL)

When config/auth.php configures an API guard using the native token driver:

'guards' => [
    'api' => [
        'driver' => 'token',
        'provider' => 'users',
        'hash' => false,
    ],
],
Enter fullscreen mode Exit fullscreen mode

TokenGuard attempts to extract the token from the request query string (?api_token=...), the request body (input('api_token')), or the Bearer authorization header.

If an attacker sends a JSON body or query parameter where api_token is structured as an array or non-string primitive instead of a flat string:

{
  "api_token": {
    "0": 0
  }
}
Enter fullscreen mode Exit fullscreen mode

In unpatched versions of Laravel, if hash is false, TokenGuard passes the non-string input directly into UserProvider::retrieveByCredentials(). When Eloquent constructs the WHERE api_token = ? binding, MySQL or MariaDB may perform implicit type conversion or array-to-parameter binding quirks, evaluating the condition loosely and returning the first matching user record in the table.


Step 1: Audit Your Application for Exposure

Run Composer's built-in security audit in your project root to check if your locked laravel/framework version is vulnerable:

composer audit
Enter fullscreen mode Exit fullscreen mode

Next, check your current framework version:

php artisan --version
Enter fullscreen mode Exit fullscreen mode

Finally, inspect config/auth.php to see if any guard uses 'driver' => 'token':

grep -rn "'driver' => 'token'" config/
Enter fullscreen mode Exit fullscreen mode

Note: If your API exclusively uses **Laravel Sanctum* ('driver' => 'sanctum') or Laravel Passport ('driver' => 'passport'), your routes do not use the legacy TokenGuard lookup directly, though you should still upgrade laravel/framework to keep your dependency tree clean.*


Step 2: Upgrade laravel/framework to the Patched Release

Update your framework dependency to 12.68.0+ or 13.29.0+:

composer update laravel/framework --with-all-dependencies
Enter fullscreen mode Exit fullscreen mode

Verify the patched version is installed:

composer show laravel/framework | grep versions
Enter fullscreen mode Exit fullscreen mode

Ensure the output displays v12.68.0 (or higher) or v13.29.0 (or higher).


Step 3: Temporary Middleware Mitigation (If You Cannot Upgrade Immediately)

If your application is locked to an older release due to dependency constraints, enforce strict string type validation on api_token inputs via global middleware before the request reaches TokenGuard:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class EnsureApiTokenIsString
{
    public function handle(Request $request, Closure $next): Response
    {
        if ($request->has('api_token') && ! is_string($request->input('api_token'))) {
            abort(401, 'Invalid authentication token format.');
        }

        return $next($request);
    }
}
Enter fullscreen mode Exit fullscreen mode

Additionally, if you are still using 'driver' => 'token' in production, enable SHA-256 token hashing in config/auth.php ('hash' => true) or migrate your API authentication to Laravel Sanctum, which enforces strict token parsing and hashed database lookups out of the box.


Step 4: Restart Long-Running Workers After Patching

After deploying the updated composer.lock to production, restart your queue workers, Horizon daemons, and Octane processes so in-memory workers load the patched TokenGuard class:

php artisan optimize:clear
php artisan queue:restart
php artisan horizon:terminate
Enter fullscreen mode Exit fullscreen mode

Security Checklist

  1. Run composer audit in your CI/CD pipeline on every pull request to catch framework advisories early.
  2. Upgrade laravel/framework to at least 12.68.0 or 13.29.0.
  3. Replace legacy 'driver' => 'token' guards in config/auth.php with Laravel Sanctum.
  4. Link this patch with your runtime security checklist alongside Patching PHP2Shell CVE-2026-109618 & CVE-2026-109619.

Top comments (0)