@backstage/plugin-auth-backend: OAuth redirect URI allowlist bypass
Description
Backstage is an open framework for building developer portals. Prior to 0.27.1, the experimental OIDC provider in @backstage/plugin-auth-backend is vulnerable to a redirect URI allowlist bypass. Instances that have enabled experimental Dynamic Client Registration or Client ID Metadata Documents and configured allowedRedirectUriPatterns are affected. A specially crafted redirect URI can pass the allowlist validation while resolving to an attacker-controlled host. If a victim approves the resulting OAuth consent request, their authorization code is sent to the attacker, who can exchange it for a valid access token. This requires victim interaction and that one of the experimental features is explicitly enabled, which is not the default. This vulnerability is fixed in 0.27.1.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
@backstage/plugin-auth-backendnpm | < 0.27.1 | 0.27.1 |
Affected products
1- Range: < 0.27.1
Patches
16042dd0c7f07Merge commit from fork
3 files changed · +46 −14
.changeset/fix-redirect-uri-userinfo-bypass.md+5 −0 added@@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +Improved redirect URI validation in the experimental OIDC provider to match against normalized URLs rather than raw strings.
plugins/auth-backend/src/service/OidcService.test.ts+27 −0 modified@@ -283,6 +283,33 @@ describe('OidcService', () => { ); }); + it('should reject redirect URIs containing userinfo', async () => { + const { service } = await createOidcService({ + databaseId, + config: { + auth: { + experimentalDynamicClientRegistration: { + allowedRedirectUriPatterns: ['http://localhost:*'], + }, + }, + }, + }); + + await expect( + service.registerClient({ + clientName: 'Evil Client', + redirectUris: ['http://localhost:3000@attacker.example/callback'], + }), + ).rejects.toThrow('Invalid redirect_uri'); + + await expect( + service.registerClient({ + clientName: 'Evil Client', + redirectUris: ['http://user:pass@example.com/callback'], + }), + ).rejects.toThrow('Invalid redirect_uri'); + }); + it('should create a client with default values', async () => { const { service } = await createOidcService({ databaseId });
plugins/auth-backend/src/service/OidcService.ts+14 −14 modified@@ -29,6 +29,18 @@ import matcher from 'matcher'; import { OfflineAccessService } from './OfflineAccessService'; import { validateCimdUrl, fetchCimdMetadata } from './CimdClient'; +function validateRedirectUri( + redirectUri: string, + allowedPatterns: string[], +): void { + const parsed = new URL(redirectUri); + const normalized = `${parsed.protocol}//${parsed.host}${parsed.pathname}`; + + if (!allowedPatterns.some(pattern => matcher.isMatch(normalized, pattern))) { + throw new InputError('Invalid redirect_uri'); + } +} + export class OidcService { private readonly auth: AuthService; private readonly tokenIssuer: TokenIssuer; @@ -162,13 +174,7 @@ export class OidcService { ) ?? ['*']; for (const redirectUri of opts.redirectUris ?? []) { - if ( - !allowedRedirectUriPatterns.some(pattern => - matcher.isMatch(redirectUri, pattern), - ) - ) { - throw new InputError('Invalid redirect_uri'); - } + validateRedirectUri(redirectUri, allowedRedirectUriPatterns); } return await this.oidc.createClient({ @@ -305,13 +311,7 @@ export class OidcService { }); if (opts.redirectUri) { - if ( - !cimd.allowedRedirectUriPatterns.some(pattern => - matcher.isMatch(opts.redirectUri!, pattern), - ) - ) { - throw new InputError('Invalid redirect_uri'); - } + validateRedirectUri(opts.redirectUri, cimd.allowedRedirectUriPatterns); if (!cimdClient.redirectUris.includes(opts.redirectUri)) { throw new InputError('Redirect URI not registered');
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-wqvh-63mv-9w92ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-32235ghsaADVISORY
- github.com/backstage/backstage/commit/6042dd0c7f0706e0f473dafa92799ecf19c825ecghsaWEB
- github.com/backstage/backstage/security/advisories/GHSA-wqvh-63mv-9w92ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.