Apr 9, 2026·5 min read·37 visits
Laravel Passport before 13.7.1 allows client credentials tokens to authenticate as real users if client UUIDs are disabled. The TokenGuard incorrectly uses the numeric client identifier as a user ID, leading to full authentication bypass.
An authentication bypass vulnerability in Laravel Passport allows machine-to-machine client credentials tokens to inadvertently authenticate as unrelated users. This occurs due to improper validation of the JWT subject claim when UUIDs are disabled for OAuth clients, resulting in an integer collision between client IDs and user primary keys.
Laravel Passport provides OAuth2 server support for Laravel applications. It relies on the thephpleague/oauth2-server library for core OAuth2 operations. The vulnerability resides in how Passport processes access tokens issued under the client_credentials grant type.
In a client_credentials flow, authentication occurs machine-to-machine. There is no associated user context. The underlying OAuth2 server correctly reflects this by setting the JWT sub (subject) claim to the client identifier because no user identifier is present during token issuance.
Prior to version 13.7.1, Passport's TokenGuard did not validate whether the sub claim represented a user or a client before querying the database. When applications explicitly configured Passport to use integer client IDs, a direct collision between client IDs and user IDs became possible.
The Laravel\Passport\Guards\TokenGuard::authenticateViaBearerToken() method resolves an authenticated user from an incoming Bearer token. It retrieves the oauth_user_id attribute from the parsed PSR-7 request, which corresponds directly to the JWT sub claim.
The method immediately passes this value to the user provider's retrieveById() method. The provider issues a database query to find a user matching the provided integer ID. If the application configuration disables UUIDs for OAuth clients via Passport::$clientUuids = false, both the oauth_clients and users tables share an overlapping integer ID space.
When a machine-to-machine client authenticates, the resulting token contains its numeric client identifier in the sub claim. The TokenGuard extracts this numeric identifier and passes it to the user provider. The application then resolves an actual user account possessing the same numeric primary key.
The vulnerability was patched in version 13.7.1 by modifying the authentication logic within src/Guards/TokenGuard.php. The patch introduces strict validation to ensure that a client_credentials token is not used to falsely authenticate a user session.
Before the patch, the guard simply checked if the oauth_user_id was not empty. It lacked contextual awareness of the grant type used to generate the token. The numeric client ID passed through without scrutiny.
// Vulnerable logic in TokenGuard.php
$oauthUserId = $psr->getAttribute('oauth_user_id');
if (empty($oauthUserId)) {
return null;
}
return $this->provider->retrieveById($oauthUserId);The patched code implements a specific check for the collision scenario. It verifies if the oauth_user_id exactly matches the oauth_client_id and checks whether the token was issued via the client_credentials grant type.
// Patched logic in TokenGuard.php
$oauthUserId = $psr->getAttribute('oauth_user_id');
if (empty($oauthUserId) || ($oauthUserId === $psr->getAttribute('oauth_client_id') && $client->hasGrantType('client_credentials'))) {
return null;
}
return $this->provider->retrieveById($oauthUserId);Exploiting this vulnerability requires the attacker to possess valid client credentials for an application configured with integer client IDs. The target environment must have Passport::$clientUuids explicitly set to false in its configuration.
The attacker begins by authenticating against the OAuth2 token endpoint. They request an access token using the client_credentials grant type, providing their known client ID and client secret.
curl -X POST http://api.example.com/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "client_credentials",
"client_id": "5",
"client_secret": "known-secret"
}'The server responds with a valid JWT access token. The attacker then attaches this token as a Bearer authorization header in a subsequent request directed at an endpoint protected by the auth:api middleware. The application incorrectly authenticates the request as the user whose primary key matches the attacker's client ID.
The vulnerability results in a direct authentication bypass and unauthorized access to user data. An attacker operating a machine-to-machine client gains the ability to impersonate an unrelated user account without requiring the user's credentials.
The exact scope of the impact depends on the privileges associated with the impersonated user account. If the matched user is an administrator, the attacker achieves complete control over the application. The integrity and confidentiality of the victim's data are severely compromised.
The CVSS v3.1 base score is 6.8. The score reflects the network-based attack vector and low privilege requirements. The complexity is rated high because exploitation strictly depends on a non-default configuration (Passport::$clientUuids = false) and the existence of a corresponding numeric user ID.
The primary remediation strategy is upgrading the laravel/passport package to version 13.7.1 or later. The patch effectively neutralizes the vulnerability by explicitly blocking user resolution for client_credentials tokens when the user ID matches the client ID.
If immediate patching is not feasible, administrators should re-enable UUIDs for OAuth clients. This involves setting Passport::$clientUuids = true. Changing this configuration requires migrating existing client records to use UUIDs, which breaks backward compatibility for established integrations.
A secondary mitigation involves disabling the client_credentials grant type if it is not actively utilized. Alternatively, developers can implement custom middleware to inspect incoming requests. The middleware must verify that tokens utilizing the client_credentials grant are restricted from accessing user-specific endpoints.
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
laravel/passport Laravel | < 13.7.1 | 13.7.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-287 |
| Attack Vector | Network |
| CVSS Base Score | 6.8 |
| Impact | Authentication Bypass / Impersonation |
| Exploit Status | Unweaponized / Conditional |
| Required Configuration | Passport::$clientUuids = false |
Software does not properly prove that a user or entity is who they claim to be, leading to an authentication bypass.
Payload CMS, a popular open-source headless Content Management System, contains a critical Regular Expression Denial of Service (ReDoS) and uncontrolled resource consumption vulnerability in versions prior to 3.90.0 and canary versions prior to 4.0.0-canary.34. Due to nested quantifiers in the multipart boundary regex validation pattern, and the absence of streaming backpressure controls, remote attackers can trigger catastrophic backtracking and memory exhaustion. This blocks the single-threaded Node.js event loop, resulting in a persistent and complete Denial of Service (DoS).
An Improper Access Control vulnerability (CWE-284) in Payload CMS prior to version 3.90.0 and 4.0.0-canary.34 allows authenticated, low-privileged users to bypass field-level access control restrictions and overwrite the password of other accounts, leading to complete account takeover and privilege escalation.
Payload CMS was discovered to use an insecure default configuration for its password-hashing mechanism. The system requested a 512-byte key from PBKDF2-HMAC-SHA256 with 25,000 iterations, creating a severe cryptographic asymmetry. While the defending server sequentially computed 16 blocks of key material (equivalent to 400,000 internal iterations), an offline attacker only needed to compute the first 32-byte block to verify password guesses. This allowed offline attackers to crack stolen database hashes 16 times faster than intended by the security design.
VectorFreed identifies a critical Use-After-Free (UAF) memory corruption vulnerability in librsvg (CVE-2026-96889), which manifests when parsing structured SVG documents containing nested XML inclusions (XIncludes) and duplicate entity declarations. The flaw results from an entity ownership conflict where librsvg prematurely deallocates an xmlEntity structure still actively referenced by the underlying libxml2 parser context. When transitively compiled into downstream applications such as the high-performance sharp image processing library, this vulnerability facilitates denial of service and unauthenticated remote code execution on the host operating system.
CVE-2026-102275 (GHSA-x33g-cr3x-6449) is a public/private key identity confusion vulnerability in PyJWT versions 2.1.0 through 2.14.0. When importing Octet Key Pair (OKP) JSON Web Keys (JWKs) representing Ed25519 or Ed448 curves, PyJWT fails to verify that the public parameter 'x' matches the private parameter 'd'. An attacker can construct a hybrid JWK combining a victim's public key with the attacker's private key. In protocols like DPoP that bind sessions via public key thumbprints, this allows the attacker to authenticate as the victim while signing proofs with their own private key, fully bypassing sender-constrained security guarantees.
An authentication bypass and privilege escalation vulnerability exists in Filament (filamentphp/filament) due to missing password verification during multi-factor authentication (MFA) setup and management. An attacker with access to an active session can modify or disable MFA, leading to account hijacking.