CVE-2026-73302
Budibase: OIDC SSO account takeover: incoming identity linked by email without checking email_verified
Budibase is an open-source low-code platform. Prior to 3.39.30, the OIDC flow in packages/backend-core/src/middleware/passport/sso/oidc.ts resolved an email without getEmailVerified or an email_verified requirement, and packages/backend-core/src/middleware/passport/sso/sso.ts then used users.getGlobalUserByEmail as a fallback account-linking key. An attacker who can authenticate through a configured identity provider that asserts a victim email as unverified can have a fresh provider identity merged into the victim Budibase account and inherit the victim roles. This issue is fixed in version 3.39.30.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
9.0
Budibase: OIDC SSO account takeover: incoming identity linked by email without checking email_verified
Budibase is an open-source low-code platform. Prior to 3.39.30, the OIDC flow in packages/backend-core/src/middleware/passport/sso/oidc.ts resolved an email without getEmailVerified or an email_verified requirement, and packages/backend-core/src/middleware/passport/sso/sso.ts then used users.getGlobalUserByEmail as a fallback account-linking key. An attacker who can authenticate through a configured identity provider that asserts a victim email as unverified can have a fresh provider identity merged into the victim Budibase account and inherit the victim roles. This issue is fixed in version 3.39.30.
- Record
CVE-2026-73302- CVSS 4.0
- 9.0 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H - Weakness
- CWE-287
- Updated
- 2026-11-02
EUVDEUVD-2026-58525
9.0
Budibase is an open-source low-code platform. Prior to 3.39.30, the OIDC flow in packages/backend-core/src/middleware/passport/sso/oidc.ts resolved an email without getEmailVerified or an email_verified requirement, and packages/backend-core/src/middleware/passport/sso/sso.ts then used users.getGlobalUserByEmail as a fallback account-linking key. An attacker who can authenticate through a configured identity provider that asserts a victim email as unverified can have a fresh provider identity merged into the victim Budibase account and inherit the victim roles. This issue is fixed in version 3.39.30.
- Record
EUVD-2026-58525- CVSS 4.0
- 9.0 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-hp6v-6jw7-gv2f
9.0
Budibase: OIDC SSO account takeover: incoming identity linked by email without checking email_verified
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) returnsprofile._json.email->jwtClaims.email->preferred_username. Noemail_verifiedcheck.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,44users.getById(generateGlobalUserID(details.userId))keyed on the IdPsub; for a fresh attacker IdP account this 404s and is swallowed (:45-54).:57-59fallback: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_EMAILview, no binding to the IdPsub).syncUser(...)(sso.ts:80,102-138) spreads...user, preserving the victim_id/tenantId/roles; only overwrites provider fields.
UserDB.save(packages/backend-core/src/users/db.ts:235): becausessoUser._idis the victim's, the_idbranch runs (:253),getById(_id)matches the victim (:256), the "Email address cannot be changed" guard (:257-259) does not fire (dbUser.email === email), and theEmailUnavailableErrorguard (:269-275) is skipped (it only runs in the!dbUserbranch). The merge proceeds silently; a session JWT is issued for the victim.
Per OIDC Core §5.7, the email claim MUST NOT be used as an identity key unless email_verified is true. Budibase never reads the flag.
Preconditions (attack requirement — AT:P): the attacker must be able to authenticate through an IdP that the Budibase instance trusts AND get that IdP to assert the victim's email with email_verified = false. This is reachable, not exotic:
- Self-registration with an unverified email — Keycloak and Authentik ship with "Verify Email" OFF by default; if the trusted IdP allows public sign-up, the attacker registers a new account and simply enters
email = <victim>at sign-up. No confirmation email is needed — the IdP stores and asserts it unverified. - Self-service profile editing — many IdPs let a logged-in user change their own email without forced re-verification.
- Attacker-operated / federated IdP or permissive social login — where the attacker controls or influences a trusted provider, or the provider asserts a user-typed (unverified) email.
It is not exploitable through a strict corporate IdP that enforces email verification (there
email_verified = trueand the attacker cannot claim the victim's address) — which is exactly why Budibase must check the flag…
- Record
GHSA-hp6v-6jw7-gv2f- CVSS 4.0
- 9.0 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H - Weakness
- CWE-287
- Updated
- 2026-11-02
NVD
9.0
Budibase is an open-source low-code platform. Prior to 3.39.30, the OIDC flow in packages/backend-core/src/middleware/passport/sso/oidc.ts resolved an email without getEmailVerified or an email_verified requirement, and packages/backend-core/src/middleware/passport/sso/sso.ts then used users.getGlobalUserByEmail as a fallback account-linking key. An attacker who can authenticate through a configured identity provider that asserts a victim email as unverified can have a fresh provider identity merged into the victim Budibase account and inherit the victim roles. This issue is fixed in version 3.39.30.
- Record
CVE-2026-73302- CVSS 4.0
- 9.0 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - Weakness
- CWE-287
- Updated
- 2026-11-02
OSV
9.0
Budibase: OIDC SSO account takeover: incoming identity linked by email without checking email_verified
Budibase is an open-source low-code platform. Prior to 3.39.30, the OIDC flow in packages/backend-core/src/middleware/passport/sso/oidc.ts resolved an email without getEmailVerified or an email_verified requirement, and packages/backend-core/src/middleware/passport/sso/sso.ts then used users.getGlobalUserByEmail as a fallback account-linking key. An attacker who can authenticate through a configured identity provider that asserts a victim email as unverified can have a fresh provider identity merged into the victim Budibase account and inherit the victim roles. This issue is fixed in version 3.39.30.
- Record
CVE-2026-73302- CVSS 4.0
- 9.0 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H - Weakness
- CWE-287
- Updated
- 2026-11-02
OSVGHSA-hp6v-6jw7-gv2f
9.0
Budibase: OIDC SSO account takeover: incoming identity linked by email without checking email_verified
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) returnsprofile._json.email->jwtClaims.email->preferred_username. Noemail_verifiedcheck.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,44users.getById(generateGlobalUserID(details.userId))keyed on the IdPsub; for a fresh attacker IdP account this 404s and is swallowed (:45-54).:57-59fallback: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_EMAILview, no binding to the IdPsub).syncUser(...)(sso.ts:80,102-138) spreads...user, preserving the victim_id/tenantId/roles; only overwrites provider fields.
UserDB.save(packages/backend-core/src/users/db.ts:235): becausessoUser._idis the victim's, the_idbranch runs (:253),getById(_id)matches the victim (:256), the "Email address cannot be changed" guard (:257-259) does not fire (dbUser.email === email), and theEmailUnavailableErrorguard (:269-275) is skipped (it only runs in the!dbUserbranch). The merge proceeds silently; a session JWT is issued for the victim.
Per OIDC Core §5.7, the email claim MUST NOT be used as an identity key unless email_verified is true. Budibase never reads the flag.
Preconditions (attack requirement — AT:P): the attacker must be able to authenticate through an IdP that the Budibase instance trusts AND get that IdP to assert the victim's email with email_verified = false. This is reachable, not exotic:
- Self-registration with an unverified email — Keycloak and Authentik ship with "Verify Email" OFF by default; if the trusted IdP allows public sign-up, the attacker registers a new account and simply enters
email = <victim>at sign-up. No confirmation email is needed — the IdP stores and asserts it unverified. - Self-service profile editing — many IdPs let a logged-in user change their own email without forced re-verification.
- Attacker-operated / federated IdP or permissive social login — where the attacker controls or influences a trusted provider, or the provider asserts a user-typed (unverified) email.
It is not exploitable through a strict corporate IdP that enforces email verification (there
email_verified = trueand the attacker cannot claim the victim's address) — which is exactly why Budibase must check the flag…
- Record
GHSA-hp6v-6jw7-gv2f- CVSS 4.0
- 9.0 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H - Weakness
- CWE-287
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
@budibase/servernpm |
through 3.38.1 | None known |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-73302 is a critical vulnerability (CVSS 9.0) in Budibase, published July 24, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.43%, the 37th percentile. No source names a fixed version.
References
github.com/Budibase/budibase/security/advisories/GHSA-hp6v-6jw7-gv2f
github.com/Budibase/budibase/pull/19173
github.com/Budibase/budibase/commit/9ecd0048d9c3ae0ee9bd0e6204c621794dd1a4d3
github.com/Budibase/budibase/releases/tag/3.39.30
github.com/advisories/GHSA-hp6v-6jw7-gv2f
github.com/CVEProject/cvelistV5/tree/main/cves/2026/73xxx/CVE-2026-73302.json
nvd.nist.gov/vuln/detail/CVE-2026-73302
github.com/Budibase/budibase
Left out here: the rest of 2 source descriptions. The JSON record has them.