Back to Blog
critical SEVERITY8 min read

How Unicode Homoglyph Email Bypass happens in Next.js (Auth.js) and how to fix it

CVE-2026-73420 is a critical authentication bypass vulnerability in Auth.js (next-auth) where the email normalizer validates an address before applying Unicode normalization, allowing an attacker to craft an email containing a Unicode homoglyph that looks like "@" to slip past validation and impersonate another user. The fix upgrades next-auth from 4.24.13 to 4.24.15 (and 5.0.0-beta.32 for the beta line), ensuring normalization happens before validation so lookalike characters are resolved to th

O
By Orbis AppSec
•Technically reviewed by Anupam Mediratta•Published August 26, 2026•Reviewed August 26, 2026

Answer Summary

CVE-2026-73420 is a critical authentication bypass in Auth.js / next-auth (CWE-178: Improper Handling of Case Sensitivity / Unicode normalization order). The email normalizer validated the address before applying Unicode normalization, so a homoglyph character visually identical to "@" could pass the format check while resolving to a different canonical address after normalization, enabling account takeover. The fix is to upgrade next-auth to 4.24.15 (v4) or 5.0.0-beta.32 (v5 beta), which reorders the pipeline so normalization always precedes validation.

Vulnerability at a Glance

cweCWE-178 (Improper Handling of Case Sensitivity) / CWE-20 (Improper Input Validation)
fixUpgrade next-auth to 4.24.15 / 5.0.0-beta.32, which normalizes the email string before validation
riskAttacker registers or signs in with a homoglyph email that bypasses format validation, potentially impersonating a legitimate user and gaining unauthorized account access
languageJavaScript / TypeScript (Node.js)
root causeEmail format validation runs before Unicode normalization, so homoglyph "@" characters pass the validator but resolve to a different canonical address
vulnerabilityUnicode Homoglyph Email Bypass

Introduction

The package-lock.json file in a Next.js application is easy to overlook — it is auto-generated, rarely read by humans, and usually committed without ceremony. But locked inside it was a critical authentication vulnerability: CVE-2026-73420, a flaw in how Auth.js (the library powering next-auth) normalizes email addresses before sign-in.

The bug is subtle and dangerous. Auth.js's email normalizer was validating the address format before applying Unicode normalization. That ordering mistake means an attacker can submit an email like user@example.com — where @ (U+FF20, FULLWIDTH COMMERCIAL AT) is a Unicode lookalike for the standard @ (U+0040) — and the validator sees a string with no recognizable @ character, potentially treating it as valid under certain code paths while downstream processing resolves it to user@example.com, the address of a real user.

The fix: upgrade next-auth from 4.24.13 → 4.24.15 (and 5.0.0-beta.32 for the v5 beta line), which reorders the pipeline so normalization always precedes validation.


The Vulnerability Explained

What is a Homoglyph Attack?

Unicode contains thousands of characters that are visually indistinguishable — or nearly so — from common ASCII characters. The @ sign (U+0040) that separates the local part from the domain in an email address has multiple lookalikes in Unicode, including:

Character Unicode Code Point Name
@ U+0040 COMMERCIAL AT (standard)
@ U+FF20 FULLWIDTH COMMERCIAL AT
﹫ U+FE6B SMALL COMMERCIAL AT

A properly hardened email normalizer should call something equivalent to:

// Safe order: normalize FIRST, then validate
const normalized = rawEmail.normalize('NFKC').toLowerCase().trim();
if (!isValidEmail(normalized)) throw new Error('Invalid email');

But the vulnerable version of Auth.js did the opposite — it validated the raw input first, then normalized. Conceptually:

// VULNERABLE order (pre-fix behavior in next-auth 4.24.13)
if (!isValidEmail(rawEmail)) throw new Error('Invalid email');
const normalized = rawEmail.normalize('NFKC').toLowerCase().trim();
// Too late — a homoglyph @ already passed validation

The Concrete Attack Scenario

