VYPR
High severityNVD Advisory· Published Jun 12, 2024· Updated Aug 2, 2024

@strapi/plugin-users-permissions leaks 3rd party authentication tokens and authentication bypass

CVE-2024-34065

Description

Strapi is an open-source content management system. By combining two vulnerabilities (an Open Redirect and session token sent as URL query parameter) in @strapi/plugin-users-permissions before version 4.24.2, is its possible of an unauthenticated attacker to bypass authentication mechanisms and retrieve the 3rd party tokens. The attack requires user interaction (one click). Unauthenticated attackers can leverage two vulnerabilities to obtain an 3rd party token and the bypass authentication of Strapi apps. Users should upgrade @strapi/plugin-users-permissions to version 4.24.2 to receive a patch.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Unauthenticated attackers can chain an open redirect with a session token in query parameters to steal third-party OAuth tokens and bypass authentication in Strapi.

Vulnerability

An unauthenticated attacker can combine an open redirect vulnerability with a session token transmitted as a URL query parameter in Strapi's @strapi/plugin-users-permissions before version 4.24.2. The open redirect occurs because the plugin allows user-controlled data to be incorporated into OAuth callback URLs without sufficient validation, enabling redirection to arbitrary external domains [1]. Simultaneously, the session token is exposed in the query string during the OAuth flow, making it available for capture via the redirect [1][2].

Exploitation

The attack requires user interaction: a victim must click a crafted link that triggers the open redirect while the session token is present in the URL. An unauthenticated attacker can exploit this by sending a malicious link to a logged-in user. If the victim clicks the link, the session token is leaked to the attacker-controlled external domain, allowing the attacker to retrieve third-party OAuth tokens [1][2]. The vulnerability does not require any pre-existing authentication or special network position beyond the ability to deliver the link [2].

Impact

Successful exploitation enables an unauthenticated attacker to obtain third-party tokens (e.g., OAuth tokens from social login providers) and use them to bypass authentication mechanisms in the Strapi application. The attacker can then impersonate the victim and gain unauthorized access to resources protected by Strapi's users-permissions plugin [1][2].

Mitigation

The Strapi project released a fix in version 4.24.2 of @strapi/plugin-users-permissions. The patch adds validation of OAuth callback URLs to prevent open redirects by checking that the origin and pathname match the provider's expected callback, while still allowing different state parameters. Users are advised to upgrade to version 4.24.2 or later to remediate the vulnerability [1][4]. No workarounds are publicly documented, and the vendor recommends immediate upgrade [2].

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
@strapi/plugin-users-permissionsnpm
< 4.24.24.24.2

Affected products

2

Patches

1
9c79921d2214

Merge pull request from GHSA-wrvh-rcmr-9qfc

https://github.com/strapi/strapiAlexandre BODINMay 3, 2024via ghsa
2 files changed · +52 4
  • packages/plugins/users-permissions/server/config.js+30 0 modified
    @@ -18,6 +18,36 @@ module.exports = {
             },
           },
         },
    +    callback: {
    +      validate(callback, provider) {
    +        let uCallback;
    +        let uProviderCallback;
    +
    +        try {
    +          uCallback = new URL(callback);
    +          uProviderCallback = new URL(provider.callback);
    +        } catch {
    +          throw new Error('The callback is not a valid URL')
    +        }
    +
    +
    +        // Make sure the different origin matches
    +        if(uCallback.origin !== uProviderCallback.origin)  {
    +          throw new Error(
    +            `Forbidden callback provided: origins don't match. Please verify your config.`
    +          );
    +        }
    +
    +        // Make sure the different pathname matches
    +        if(uCallback.pathname !== uProviderCallback.pathname)  {
    +          throw new Error(
    +            `Forbidden callback provided: pathname don't match. Please verify your config.`
    +          );
    +        }
    +
    +        // NOTE: We're not checking the search parameters on purpose to allow passing different states
    +      }
    +    },
       }),
       validator() {},
     };
    
  • packages/plugins/users-permissions/server/controllers/auth.js+22 4 modified
    @@ -201,10 +201,28 @@ module.exports = {
         }
     
         // Ability to pass OAuth callback dynamically
    -    grantConfig[provider].callback =
    -      _.get(ctx, 'query.callback') ||
    -      _.get(ctx, 'session.grant.dynamic.callback') ||
    -      grantConfig[provider].callback;
    +    const queryCustomCallback = _.get(ctx, 'query.callback');
    +    const dynamicSessionCallback = _.get(ctx, 'session.grant.dynamic.callback');
    +
    +    const customCallback = queryCustomCallback ?? dynamicSessionCallback;
    +
    +    // The custom callback is validated to make sure it's not redirecting to an unwanted actor.
    +    if (customCallback !== undefined) {
    +      try {
    +        // We're extracting the callback validator from the plugin config since it can be user-customized
    +        const { validate: validateCallback } = strapi
    +          .plugin('users-permissions')
    +          .config('callback');
    +
    +        await validateCallback(customCallback, grantConfig[provider]);
    +
    +        grantConfig[provider].callback = customCallback;
    +      } catch (e) {
    +        throw new ValidationError('Invalid callback URL provided', { callback: customCallback });
    +      }
    +    }
    +
    +    // Build a valid redirect URI for the current provider
         grantConfig[provider].redirect_uri = getService('providers').buildRedirectUri(provider);
     
         return grant(grantConfig)(ctx, next);
    

Vulnerability mechanics

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