VYPR
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.

PackageAffected versionsPatched versions
@auth0/nextjs-auth0npm
>= 4.9.0, < 4.13.04.13.0

Affected products

1

Patches

1
35eb321de334

fix: prevent OAuth parameter injection via returnTo (#2381)

https://github.com/auth0/nextjs-auth0Tushar PandeyNov 17, 2025via ghsa
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

News mentions

0

No linked articles in our index yet.