Consider an application that uses next-auth with an email sign-in provider (magic links or OTP). The target victim has the account alice@example.com.

  1. Attacker crafts the payload: alice@example.com — using U+FF20 FULLWIDTH COMMERCIAL AT instead of the standard @.
  2. Validation step (pre-fix): The validator inspects the raw string. Depending on the regex used, the string may pass (no standard @ found, so the local-part is treated as the entire string, or the regex matches the fullwidth variant as a non-@ character and passes a lenient check) or behave unexpectedly.
  3. Normalization step (post-validation, pre-fix): NFKC normalization converts @ → @, producing alice@example.com.
  4. Session / token issued: Auth.js now has a normalized email alice@example.com — the real victim's address — and may issue a session or send a magic link to that address, effectively granting the attacker access to the victim's account.

The exact exploitability depends on the sign-in flow, but the root cause — validate-then-normalize instead of normalize-then-validate — creates a window where the identity of the email address is ambiguous between the validation and normalization steps.

Why This Is Critical

Email addresses are primary identity keys in most web applications. A bypass here is not a theoretical edge case — it is a direct path to account takeover. An attacker who can register or sign in as alice@example.com by submitting alice@example.com can:

  • Receive magic-link emails intended for the victim (if the mailer normalizes independently)
  • Inherit an existing account's data, permissions, and sessions
  • Bypass email-based MFA flows

The Fix

The remediation is a targeted dependency upgrade in package.json and package-lock.json. Here is the exact change:

package.json / package-lock.json — Version Pin

Before:

"next-auth": "^4.22.3"

After:

"next-auth": "^4.24.15"

And in the resolved lock entry:

-      "version": "4.24.13",
-      "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.13.tgz",
-      "integrity": "sha512-sgObCfcfL7BzIK76SS5TnQtc3yo2Oifp/...",
+      "version": "4.24.15",
+      "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.15.tgz",
+      "integrity": "sha512-NnjYtjrSOAx/TIVFGTX4IfI/9yHnNpi4B7FuLUwuV20v2Zxgr2OGP/...",

Sub-dependency: uuid Bumped to v11

The fix also updates the bundled uuid sub-dependency from 8.3.2 → 11.1.1:

-        "uuid": "^8.3.2"
+        "uuid": "^11.1.1"
-      "version": "8.3.2",
-      "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+      "version": "11.1.1",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz",

The uuid bump is a hardening improvement included in the patched release — v11 drops the legacy v1/v3 generators that had weaker entropy properties and aligns with the updated RFC 9562 UUID specification.

Why These Two Files?

package.json sets the minimum acceptable version (^4.24.15), preventing future npm install runs from ever resolving to the vulnerable 4.24.13. package-lock.json pins the exact resolved artifact and its SHA-512 integrity hash, ensuring that the specific .tgz downloaded from the registry is the patched one. Both changes together close the vulnerability at install time and at runtime.


Key Takeaways

  • Validate after normalizing, never before: The root cause of CVE-2026-73420 is a two-line ordering mistake — normalization came after validation in Auth.js's email pipeline. This single ordering error opened a critical authentication bypass.
  • Homoglyph attacks are practical, not theoretical: Unicode contains multiple @-lookalike characters (U+FF20, U+FE6B, etc.) that are trivially copy-pasteable. Any application accepting email addresses from untrusted input is potentially exposed if it skips pre-validation normalization.
  • package-lock.json integrity hashes matter: The fix updates both the version string and the SHA-512 integrity hash in package-lock.json, ensuring the exact patched artifact is fetched — not just a version that satisfies the semver range.
  • Sub-dependency hygiene counts: The uuid bump from 8.3.2 → 11.1.1 inside next-auth is a secondary hardening improvement. Transitive dependency updates in security patches are intentional and should not be reverted.
  • SCA scanning in CI catches this class of issue automatically: Trivy identified this CVE from the package-lock.json entry alone, before any manual code review. Integrating SCA into your pipeline means you get alerted — or auto-fixed — before vulnerable code ships.

How Orbis AppSec Detected This

  • Source: User-supplied email address submitted to the Auth.js sign-in endpoint (HTTP POST body parameter, typically email or identifier)
  • Sink: Auth.js's internal email normalizer function, which called the format validator on the raw input string before invoking Unicode normalization — allowing a homoglyph @ character to pass the format check and resolve to a different canonical address downstream
  • Missing control: Unicode normalization (NFKC) was absent from the pre-validation step; the normalizer only ran after the validator had already accepted the raw, potentially homoglyph-containing string
  • CWE: CWE-178 — Improper Handling of Case Sensitivity (Unicode normalization order); CWE-20 — Improper Input Validation
  • Fix: Upgraded next-auth from 4.24.13 to 4.24.15 in package-lock.json, which reorders the email pipeline so NFKC normalization precedes format validation

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.


Conclusion

CVE-2026-73420 is a reminder that authentication security is not just about algorithms and key lengths — it is also about the order of operations applied to user-supplied identifiers. A two-step pipeline (validate → normalize) that gets its steps reversed becomes a critical authentication bypass. The fix is a one-line version bump, but understanding why that bump matters is what separates a reactive patch from a durable security posture.

If your application uses next-auth, upgrade to 4.24.15 (v4) or 5.0.0-beta.32 (v5 beta) immediately. If you build email normalization logic yourself, always apply normalize('NFKC') before any format validation. And if you want your dependency tree scanned automatically for issues like this, Orbis AppSec has you covered.


Prevention and further reading

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #16

Related Articles

critical

Music Studio App Express Server: CWE-287 Authentication Bypass via

A critical authentication bypass vulnerability in a music studio application's Express server allowed remote attackers to access API endpoints despite the intended localhost-only restriction. The localRequest middleware validated the Host header but failed to verify the actual remote socket address, enabling trivial bypasses in containerized and multi-user environments.

high

CVE-2026-104850: MCP TypeScript SDK OAuth Credential Leak

The MCP TypeScript SDK (`@modelcontextprotocol/sdk`) contained a flaw in its OAuth client flow where the MCP server being connected to could influence which authorization server the client talked to, meaning client credentials and token-exchange traffic could be directed to an endpoint the attacker controls. This project was pinned to the affected `1.30.0`; the dependency has been moved to `^1.31.0`, which carries the upstream fix for CVE-2026-104850. Any MCP client that performs OAuth against t

high

SQLite Auth Database Plaintext Storage in InitAuthDB()

The `InitAuthDB()` function opened SQLite databases without restricting filesystem permissions, leaving bcrypt password hashes, session tokens, and user settings exposed to any local account with read access. The fix explicitly sets `os.Chmod(filepath, 0600)` immediately after database creation, ensuring only the owner can access authentication secrets.

high

undici 8.10.0 Cache Poisoning: CVE-2026-85152 Auth Bypass

undici, the HTTP client used by Node.js's `fetch()` implementation, shipped a caching layer that did not properly isolate cached responses by origin, letting a response poisoned on one origin be served to requests for another. This created a path to cross-origin authentication bypass, tracked as CVE-2026-85152 and fixed in undici 8.10.2.

critical

Hybridauth Telegram OAuth Timing Attack in `authenticateCheckError()`

The Telegram OAuth provider in Hybridauth relied on `strcmp()` to validate HMAC-SHA256 signatures, exposing a timing side-channel that could allow attackers to forge authentication tokens character by character. The fix replaces this with PHP's timing-safe `hash_equals()` function, eliminating the information leak.

critical

Node.js Auth Query SQL Injection via Group Code Interpolation

A sign-in authorization check built its SQL query by mapping an `authorizedGroups` array into quoted string literals and joining them directly into a template literal, creating a classic SQL injection point in a critical authentication path. The fix replaces every interpolated value — including the previously "typed" parameter — with `?` placeholders bound through a value-builder helper, closing off the injection vector entirely.