Aug 31, 2026·6 min read·5 visits
A logical error in @hono/oauth-providers allows attackers to bypass OAuth state checks when the state is omitted on both sides, leading to unauthenticated login CSRF and forced account linking.
An authentication bypass vulnerability in @hono/oauth-providers prior to version 0.8.6 allows unauthenticated remote attackers to perform login Cross-Site Request Forgery (CSRF) and forced account linking. Due to a logical 'fail-open' comparison flaw, the middleware validates OAuth callbacks when the state parameter is omitted from both the client cookie and the request query parameters, completely bypassing standard anti-CSRF protections.
The @hono/oauth-providers package is an authentication middleware library designed for the Hono web framework. It provides developers with ready-to-use integrations for popular social identity providers. In a standard deployment, this middleware handles both the initial authorization redirect and the subsequent token exchange callback within the OAuth 2.0 flow.
Prior to version 0.8.6, the library exposed a critical vulnerability in its callback validation mechanism. By failing to ensure that anti-CSRF state tokens were actually present before comparing them, the middleware introduced a bypass on its callback endpoints. This allowed unauthenticated external actors to exploit the authentication state of arbitrary users.
The vulnerability is classified under CWE-352 (Cross-Site Request Forgery) and CWE-1275 (Sensitive Cookie with Improper SameSite Attribute). It affects multiple built-in social login integrations, including Google, GitHub, Facebook, Discord, Twitch, LinkedIn, and MS Entra. The X (formerly Twitter) provider is not vulnerable due to its native implementation of Proof Key for Code Exchange (PKCE).
To secure OAuth callbacks against request forgery, applications generate a cryptographically secure random string, store it in an HTTP cookie, and transmit it to the provider in the authorization request. Upon successful authentication, the identity provider redirects the user back to the application with this exact state parameter. The application must then strictly verify that the incoming parameter matches the value stored inside the cookie.
In affected versions of @hono/oauth-providers, this validation was structured around a simple inequality check. If the browser initiated a request without a preceding login flow, the local state cookie did not exist, evaluating to undefined. Similarly, if the attacker engineered a callback request that omitted the state parameter entirely, the incoming parameter also resolved to undefined.
The middleware executed the comparison c.req.query('state') !== storedState to detect discrepancies. When evaluating undefined !== undefined in JavaScript or TypeScript, the expression resolves to false. Because the inequality condition was false, the middleware bypassed the safety block and assumed verification had succeeded.
This flaw was exacerbated by a weak activation heuristic that only triggered the check if the request URL contained a question mark (?). Additionally, standard global CSRF middleware failed to mitigate this vector. Such protections usually ignore top-level HTTP GET navigations, which are the standard method for processing OAuth redirects.
The vulnerability resided in the individual provider files (such as googleAuth.ts, githubAuth.ts, and discordAuth.ts). The comparison and cookie initialization logic allowed for passive validation bypass and exposed state secrets across origins.
Below is the comparison of the vulnerable implementation versus the patched codebase:
// VULNERABLE CODE PATH (0.8.5 and prior)
if (c.req.url.includes('?')) {
const storedState = getCookie(c, 'state')
if (c.req.query('state') !== storedState) {
throw new HTTPException(401)
}
}// PATCHED CODE PATH (0.8.6+)
if (auth.code) {
const storedState = getCookie(c, 'state')
const state = c.req.query('state')
if (!storedState || !state || state !== storedState) {
throw new HTTPException(401)
}
}By refactoring the activation hook to if (auth.code), the validator fires only when an authorization token is actively presented for exchange. The corrected logic checks both strings for truthiness (!storedState || !state) before performing the string comparison. If either the cookie or the query parameter is absent, the execution fails closed.
The patch also hardened the cookie configuration. The previous deployment left secure: true commented out and omitted the sameSite attribute. The updated code enforces secure: true and sameSite: 'Lax', protecting the state token from cross-site leakage during navigation.
An attacker can exploit this vulnerability through two primary attack vectors: Login CSRF or Forced Account Linking. Both approaches rely on driving a target user to a specially crafted link that performs a top-level GET navigation to the callback endpoint.
In a Login CSRF scenario, the attacker begins by initiating a genuine OAuth session using their own provider credentials. They intercept the redirect request to capture their own valid authorization code, preventing their own browser from executing it. They then construct a malicious URL targeting the victim's browser, completely omitting the state query parameter:
https://target-app.com/auth/discord/callback?code=ATTACKER_CODE
When the victim visits this link, the application processes the request. Because the victim did not start an OAuth session, no state cookie exists in their browser. The validation logic evaluates undefined !== undefined, passes validation, and associates the victim's session with the attacker's social identity.
In a Forced Account Linking scenario, the attacker intercepts a code intended to link an identity. They force the victim to execute the callback, linking the attacker's credentials to the victim's pre-existing profile. The attacker can then authenticate directly to the victim's account.
The impact of this vulnerability is assessed at Medium severity with a CVSS 3.1 score of 5.4 (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N). The vulnerability requires user interaction to succeed, as a victim must click an attacker-controlled link or navigate to a compromised landing page.
If exploited, the confidentiality and integrity of the victim's user data are compromised. Under a Login CSRF attack, the victim is forced into an account session controlled by the attacker. Any sensitive actions, billing information, or private communications entered by the victim during this period are visible to the attacker.
If used to execute forced account linking, the impact escalates to complete account takeover. The attacker links their own social identity to the victim's target account, establishing a persistent back door. This allows the attacker to log into the victim's account at will, bypassing normal authentication credentials.
To fully resolve this vulnerability, security administrators must upgrade @hono/oauth-providers to version 0.8.6 or higher. The update overwrites the vulnerable validation files and implements the fail-closed logic across all supported authentication backends.
In environments where upgrading dependencies immediately is not possible, a pre-validation middleware can serve as an effective mitigation. This custom middleware must inspect incoming requests to the callback URLs and verify that if an authorization code is present, a state parameter must also be supplied in the query string:
app.get('/auth/google/callback', async (c, next) => {
const state = c.req.query('state')
const code = c.req.query('code')
if (code && !state) {
return c.text('Unauthorized: State parameter missing', 401)
}
await next()
})Security teams can detect potential exploitation by scanning web server logs for requests sent to OAuth callback endpoints that contain a code parameter but lack a state parameter. Since legitimate client integrations always submit a state, the absence of this variable indicates a high-probability attack attempt.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
@hono/oauth-providers honojs | < 0.8.6 | 0.8.6 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-352 |
| Attack Vector | Network (AV:N) |
| CVSS v3.1 Score | 5.4 (Medium) |
| Exploit Status | Proof of Concept (PoC) available |
| CISA KEV Status | Not Listed |
| Affected Providers | google, github, facebook, discord, twitch, linkedin, msentra |
The web application does not sufficiently verify whether a request was intentionally sent by the user, enabling attackers to perform actions on behalf of the victim.
An in-depth analysis of CVE-2026-81889, a critical Server-Side Request Forgery (SSRF) vulnerability in the remote URL upload component of elFinder web file manager before version 2.1.70. The flaw leverages DNS rebinding due to insecure socket fallbacks when the PHP cURL extension is missing, resulting in access to internal network resources and local loopback services.
A critical algorithmic complexity Denial of Service (DoS) vulnerability exists in the npm package decode-uri-component versions 0.1.0 through 0.4.1. The package employs an inefficient, high-complexity recursive mechanism when processing invalid percent-encoded sequences, such as isolated continuation bytes. An attacker can exploit this behavior by sending malformed strings, causing the Node.js event loop to block entirely and exhausting CPU resources. This vulnerability is resolved in version 0.5.0 by replacing the recursive parser with a single-pass, linear scanning algorithm.
A critical path traversal vulnerability was discovered in the Kirby CMS media component. Prior to versions 4.9.5 and 5.5.2, Kirby failed to validate path-traversal indicators in requested filenames, allowing attackers to check for the existence of local JSON files, delete them, or bypass directory prefix containment logic under certain web server configurations.
A missing authorization vulnerability (CWE-862) in Kirby CMS (versions 5.0.0 through 5.5.1) allows low-privileged authenticated users with Panel access to write temporary chunk files to disk, leading to potential Denial of Service via storage exhaustion.
An input validation vulnerability in the WebTransport upgrade handler of the Engine.IO server (the core engine driving Socket.IO) allows remote, unauthenticated attackers to trigger a denial of service via application crashes. By sending a crafted session identifier corresponding to a JavaScript prototype property (such as __proto__), an attacker forces the server to reference Object.prototype instead of a valid socket instance, causing a fatal TypeError in the asynchronous execution context.
CVE-2026-15305 describes a critical security vulnerability within the TYPO3 CMS Form Framework (ext:form) extension. Due to a lifecycle timing mismatch, server-side MIME type validation was bypassed when processing files uploaded via FileUpload or ImageUpload form elements. This allowed remote, unauthenticated attackers to upload arbitrary file types (with the exception of blocked PHP extensions) to the web server's public storage directory.