Mar 10, 2026·8 min read·2 visits
A fallback logic flaw in the FeathersJS OAuth module allows attackers to supply arbitrary identity data in query parameters during the callback phase. This results in complete, unauthenticated account takeover.
FeathersJS versions prior to 5.0.42 contain a critical improper authentication vulnerability in the OAuth callback handler. An unauthenticated attacker can forge user profile data via URL query parameters, bypassing the standard OAuth flow to obtain a valid JSON Web Token (JWT) for any user account.
FeathersJS is a web framework for building real-time applications and REST APIs. The framework provides modular authentication capabilities, including OAuth integration via the @feathersjs/authentication-oauth package. This package manages the multi-step handshake required to authenticate users against third-party identity providers such as Google, GitHub, or Facebook.
CVE-2026-29792 documents a critical flaw in how this package processes incoming authentication callbacks. The vulnerability is classified under CWE-287 (Improper Authentication) and carries a CVSS score of 9.8. The core issue lies in a fallback mechanism that inadvertently trusts user-supplied query parameters when legitimate internal state objects are empty or absent.
By exploiting this logic flaw, an unauthenticated attacker can bypass the identity provider entirely. The attacker supplies a forged profile object within a direct request to the callback endpoint. The FeathersJS backend incorrectly processes this forged payload as a verified authentication response, leading directly to unauthorized access.
Simultaneous to the release fixing this OAuth issue, the maintainers addressed a NoSQL injection vulnerability in the @feathersjs/mongodb adapter. The concurrent patches in version 5.0.42 resolve both the authentication bypass and the database injection risks.
The standard OAuth 2.0 authorization code flow requires an initiation phase where the user is redirected to the identity provider. Upon successful authentication, the provider redirects the user back to the application's callback endpoint (e.g., /oauth/github/callback) with an authorization code. The @feathersjs/authentication-oauth package processes this callback in the packages/authentication-oauth/src/service.ts file.
The vulnerability originates in how the service.ts file constructs the user profile payload. The application attempts to resolve the authenticated user data through a sequential fallback chain. The logic checks grant?.response, followed by result?.session?.response, and result?.state?.response. These three sources represent secure, internally managed states populated during a legitimate OAuth handshake.
Crucially, the fallback chain concludes with params.query. This variable contains the raw, unauthenticated query parameters from the incoming HTTP GET request. If an attacker accesses the callback endpoint directly without initiating an OAuth session, the grant, session, and state objects remain unpopulated or undefined.
The logic seamlessly falls back to reading params.query. Because the application applies no further cryptographic verification or state validation to this specific fallback branch, the untrusted query parameters are ingested as verified identity data. The application then performs an internal user lookup based on this forged identity and issues a valid authentication token.
The flawed code resides in the authentication payload resolution logic within packages/authentication-oauth/src/service.ts. The implementation groups secure, server-side state resolution with untrusted, client-controlled input in a single assignment operation.
In versions prior to 5.0.42, the code explicitly included params.query as the final option in the logical OR chain. This design pattern constitutes a "fail-open" state, where the absence of secure verification defaults to accepting user input.
// Vulnerable Implementation in packages/authentication-oauth/src/service.ts
const payload = grant?.response || result?.session?.response || result?.state?.response || params.queryThe fix introduced in commit d6b0b5cfbaf6f86a63662027c25616c28e54ede1 removes params.query from the fallback sequence. By removing this variable, the application explicitly severs the execution path that allowed arbitrary query parameters to define the authentication payload.
// Patched Implementation in packages/authentication-oauth/src/service.ts
const payload = grant?.response || result?.session?.response || result?.state?.response
if (!payload) {
throw new NotAuthenticated(
'No valid oAuth response. You must initiate the oAuth flow from the authorize endpoint.'
)
}Following the payload extraction, the patch introduces an explicit existence check. If the payload object remains undefined after querying the secure state locations, the application throws a NotAuthenticated exception. This enforces a strict requirement that all incoming callbacks must correlate with an existing, server-tracked authorization flow.
Exploiting CVE-2026-29792 requires network access to the target application and knowledge of a valid user identifier, such as an internal user ID or an email address. The attacker does not require any existing privileges or pre-authentication. The target application must be running an affected version of @feathersjs/authentication-oauth with at least one OAuth provider configured.
The attack begins by bypassing the standard /oauth/:provider authorization endpoint. Instead, the attacker constructs a direct HTTP GET request to the application's callback endpoint. The specific provider path (e.g., google, github, auth0) must match an active configuration on the target server.
The attacker appends the forged profile data directly into the URL query string using bracket notation for object construction. For example, to target an administrative user via their email address, the attacker structures the request as follows:
GET /oauth/google/callback?profile[email]=admin@example.com HTTP/1.1
Host: vulnerable-app.com
Accept: application/jsonUpon receiving this request, the vulnerable FeathersJS backend processes the empty state and falls back to parsing the query string. It interprets the { "email": "admin@example.com" } object as a successful authentication response from the identity provider. The framework subsequently maps this profile to the existing administrative account, generates a signed JSON Web Token (JWT), and returns it to the attacker in the HTTP response.
The impact of CVE-2026-29792 is total system compromise at the application layer. The CVSS v4.0 vector (CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N) reflects the low complexity and lack of prerequisites required to execute the attack. Any remote, unauthenticated entity can obtain a valid session for any user in the database.
Once an attacker possesses a valid JWT for a targeted user, they operate with the full authorization context of that identity. If the compromised account holds administrative privileges, the attacker gains the ability to read all underlying database records, modify sensitive application data, or interact with downstream internal APIs integrated with the FeathersJS backend.
Unlike traditional session hijacking or Cross-Site Scripting (XSS) attacks, this vulnerability requires no user interaction. The attack executes entirely server-side, meaning that multi-factor authentication (MFA) implemented at the third-party identity provider level provides zero protection. The attacker bypasses the provider completely, rendering external security controls ineffective.
FeathersJS version 5.0.42 also mitigates a significant NoSQL injection flaw within the @feathersjs/mongodb package. This database adapter acts as the translation layer between the framework's service methods and the underlying MongoDB driver. The vulnerability occurred due to insufficient type enforcement on the id parameter within core operations such as get, update, patch, and remove.
In unpatched versions, the adapter assumed the id variable was a primitive scalar value (string or number). An attacker interacting with a FeathersJS REST or WebSocket endpoint could format their request payload to supply a JSON object instead of a scalar ID. By passing an object containing MongoDB query operators, such as { "$ne": null }, the attacker forced the adapter to construct an unintended database query.
This behavior alters the target scope of the database operation. Instead of targeting a specific record by its primary key, the injected operator modifies the match criteria. For example, an injected update operation intended for a specific document might instead modify the first document returned by the database engine that satisfies the "$ne": null condition.
Commit 163e664f231a57041034c852b80525fc5c8cf68d resolves this flaw by introducing strict runtime type validation. The adapter now explicitly verifies that the id parameter is strictly a string, a number, or an instance of ObjectId. If an object or other unsupported type is detected, the application immediately throws a BadRequest exception, halting the query execution.
// Patched Implementation in packages/mongodb/src/adapter.ts
if (id !== null) {
if (typeof id !== 'string' && typeof id !== 'number' && !(id instanceof ObjectId)) {
throw new BadRequest(`Invalid id '${JSON.stringify(id)}'`)
}
query.$and = (query.$and || []).concat({
[this.id]: this.getObjectId(id)
})
}The absolute remediation for these vulnerabilities is upgrading all FeathersJS framework components to version 5.0.42 or later. Developers must update @feathersjs/authentication-oauth, @feathersjs/mongodb, and any related core packages in the package.json file. Following the update, teams must rebuild the application and regenerate lockfiles to ensure the patched versions deploy to production environments.
If immediate patching is technically unfeasible due to deployment constraints, security teams can implement an application-level workaround. Developers can inject a custom FeathersJS hook directly onto the OAuth service before the standard authentication middleware executes. This hook must explicitly delete or reject any incoming request containing params.query.profile, thereby neutralizing the attack vector prior to payload resolution.
For detection and incident response, organizations should analyze HTTP access logs for suspicious activity targeting the OAuth endpoints. Defenders should query for any GET requests sent directly to /oauth/*/callback that contain the string profile[ in the query parameters. Additionally, logs should be correlated to verify that a preceding authorization initiation request to /oauth/* exists for every observed callback execution.
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
@feathersjs/authentication-oauth FeathersJS | >= 5.0.0, < 5.0.42 | 5.0.42 |
@feathersjs/mongodb FeathersJS | >= 5.0.0, < 5.0.42 | 5.0.42 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-287 |
| Attack Vector | Network (Remote) |
| Authentication Required | None |
| CVSS v4.0 | 9.3 |
| Exploit Status | PoC Available |
| CISA KEV | No |
Improper Authentication occurs when an application incorrectly proves the identity of a user, allowing attackers to access unauthorized data or functionality.