CVE-2026-53515 is a high-severity (CVSS 7.1) Improper Privilege Management vulnerability in @better-auth/sso. A fix is available for @better-auth/sso — see the affected versions and patch details below.
Better Auth: Privilege escalation via SSO provider registration: missing admin role check in @better-auth/sso
Exploitation Status
No confirmed exploitation observed yet
- CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.
Exploitation and automatability from CISA’s SSVC triage for CVE-2026-53515.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
How urgent is this, really
CVE-2026-53515 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.
Where this sits among everything scored
Of 388,997 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.
Real-World Exposure
How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.
@better-auth/ssonpmDescription
Am I affected?
You are affected if all of the following are true:
- You depend on
@better-auth/ssoat any version in>= 1.2.10, < 1.6.11, or any currentnextpre-release. - You enable both
sso()andorganization()plugins. providersLimitis at its default (10) or any non-zero value, so SSO provider registration is enabled for authenticated users.- An organization has non-admin members, or your application can add users to organizations as regular members.
You are at the highest risk if any of these also hold:
- Organization membership can be obtained without a direct admin decision, such as through open invitations, self-serve onboarding, public team joins, or SCIM bulk imports.
organizationProvisioning.defaultRoleororganizationProvisioning.getRolereturnsadminor higher for SSO-provisioned users. The bug then becomes unauthorized admin creation in the org.domainVerification.enabledisfalse(the default). The malicious provider is immediately usable.
Fix:
- Upgrade to
@better-auth/[email protected]or later. - If you cannot upgrade, see workarounds below.
Summary
The SSO plugin's POST /sso/register endpoint lets any member of an organization attach a new SSO provider to that organization. It checks that the caller has a membership row, but it does not check whether the caller has an administrative role for the organization.
This creates an authorization mismatch for the same resource. Other org-linked SSO provider management endpoints treat those providers as admin-managed: list, get, update, and delete require the caller to be an organization owner or admin. The create path is less restrictive, so a regular member can attach an attacker-controlled OIDC or SAML identity provider to an organization they do not administer. After registration, downstream organization provisioning can add IdP-asserted users from /sso/callback/{providerId} into the target organization, defaulting to role member.
Details
This issue does not rely on a separate documentation statement that only admins may create SSO connections. The issue is that Better Auth already enforces an admin boundary for org-linked SSO provider management, but registerSSOProvider does not enforce the same boundary when the provider is first created.
The list, get, update, and delete endpoints in providers.ts gate org-linked SSO providers via isOrgAdmin, which accepts owner or admin. The create path in sso.ts performs only a membership lookup and never inspects member.role. As a result, the endpoint allows a low-privilege organization member to create a provider record that they would not be allowed to view, update, or delete through the companion provider-management endpoints.
The fix introduces a shared hasOrgAdminRole(member) helper (refactored out of isOrgAdmin) and adds the admin check to the registration handler so that registration matches the protections on the read and mutation paths.
Patches
Fixed in @better-auth/[email protected]. When organizationId is supplied and the organization plugin is enabled, the registerSSOProvider handler now requires the caller to hold the owner or admin role on the target organization. This makes provider creation match the existing protection on the get, update, and delete endpoints.
Workarounds
If you cannot upgrade immediately:
- Disable user-driven SSO registration entirely: set
sso({ providersLimit: 0 }). Registration throwsFORBIDDENbefore the membership gate. Trade-off: admins also lose self-serve provider creation; provisioning has to go through server-sideauth.api.registerSSOProvider({ headers: serverAdminHeaders, body })calls. - Disable SSO-driven org provisioning: set
sso({ organizationProvisioning: { disabled: true } }). The malicious provider can still be registered, but the SSO callback no longer adds users to the org automatically. Trade-off: legitimate SSO-driven onboarding stops. - Custom
beforehook on/sso/registerthat asserts the caller's role onbody.organizationIdisowneroradmin. This duplicates the patch shape in user code. - Audit existing rows: list
ssoProviderrows whereorganizationId IS NOT NULL, cross-reference eachuserIdwithmember.rolefor that organization, and remove provider rows whose creator is not currentlyowneroradmin. Removing the provider does not auto-remove members it created, so cleanup is two-step.
Impact
- Unauthorized provider configuration within an organization tenant: a regular member writes an SSO provider record on an organization they do not administer.
- Unauthorized organization membership creation: subsequent SSO callbacks can add IdP-asserted users to the target organization at the configured default role.
- Admin creation when configured: if
organizationProvisioning.defaultRoleisadmin, ororganizationProvisioning.getRolereturnsadmin, the issue can create admin-grade users in the target organization without owner consent.
Credit
Reported by @Nadav0077. The same finding was previously raised in public issue #9133 (2026-04-12).
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 📦npm | @better-auth/sso | ≥ 1.2.10&&< 1.6.11 | 1.6.11npm install @better-auth/sso@1.6.11 |
Affected Products
better authbetter-authbetter-auth\/ssobetter-authDetection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for @better-auth/sso, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update @better-auth/sso to 1.6.11 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-53515 is resolved across your whole dependency graph.
Workarounds
Close the privilege gap rather than the entry point: audit which accounts, roles and service identities can reach the affected operation, drop the component to the least privilege it actually needs, and review file and directory permissions created by earlier installs — a default left in place is what makes this reachable.
Frequently Asked Questions
Is CVE-2026-53515 in your dependencies?
Find it across npm, including transitive dependencies.