Low severityNVD Advisory· Published Dec 11, 2025· Updated Dec 11, 2025
Auth0 Next.js SDK has Improper Validation of Query Parameters
CVE-2025-67716
Description
The Auth0 Next.js SDK is a library for implementing user authentication in Next.js applications. Versions 4.9.0 through 4.12.1 contain an input-validation flaw in the returnTo parameter, which could allow attackers to inject unintended OAuth query parameters into the Auth0 authorization request. Successful exploitation may result in tokens being issued with unintended parameters. This issue is fixed in version 4.13.0.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
@auth0/nextjs-auth0npm | >= 4.9.0, < 4.13.0 | 4.13.0 |
Affected products
1- Range: >= 4.9.0, < 4.13.0
Patches
135eb321de334fix: prevent OAuth parameter injection via returnTo (#2381)
3 files changed · +90 −4
.gitignore+2 −1 modified@@ -141,4 +141,5 @@ dist *.tmp *PLAN*.md .yalc/ -yalc.lock \ No newline at end of file +yalc.lock +.npmrc
src/server/helpers/with-page-auth-required.test.ts+87 −2 modified@@ -81,7 +81,7 @@ describe("with-page-auth-required ssr", () => { ); await expect(handler({})).rejects.toThrowError("NEXT_REDIRECT"); expect(redirect).toHaveBeenCalledTimes(1); - expect(redirect).toHaveBeenCalledWith("/auth/login?returnTo=/foo"); + expect(redirect).toHaveBeenCalledWith("/auth/login?returnTo=%2Ffoo"); }); it("should protect a page and redirect to returnTo fn option", async () => { @@ -114,7 +114,7 @@ describe("with-page-auth-required ssr", () => { ).rejects.toThrowError("NEXT_REDIRECT"); expect(redirect).toHaveBeenCalledTimes(1); expect(redirect).toHaveBeenCalledWith( - "/auth/login?returnTo=/foo/bar?foo=bar" + "/auth/login?returnTo=%2Ffoo%2Fbar%3Ffoo%3Dbar" ); }); @@ -165,6 +165,91 @@ describe("with-page-auth-required ssr", () => { expect(redirect).toHaveBeenCalledTimes(1); expect(redirect).toHaveBeenCalledWith("/api/auth/custom-login"); }); + + it("should URL encode returnTo parameter to prevent OAuth param injection", async () => { + const withPageAuthRequired = appRouteHandlerFactory( + new Auth0Client({ + domain: constants.domain, + clientId: constants.clientId, + clientSecret: constants.clientSecret, + appBaseUrl: constants.appBaseUrl, + secret: constants.secret + }), + { + loginUrl: "/auth/login" + } + ); + const handler = withPageAuthRequired( + () => Promise.resolve(React.createElement("div", {}, "foo")), + { + returnTo: + "/callback?scope=openid profile&audience=https://api.example.com" + } + ); + await expect(handler({})).rejects.toThrowError("NEXT_REDIRECT"); + expect(redirect).toHaveBeenCalledTimes(1); + expect(redirect).toHaveBeenCalledWith( + "/auth/login?returnTo=%2Fcallback%3Fscope%3Dopenid%20profile%26audience%3Dhttps%3A%2F%2Fapi.example.com" + ); + }); + + it("should URL encode returnTo with special characters", async () => { + const withPageAuthRequired = appRouteHandlerFactory( + new Auth0Client({ + domain: constants.domain, + clientId: constants.clientId, + clientSecret: constants.clientSecret, + appBaseUrl: constants.appBaseUrl, + secret: constants.secret + }), + { + loginUrl: "/auth/login" + } + ); + const handler = withPageAuthRequired( + () => Promise.resolve(React.createElement("div", {}, "foo")), + { + returnTo: "/path/with spaces & special=chars" + } + ); + await expect(handler({})).rejects.toThrowError("NEXT_REDIRECT"); + expect(redirect).toHaveBeenCalledTimes(1); + expect(redirect).toHaveBeenCalledWith( + "/auth/login?returnTo=%2Fpath%2Fwith%20spaces%20%26%20special%3Dchars" + ); + }); + + it("should URL encode returnTo from function to prevent OAuth param injection", async () => { + const withPageAuthRequired = appRouteHandlerFactory( + new Auth0Client({ + domain: constants.domain, + clientId: constants.clientId, + clientSecret: constants.clientSecret, + appBaseUrl: constants.appBaseUrl, + secret: constants.secret + }), + { + loginUrl: "/auth/login" + } + ); + const handler = withPageAuthRequired( + () => Promise.resolve(React.createElement("div", {}, "foo")), + { + async returnTo({ params }: any) { + return `/callback/${(await params).id}?malicious=scope%3Dopenid`; + } + } + ); + await expect( + handler({ + params: Promise.resolve({ id: "123" }) + }) + ).rejects.toThrowError("NEXT_REDIRECT"); + expect(redirect).toHaveBeenCalledTimes(1); + expect(redirect).toHaveBeenCalledWith( + "/auth/login?returnTo=%2Fcallback%2F123%3Fmalicious%3Dscope%253Dopenid" + ); + }); }); describe("pages router", () => {
src/server/helpers/with-page-auth-required.ts+1 −1 modified@@ -196,7 +196,7 @@ export const appRouteHandlerFactory = : opts.returnTo; const { redirect } = await import("next/navigation.js"); redirect( - `${config.loginUrl}${opts.returnTo ? `?returnTo=${returnTo}` : ""}` + `${config.loginUrl}${returnTo ? `?returnTo=${encodeURIComponent(returnTo)}` : ""}` ); } return handler(params);
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/advisories/GHSA-mr6f-h57v-rpj5ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-67716ghsaADVISORY
- github.com/auth0/nextjs-auth0/commit/35eb321de3345ccf23e8c0d6f66c9f2f2f57d26cghsax_refsource_MISCWEB
- github.com/auth0/nextjs-auth0/security/advisories/GHSA-mr6f-h57v-rpj5ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.