CSIRTS // UNIFIED SECURITY ADVISORY FEEDSYS ● ONLINE · POWERED BY INTELFUSIONS.COM

GHSA-hp6v-6jw7-gv2f: Budibase: OIDC SSO account takeover: incoming identity linked by email without checking email_verified

critical
Summary Budibase's OIDC SSO login links an incoming SSO identity to an existing Budibase account by email address alone, without ever checking the email_verified claim of the OIDC ID token. Budibase first tries to match the IdP sub; when that misses (any fresh attacker IdP account) it silently falls back to matching by the email claim and merges into the existing account by email, preserving that account's _id and roles. Because the email_verified flag is never read, an attacker who can make a configured/trusted IdP emit a token carrying email = <victim> with email_verified = false is logged into Budibase as the victim, inheriting the victim's roles (including global admin/builder). Per OIDC Core §5.7 the email claim MUST NOT be used as an identity key unless email_verified is true; Budibase effectively delegates all account-linking trust to every configured IdP's email-verification policy while checking nothing itself. Full account takeover of any existing Budibase user, including the instance owner. Details The OIDC verify callback extracts the email and never consults email_verified: - packages/backend-core/src/middleware/passport/sso/oidc.ts:59 — email: getEmail(profile, jwtClaims). - getEmail (oidc.ts:113-135) returns profile._json.email ->jwtClaims.email -> preferred_username. **No email_verified check.** - buildJwtClaims (oidc.ts:99-107) assembles claims from _json.email/emails[0].value — no verification flag is read. grep -r email_verified packages/ -> 0 hits. The email is then used as the account-linking key: - sso.authenticate(...) -> packages/backend-core/src/middleware/passport/sso/sso.ts: - :38,44 users.getById(generateGlobalUserID(details.userId)) keyed on the IdP sub; for a fresh attacker IdP account this 404s and is swallowed (:45-54). - :57-59 fallback: dbUser = await users.getGlobalUserByEmail(details.email) -> loads the victim's account (victim _id + roles) purely by email (packages/backend-core/src/users/users.ts:100-124, USER_BY_EMAIL view, no

Details

Source
GitHub Security Advisories (INTL · database · site)
Severity
critical
Published
2026-07-24
Last updated
2026-07-24
Exploitation
Not in CISA KEV at last sync

Original advisory: https://github.com/advisories/GHSA-hp6v-6jw7-gv2f

More from GitHub Security Advisories