Skip to content

fix(deps): update dependency better-auth to v1.6.9#97

Open
renovate[bot] wants to merge 1 commit intomainfrom
renovate/better-auth-1.x
Open

fix(deps): update dependency better-auth to v1.6.9#97
renovate[bot] wants to merge 1 commit intomainfrom
renovate/better-auth-1.x

Conversation

@renovate
Copy link
Copy Markdown
Contributor

@renovate renovate Bot commented Apr 21, 2026

This PR contains the following updates:

Package Change Age Confidence
better-auth (source) 1.6.51.6.9 age confidence

Release Notes

better-auth/better-auth (better-auth)

v1.6.9

Compare Source

Patch Changes

v1.6.8

Compare Source

Patch Changes
  • #​9253 856ab24 Thanks @​baptisteArno! - fix(organization): allow passing id through beforeCreateTeam and beforeCreateInvitation

    Mirrors #​4765 for teams and invitations: adapter.createTeam and adapter.createInvitation now pass forceAllowId: true, so ids returned from the respective hooks survive the DB insert.

  • #​9331 9aa8e63 Thanks @​gustavovalverde! - fix(oauth): support mapProfileToUser fallback for providers that may omit email

    Social sign-in with OAuth providers that may return no email address (Discord phone-only accounts, Apple subsequent sign-ins, GitHub private emails, Facebook, LinkedIn, and Microsoft Entra ID managed users) can now be unblocked by synthesizing an email inside mapProfileToUser. Rejection logger messages now point at this workaround and at the new "Handling Providers Without Email" docs section.

    Provider profile types now reflect where email can be null or absent:

    • DiscordProfile.email is string | null and optional (absent when the email scope is not granted)
    • AppleProfile.email is optional
    • GithubProfile.email is string | null
    • FacebookProfile.email is optional
    • FacebookProfile.email_verified is optional (Meta's Graph API does not include this field)
    • LinkedInProfile.email is optional
    • LinkedInProfile.email_verified is optional
    • MicrosoftEntraIDProfile.email is optional

    TypeScript consumers who previously dereferenced profile.email directly inside mapProfileToUser will see a compile error that matches the runtime reality; use a nullish-coalescing fallback (profile.email ?? ...) or null-check the field.

    Sign-in still rejects with error=email_not_found (social callback) or error=email_is_missing (Generic OAuth plugin) when neither the provider nor mapProfileToUser produces an email. First-class support for users without an email, keyed on (providerId, accountId) per OpenID Connect Core §5.7, is tracked in #​9124.

  • Updated dependencies [9aa8e63]:

v1.6.7

Compare Source

Patch Changes
  • #​9211 307196a Thanks @​stewartjarod! - Preserve Set-Cookie headers accumulated on ctx.responseHeaders when an endpoint throws APIError. Cookie side-effects from deleteSessionCookie (and any ctx.setCookie / ctx.setHeader calls before the throw) are no longer silently discarded on the error path.

  • #​9292 4f373ee Thanks @​gustavovalverde! - Accept an array of Client IDs on providers that verify ID tokens by audience (Google, Apple, Microsoft Entra, Facebook, Cognito). The first entry is used for the authorization code flow; all entries are accepted when verifying an ID token's aud claim, so a single backend can serve Web, iOS, and Android clients with their platform-specific Client IDs.

    socialProviders: {
      google: {
        clientId: [
          process.env.GOOGLE_WEB_CLIENT_ID!,
          process.env.GOOGLE_IOS_CLIENT_ID!,
          process.env.GOOGLE_ANDROID_CLIENT_ID!,
        ],
        clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
      },
    }

    Passing a single string keeps working; no migration needed.

    Also exports getPrimaryClientId from @better-auth/core/oauth2 for provider authors: it returns the primary Client ID (the raw string, or the entry at array index 0), paired with clientSecret for the authorization code flow. Providers now reject empty arrays, empty strings, and missing config at sign-in time instead of silently producing a malformed authorization URL. Google, Apple, and Facebook require both clientId and clientSecret because each of those providers mandates a client secret for their server-side code exchange. Microsoft Entra and Cognito only require clientId, since both support public-client flows with PKCE alone (no secret).

  • #​9293 e1b1cfc Thanks @​gustavovalverde! - Guard against c.body being undefined in parseState. Callback requests that arrive as GET leave c.body unset in some runtimes, which caused c.body.state to throw a TypeError before the existing error redirect could run. The state lookup now short-circuits on the query parameter and falls back to c.body?.state safely, so a callback without a state parameter redirects to the error page instead of crashing.

  • #​4894 d053a45 Thanks @​Kinfe123! - Fire callbackOnVerification when a phone number is verified with updatePhoneNumber: true. The callback previously only ran on initial verification, so consumers relying on it (e.g. to sync verified numbers to an external system) would miss the event when an authenticated user changed their number.

  • Updated dependencies [307196a, 4a180f0, 4f373ee]:

v1.6.6

Compare Source

Patch Changes
  • #​9214 4debfb6 Thanks @​ping-maxwell! - fix(custom-session): use coerced boolean for disableRefresh query param validation

  • #​9235 9ea7eb1 Thanks @​bytaesu! - Preserve the Partitioned attribute when the customSession plugin and framework integrations forward Set-Cookie headers.

  • #​9266 ab4c10f Thanks @​ping-maxwell! - fix(organization): infer team additional fields correctly

  • #​9219 a61083e Thanks @​bytaesu! - Allow removing a phone number with updateUser({ phoneNumber: null }). The verified flag is reset atomically. Changing to a different number still requires OTP verification through verify({ updatePhoneNumber: true }).

  • #​9226 e64ff72 Thanks @​gustavovalverde! - Consolidate host/IP classification behind @better-auth/core/utils/host and close several loopback/SSRF bypasses that the previous per-package regex checks missed.

    Electron user-image proxy: SSRF bypasses closed (@better-auth/electron). fetchUserImage previously gated outbound requests with a bespoke IPv4/IPv6 regex that missed multiple vectors. All of the following were reachable in production and are now blocked:

    • http://tenant.localhost/ and other *.localhost names (RFC 6761 reserves the entire TLD for loopback).
    • http://[::ffff:169.254.169.254]/ (IPv4-mapped IPv6 to AWS IMDS, the classic SSRF bypass).
    • http://metadata.google.internal/, http://metadata.goog/ (GCP instance metadata).
    • http://instance-data/, http://instance-data.ec2.internal/ (AWS IMDS alternate FQDNs).
    • http://100.100.100.200/ (Alibaba Cloud IMDS; lives in RFC 6598 shared address space 100.64/10, which the old regex did not cover).
    • http://0.0.0.0:PORT/ (the Linux/macOS kernel routes the unspecified address to loopback: Oligo's "0.0.0.0 Day").
    • http://[fc00::...]/, http://[fd00::...]/ (IPv6 ULA per RFC 4193) and IPv6 link-local fe80::/10, neither of which the regex recognized.

    Documentation ranges (RFC 5737 / RFC 3849), benchmarking (198.18/15), multicast, and broadcast are also now rejected.

    better-auth: 0.0.0.0 is no longer treated as loopback. The previous isLoopbackHost implementation in packages/better-auth/src/utils/url.ts classified 0.0.0.0 alongside 127.0.0.1 / ::1 / localhost. 0.0.0.0 is the unspecified address, not loopback; treating it as such lets browser-origin requests reach localhost-bound dev services (Oligo's "0.0.0.0 Day"). The helper now accepts the full 127.0.0.0/8 range and any *.localhost name, and rejects 0.0.0.0.

    better-auth: trusted-origin substring hardening. getTrustedOrigins previously used host.includes("localhost") || host.includes("127.0.0.1") when deciding whether to add an http:// variant for a dynamic baseURL.allowedHosts entry. Misconfigurations like evil-localhost.com or 127.0.0.1.nip.io would incorrectly gain an HTTP origin in the trust list. The check now uses the shared classifier, so only real loopback hosts get the HTTP variant.

    @better-auth/oauth-provider: RFC 8252 compliance.

    • §7.3 redirect URI matching now accepts the full 127.0.0.0/8 range (not just 127.0.0.1) plus [::1], with port-flexible comparison. Port-flexible matching is limited to IP literals; DNS names such as localhost continue to use exact-string matching per §8.3 ("NOT RECOMMENDED" for loopback).
    • validateIssuerUrl uses the shared loopback check rather than a two-hostname literal comparison.

    New module: @better-auth/core/utils/host. Exposes classifyHost, isLoopbackIP, isLoopbackHost, and isPublicRoutableHost. One RFC 6890 / RFC 6761 / RFC 8252 implementation that handles IPv4, IPv6 (including bracketed literals, zone IDs, IPv4-mapped addresses, and 6to4 / NAT64 / Teredo tunnel forms with embedded-IPv4 recursion), and FQDNs, with a curated cloud-metadata FQDN set. All bespoke loopback/private/link-local checks across the monorepo now route through it.

  • Updated dependencies [b5742f9, a844c7d, e64ff72]:


Configuration

📅 Schedule: (in timezone Africa/Johannesburg)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Enabled.

Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate renovate Bot added the renovate label Apr 21, 2026
@socket-security
Copy link
Copy Markdown

socket-security Bot commented Apr 21, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedbetter-auth@​1.6.5 ⏵ 1.6.9971008596 +1100

View full report

@socket-security
Copy link
Copy Markdown

socket-security Bot commented Apr 21, 2026

All alerts resolved. Learn more about Socket for GitHub.

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

View full report

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 21, 2026

📚 Docs preview deployed

https://scratchyjs-docs-pr-97.asjas.workers.dev

Updates automatically on every push to this PR.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 21, 2026

⚡ Benchmark Results

benchmarks/renderer/ring-buffer.bench.ts
Suite — Benchmark ops/sec mean (µs) p99 (µs) ±rme vs main
SharedRingBuffer – small payload (64 B) — write 64 bytes 652.1 K 0.0015 0.0058 ±1.01% +20.1% 🚀
SharedRingBuffer – small payload (64 B) — write + read 64 bytes 571.0 K 0.0018 0.0067 ±1.04% +8.5%
SharedRingBuffer – medium payload (1 KB) — write 1 KB 325.9 K 0.0031 0.0119 ±0.48% -6.1%
SharedRingBuffer – medium payload (1 KB) — write + read 1 KB 196.8 K 0.0051 0.0167 ±1.11% -24.3% ⚠️
SharedRingBuffer – large payload (16 KB) — write 16 KB 66.1 K 0.0151 0.0402 ±1.02% +13.6% 🚀
SharedRingBuffer – large payload (16 KB) — write + read 16 KB 74.7 K 0.0134 0.0444 ±26.45% -3.1%
SharedRingBuffer – sequential throughput (100 × 64 B) — 100 write + read cycles 41.7 K 0.0240 0.0381 ±0.39% +2.6%
SharedRingBuffer – introspection — availableToRead 14.89 M 0.0001 0.0001 ±0.11% ~0%
SharedRingBuffer – introspection — isEmpty 15.01 M 0.0001 0.0001 ±0.11% +2.7%
SharedRingBuffer – introspection — isFull 14.79 M 0.0001 0.0001 ±0.10% +1.4%
benchmarks/renderer/shared-buffer.bench.ts
Suite — Benchmark ops/sec mean (µs) p99 (µs) ±rme vs main
SharedBuffer – allocation — createSharedBuffer(4 KB) 625.5 K 0.0016 0.0065 ±0.82% -12.3% ⚠️
SharedBuffer – allocation — createSharedBuffer(64 KB) 56.7 K 0.0176 0.0386 ±1.09% ~0%
SharedBuffer – small payload round-trip — write small JSON 343.2 K 0.0029 0.0109 ±0.38% -4.5%
SharedBuffer – small payload round-trip — write + read small JSON 247.4 K 0.0040 0.0135 ±0.44% -9.6%
SharedBuffer – medium payload round-trip — write medium JSON (~2 KB) 92.7 K 0.0108 0.0260 ±6.14% +4.1%
SharedBuffer – medium payload round-trip — write + read medium JSON (~2 KB) 59.2 K 0.0169 0.0294 ±0.35% +1.5%
SharedBuffer – large payload round-trip — write large JSON (~10 KB) 14.7 K 0.0678 0.1203 ±0.73% -4.4%
SharedBuffer – large payload round-trip — write + read large JSON (~10 KB) 7.5 K 0.1328 0.1843 ±0.37% -3.7%
benchmarks/utils/ip-address.bench.ts
Suite — Benchmark ops/sec mean (µs) p99 (µs) ±rme vs main
getClientIPAddress – no IP headers — no IP-related headers → null 2.64 M 0.0004 0.0008 ±1.14% ~0%
getClientIPAddress – single header — cf-connecting-ip (Cloudflare) 1.68 M 0.0006 0.0011 ±0.95% ~0%
getClientIPAddress – single header — x-forwarded-for (simple) 1.95 M 0.0005 0.0008 ±0.37% +1.1%
getClientIPAddress – single header — x-real-ip 1.51 M 0.0007 0.0012 ±1.21% ~0%
getClientIPAddress – single header — true-client-ip (Akamai / Cloudflare Enterprise) 1.57 M 0.0006 0.0009 ±1.07% +1.5%
getClientIPAddress – x-forwarded-for multi-hop — 2-hop chain 1.84 M 0.0005 0.0007 ±0.12% +5.6%
getClientIPAddress – x-forwarded-for multi-hop — 4-hop chain 1.69 M 0.0006 0.0009 ±0.19% +1.3%
getClientIPAddress – Forwarded header (RFC 7239) — simple for= directive 943.1 K 0.0011 0.0027 ±1.98% -7.0%
getClientIPAddress – Forwarded header (RFC 7239) — for= with port 730.1 K 0.0014 0.0027 ±0.36% ~0%
getClientIPAddress – Forwarded header (RFC 7239) — IPv6 literal 745.9 K 0.0013 0.0020 ±1.26% -2.0%
getClientIPAddress – Forwarded header (RFC 7239) — multi-hop Forwarded 838.6 K 0.0012 0.0017 ±0.33% ~0%
getClientIPAddress – IPv6 addresses — x-forwarded-for IPv6 1.14 M 0.0009 0.0012 ±0.32% -1.1%
benchmarks/utils/promise.bench.ts
Suite — Benchmark ops/sec mean (µs) p99 (µs) ±rme vs main
promiseHash – concurrent resolution — 2 already-resolved promises 868.7 K 0.0012 0.0028 ±1.24% +1.5%
promiseHash – concurrent resolution — 5 already-resolved promises 526.4 K 0.0019 0.0025 ±0.35% ~0%
promiseHash – concurrent resolution — 10 already-resolved promises 294.7 K 0.0034 0.0080 ±2.59% +3.4%
promiseHash – concurrent resolution — 5 promises with object values 479.3 K 0.0021 0.0028 ±0.35% -1.4%
timeout – wrapping fast promises — timeout wrapping an already-resolved promise (1 s budget) 949.6 K 0.0011 0.0020 ±0.35% -1.9%
timeout – wrapping fast promises — timeout wrapping an already-resolved object (5 s budget) 803.0 K 0.0012 0.0029 ±5.21% -14.1% ⚠️
benchmarks/utils/safe-redirect.bench.ts
Suite — Benchmark ops/sec mean (µs) p99 (µs) ±rme vs main
safeRedirect – valid paths — root path / 7.60 M 0.0001 0.0002 ±0.12% +12.4% 🚀
safeRedirect – valid paths — simple path /dashboard 3.47 M 0.0003 0.0003 ±0.11% -3.9%
safeRedirect – valid paths — nested path /settings/profile 3.19 M 0.0003 0.0003 ±0.10% ~0%
safeRedirect – valid paths — path with query string /search?q=hello 3.53 M 0.0003 0.0003 ±0.11% +1.2%
safeRedirect – valid paths — path with hash /docs#section 3.52 M 0.0003 0.0003 ±0.11% -2.0%
safeRedirect – rejected inputs — absolute URL https://evil.com 4.61 M 0.0002 0.0002 ±0.13% ~0%
safeRedirect – rejected inputs — protocol-relative URL //evil.com 4.84 M 0.0002 0.0002 ±0.11% +7.4%
safeRedirect – rejected inputs — backslash-relative /\evil.com 4.58 M 0.0002 0.0002 ±0.11% -1.2%
safeRedirect – rejected inputs — path traversal /../etc/passwd 4.16 M 0.0002 0.0003 ±0.11% ~0%
safeRedirect – rejected inputs — null input 15.95 M 0.0001 0.0001 ±0.11% -1.6%
safeRedirect – rejected inputs — undefined input 15.93 M 0.0001 0.0001 ±0.11% -1.7%
safeRedirect – rejected inputs — empty string 15.99 M 0.0001 0.0001 ±0.11% -1.3%
safeRedirect – percent-encoded bypass — percent-encoded // (%2F%2F) 4.55 M 0.0002 0.0003 ±0.31% -4.3%
safeRedirect – percent-encoded bypass — percent-encoded path traversal (%2e%2e) 4.58 M 0.0002 0.0003 ±0.11% -3.5%
safeRedirect – percent-encoded bypass — mixed percent-encoded absolute URL 4.45 M 0.0002 0.0003 ±0.11% -2.8%
safeRedirect – custom default redirect — valid path with custom default 3.69 M 0.0003 0.0003 ±0.16% -1.5%
safeRedirect – custom default redirect — invalid input with custom default 4.65 M 0.0002 0.0002 ±0.10% -3.3%

🔬 Compared against the latest benchmark run on main. ⚠️ = >10% slower · 🚀 = >10% faster.

@renovate renovate Bot assigned Asjas Apr 22, 2026
@renovate renovate Bot force-pushed the renovate/better-auth-1.x branch from 17ff67a to 0c71942 Compare April 22, 2026 17:55
@renovate renovate Bot changed the title fix(deps): update dependency better-auth to v1.6.6 fix(deps): update dependency better-auth to v1.6.7 Apr 22, 2026
@renovate renovate Bot force-pushed the renovate/better-auth-1.x branch from 0c71942 to 074925e Compare April 23, 2026 10:49
@renovate renovate Bot changed the title fix(deps): update dependency better-auth to v1.6.7 fix(deps): update dependency better-auth to v1.6.8 Apr 23, 2026
@renovate renovate Bot force-pushed the renovate/better-auth-1.x branch from 074925e to 14d5a8a Compare April 24, 2026 06:38
@renovate renovate Bot changed the title fix(deps): update dependency better-auth to v1.6.8 fix(deps): update dependency better-auth to v1.6.9 Apr 24, 2026
@renovate renovate Bot force-pushed the renovate/better-auth-1.x branch from 14d5a8a to 1376d38 Compare April 29, 2026 20:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant