Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
📦
📦 npm
Not in CISA KEV
HIGH severity

GHSA-gv74-j8m3-fg5f

HIGHFix: better-auth/better-auth#9220

GHSA-gv74-j8m3-fg5f is a high-severity (CVSS 7.1) Improper Privilege Management vulnerability in @better-auth/sso. O3 Security confirms whether GHSA-gv74-j8m3-fg5f is actually reachable in your code before you act, and blocks exploitation at runtime until you patch.

@better-auth/sso: SSO provider may allow registration for any org member without a checking their role

Also known asCVE-2026-53515
Published
Jul 20, 2026
Updated
Jul 20, 2026
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Aug 10, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

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 GHSA-gv74-j8m3-fg5f.

EPSS Exploitation Probability

via FIRST.org ↗
0.2%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs15th percentile — riskier than 15% of all scored CVEsHighest risk
0.00%0.25%0.49%0.74%0.2%0.2%Aug 26Aug 26

EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.

How urgent is this, really

GHSA-gv74-j8m3-fg5f plotted by exploitation likelihood (EPSS) against impact (CVSS). The shaded corner — EPSS 50%+ and CVSS 7.0+ — is where this CVE doesn't sit, though severity or exploitability alone can still warrant action.

Where this sits among everything scored

Of 366,526 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Real counts from FIRST.org, not a sample — log-scaled since the landscape is heavily right-skewed.

Real-World Exposure

1 pkg affected

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.

17other npm packages depend on this — each one inherits the vulnerability until it's patched upstream
@better-auth/ssonpm
548Kdownloads / week

Description

Am I affected?

You are affected if all of the following are true:

  • You depend on @better-auth/sso at any version in >= 1.2.10, < 1.6.11, or any current next pre-release.
  • You enable both sso() and organization() plugins.
  • providersLimit is 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.defaultRole or organizationProvisioning.getRole returns admin or higher for SSO-provisioned users. The bug then becomes unauthorized admin creation in the org.
  • domainVerification.enabled is false (the default). The malicious provider is immediately usable.

Fix:

  1. Upgrade to @better-auth/[email protected] or later.
  2. 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 throws FORBIDDEN before the membership gate. Trade-off: admins also lose self-serve provider creation; provisioning has to go through server-side auth.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 before hook on /sso/register that asserts the caller's role on body.organizationId is owner or admin. This duplicates the patch shape in user code.
  • Audit existing rows: list ssoProvider rows where organizationId IS NOT NULL, cross-reference each userId with member.role for that organization, and remove provider rows whose creator is not currently owner or admin. 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.defaultRole is admin, or organizationProvisioning.getRole returns admin, 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

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
📦npm@better-auth/sso1.2.10&&< 1.6.111.6.11

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for @better-auth/sso. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.

  2. 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 GHSA-gv74-j8m3-fg5f is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 pinpoints whether GHSA-gv74-j8m3-fg5f is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.

Tailored to GHSA-gv74-j8m3-fg5f. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

### Am I affected? You are affected if all of the following are true: - You depend on `@better-auth/sso` at any version in `>= 1.2.10, < 1.6.11`, or any current `next` pre-release. - You enable both `sso()` and `organization()` plugins. - `providersLimit` is 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 a
O3 Security · Impact-Aware SCA

Is GHSA-gv74-j8m3-fg5f in your dependencies?

O3 detects GHSA-gv74-j8m3-fg5f across npm dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.

GHSA-gv74-j8m3-fg5f: @better-auth/sso… | O3 Security