From e7c8066cf126bb7da9eecc94f4461ebb50933494 Mon Sep 17 00:00:00 2001 From: Taesu <166604494+bytaesu@users.noreply.github.com> Date: Sun, 21 Jun 2026 22:39:30 -0700 Subject: [PATCH] docs: refine warning guidance across plugin docs (#10185) --- docs/content/docs/plugins/magic-link.mdx | 4 ++-- packages/better-auth/src/plugins/magic-link/index.ts | 8 ++++---- packages/better-auth/src/plugins/mcp/index.ts | 11 ++++------- .../better-auth/src/plugins/oidc-provider/index.ts | 11 ++++------- packages/scim/src/routes.ts | 3 +-- 5 files changed, 15 insertions(+), 22 deletions(-) diff --git a/docs/content/docs/plugins/magic-link.mdx b/docs/content/docs/plugins/magic-link.mdx index 3879c52a2b..399259e863 100644 --- a/docs/content/docs/plugins/magic-link.mdx +++ b/docs/content/docs/plugins/magic-link.mdx @@ -128,7 +128,7 @@ and a `ctx` context object as the second parameter. **expiresIn**: specifies the time in seconds after which the magic link will expire. The default value is `300` seconds (5 minutes). -**allowedAttempts** (deprecated): Each verification call now consumes the token atomically on the first attempt, so retries always fail with `?error=INVALID_TOKEN` regardless of this setting (see [GHSA-hc7v-rggr-4hvx](https://github.com/better-auth/better-auth/security/advisories/GHSA-hc7v-rggr-4hvx)). The option is kept for source compatibility but ignored; multi-attempt redemption is no longer supported. Setting it to any value other than `1` emits a `console.warn` at startup (including `0`, which previously rejected immediately and now has no effect). +**allowedAttempts** (deprecated): Each verification call now consumes the token atomically on the first attempt, so retries always fail with `?error=INVALID_TOKEN` regardless of this setting. The option is kept for source compatibility but ignored; multi-attempt redemption is no longer supported. Setting it to any value other than `1` emits a `console.warn` at startup (including `0`, which previously rejected immediately and now has no effect). **disableSignUp**: If set to `true`, the user will not be able to sign up using the magic link. The default value is `false`. @@ -153,5 +153,5 @@ The `storeToken` function can be one of the following: The storage backend itself is controlled by the global [`verification`](/docs/reference/options#verification) config. If you configure `secondaryStorage`, magic link verification records can be stored there instead of the database. - When `secondaryStorage` backs verification (`verification.storeInDatabase: false`), the atomic single-use guarantee from [GHSA-hc7v-rggr-4hvx](https://github.com/better-auth/better-auth/security/advisories/GHSA-hc7v-rggr-4hvx) requires your secondary storage to expose `getAndDelete` (Redis `GETDEL`, KV `getAndDelete`). If the implementation only exposes `get` and `delete`, the consume falls back to an in-process JavaScript lock that does not coordinate across multiple application instances. Multi-instance deployments using secondary-storage verification MUST configure a backend that implements `getAndDelete`. + When `secondaryStorage` backs verification (`verification.storeInDatabase: false`), the atomic single-use guarantee requires your secondary storage to expose `getAndDelete` (Redis `GETDEL`, KV `getAndDelete`). If the implementation only exposes `get` and `delete`, the consume falls back to an in-process JavaScript lock that does not coordinate across multiple application instances. Multi-instance deployments using secondary-storage verification MUST configure a backend that implements `getAndDelete`. diff --git a/packages/better-auth/src/plugins/magic-link/index.ts b/packages/better-auth/src/plugins/magic-link/index.ts index f85cd046f5..28d7e92549 100644 --- a/packages/better-auth/src/plugins/magic-link/index.ts +++ b/packages/better-auth/src/plugins/magic-link/index.ts @@ -32,9 +32,9 @@ export interface MagicLinkOptions { * @deprecated Multi-attempt verification is no longer supported. Each * magic link token is consumed atomically on the first verification call, * so a given token mints at most one session regardless of this value - * (see GHSA-hc7v-rggr-4hvx). The option is kept for source compatibility - * and may be removed in a future major; any value other than `1` is - * ignored and emits a `console.warn` at plugin construction. + * The option is kept for source compatibility and may be removed in a future + * major; any value other than `1` is ignored and emits a `console.warn` at + * plugin construction. * * @default 1 */ @@ -162,7 +162,7 @@ export const magicLink = (options: MagicLinkOptions) => { if (options.allowedAttempts !== undefined && options.allowedAttempts !== 1) { console.warn( - "[better-auth/magic-link] `allowedAttempts` is ignored: tokens are consumed atomically on the first verification call (GHSA-hc7v-rggr-4hvx). Any value other than `1` has no effect; remove the option to silence this warning.", + "[better-auth/magic-link] `allowedAttempts` is ignored: tokens are consumed atomically on the first verification call. Any value other than `1` has no effect; remove the option to silence this warning.", ); } diff --git a/packages/better-auth/src/plugins/mcp/index.ts b/packages/better-auth/src/plugins/mcp/index.ts index 18474008ef..4276366c3b 100644 --- a/packages/better-auth/src/plugins/mcp/index.ts +++ b/packages/better-auth/src/plugins/mcp/index.ts @@ -555,13 +555,10 @@ export const mcp = (options: MCPOptions) => { // caller receives the row; concurrent racers receive `null` // and fall through to the `invalid_grant` error path. // - // TODO(legacy-hardening-coordinate): in-flight follow-ups at - // https://github.com/better-auth/better-auth/security/advisories/GHSA-9h47-pqcx-hjr4 - // and https://github.com/better-auth/better-auth/security/advisories/GHSA-pw9m-5jxm-xr6h - // touch this same surface. Whoever lands second must rebase - // to keep the atomic consume + `invalid_grant` semantics in - // place; do not regress to a `findVerificationValue` + - // delete pair. + // TODO(legacy-hardening-coordinate): follow-up hardening touches + // this same surface. Whoever lands second must rebase to keep + // the atomic consume + `invalid_grant` semantics in place; do + // not regress to a `findVerificationValue` + delete pair. const verificationValue = await ctx.context.internalAdapter.consumeVerificationValue( code.toString(), diff --git a/packages/better-auth/src/plugins/oidc-provider/index.ts b/packages/better-auth/src/plugins/oidc-provider/index.ts index e3c73a8956..3a49326e9d 100644 --- a/packages/better-auth/src/plugins/oidc-provider/index.ts +++ b/packages/better-auth/src/plugins/oidc-provider/index.ts @@ -880,13 +880,10 @@ export const oidcProvider = (options: OIDCOptions) => { // caller receives the row; concurrent racers receive `null` // and fall through to the `invalid_grant` error path. // - // TODO(legacy-hardening-coordinate): in-flight follow-ups at - // https://github.com/better-auth/better-auth/security/advisories/GHSA-9h47-pqcx-hjr4 - // and https://github.com/better-auth/better-auth/security/advisories/GHSA-pw9m-5jxm-xr6h - // touch this same surface. Whoever lands second must rebase - // to keep the atomic consume + `invalid_grant` semantics in - // place; do not regress to a `findVerificationValue` + - // delete pair. + // TODO(legacy-hardening-coordinate): follow-up hardening touches + // this same surface. Whoever lands second must rebase to keep + // the atomic consume + `invalid_grant` semantics in place; do + // not regress to a `findVerificationValue` + delete pair. const verificationValue = await ctx.context.internalAdapter.consumeVerificationValue( code.toString(), diff --git a/packages/scim/src/routes.ts b/packages/scim/src/routes.ts index be30412b03..ef37b72939 100644 --- a/packages/scim/src/routes.ts +++ b/packages/scim/src/routes.ts @@ -87,8 +87,7 @@ function resolveRequiredRoles( // TODO(scim-provider-ownership-default-on): flip default to `true` on next so // new non-org SCIM tokens are owner-locked by default. Coupled with the -// `scimProvider.userId` schema column. Tracks the SCIM provider-ownership -// advisory. +// `scimProvider.userId` schema column. function isProviderOwnershipEnabled(opts: SCIMOptions): boolean { return opts.providerOwnership?.enabled ?? false; }