GHSA-fcrw-f7gg-6g9f: Budibase: SSO OAuth2 Token Leakage via User Metadata Endpoints to Power-Role Users
Summary
The /api/users/metadata and /api/users/metadata/:id endpoints in @budibase/server return full global user profiles to any user with POWER role or above. For SSO-authenticated users (OIDC, Google), the response includes oauth2.accessToken and oauth2.refreshToken fields, leaking identity provider credentials to other users who should not have access to them.
Details
When a user authenticates via SSO (OIDC or Google), the OAuth2 tokens are stored in the global CouchDB user document at packages/backend-core/src/auth/auth.ts:170-173:
dbUser.oauth2 = {
...dbUser.oauth2,
...details,
}
await db.put(dbUser)
The user metadata endpoints are protected by PermissionType.USER, PermissionLevel.READ (packages/server/src/api/routes/user.ts:11), which maps to the POWER permission set (packages/backend-core/src/security/permissions.ts:99).
Path 1 — List all users (GET /api/users/metadata):
1. controller.fetchMetadata → sdk.users.fetchMetadata() (packages/server/src/sdk/users/utils.ts:78)
2. → getGlobalUsers() → getRawGlobalUsers() (packages/server/src/utilities/global.ts:101-122) — strips only password and forceResetPassword
3. → processUser() (packages/server/src/utilities/global.ts:15-76) — strips only password and roles
4. The oauth2 field containing accessToken and refreshToken is never removed
Path 2 — Single user (GET /api/users/metadata/:id):
1. controller.findMetadata → getFullUser() (packages/server/src/utilities/users.ts:6)
2. → getGlobalUser() → getRawGlobalUser() (packages/server/src/utilities/global.ts:90-92) — raw CouchDB fetch, no field stripping at all
3. → processUser() — strips only password and roles
4. Same result: oauth2 tokens are returned
There is no output sanitization middleware on these routes that would strip sensitive fields before the response reaches the client.
PoC
Prerequisites: A Budibase instance with at least one SSO-authenticated user (OIDC or Google) and a separate user with POWER role in an app.
Step 1 — As the POWER user, list
Details
Original advisory: https://github.com/advisories/GHSA-fcrw-f7gg-6g9f
More from GitHub Security Advisories
- mediumGHSA-jr6p-8pjj-mfx6: Capsule has an incomplete fix of CVE-2026-22872: TenantResource RawItems and Generators s…2026-07-31
- mediumGHSA-68cj-mvg9-rgm2: Capsule: CapsuleConfiguration NodeMetadata regex fields lack webhook validation, allowing…2026-07-31
- mediumGHSA-ff84-5f28-78qj: re2: Out-of-bounds heap read in `exec`/`test`/`match` via attacker-influenced `lastIndex`…2026-07-31
- mediumGHSA-6hxr-mr5r-9836: re2: Global `String.prototype.match` with an empty-matchable pattern never advances → inf…2026-07-31
- mediumGHSA-x83g-979r-f5fh: Sylius Mollie Plugin has unauthenticated IDOR that leaks order token and customer PII2026-07-31