Skip to content

fix: validate cookie methods and preserve setAll receiver - #304

Open
VG31OP wants to merge 2 commits into
supabase:mainfrom
VG31OP:fix/cookie-method-validation
Open

VG31OP wants to merge 2 commits into
supabase:mainfrom
VG31OP:fix/cookie-method-validation

Conversation

@VG31OP

@VG31OP VG31OP commented Oct 13, 2026

Copy link
Copy Markdown

What kind of change does this PR introduce?

Bug fix.

What is the current behavior?

  1. When cookie accessor methods (setAll, get, set, remove) are explicitly set to undefined (or non-function values) on the cookies options object, the library previously only used the in operator ("setAll" in cookies, "set" in cookies, etc.). Because "key" in { key: undefined } evaluates to true in JavaScript:
    • In createServerClient, omitting setAll logs a helpful warning on token refresh, but passing { getAll: () => [], setAll: undefined } (common with conditional adapter configurations) bypassed this fallback and threw TypeError: originalSetAll is not a function.
    • In createBrowserClient, passing { getAll: () => [], setAll: undefined } bypassed the initialization check and crashed later on storage write with TypeError: setAll is not a function.
    • Passing cookies: { get: () => ..., set: undefined, remove: undefined } attempted to call cookies.set and threw TypeError: cookies.set is not a function.
    1. When custom stateful cookie adapters rely on this, calling setAll as an unbound reference drops its method receiver, throwing TypeError: Cannot set properties of undefined (fixing cookies.setAll loses its receiver for stateful cookie adapters #299).
    1. In createServerClient, the internal setAll wrapper calls Object.keys(headers).length. If headers is omitted or nullish, it crashes with TypeError: Cannot convert undefined or null to object.

What is the new behavior?

  • Validates that cookie methods (get, getAll, set, remove, setAll) are actual functions before attempting invocation, preserving in for TypeScript union type narrowing while guaranteeing runtime safety when properties are explicitly undefined.
    • Preserves the cookie adapter receiver when invoking cookies.setAll.
    • Guards the setAll server wrapper with Boolean(headers && Object.keys(headers).length > 0) to handle omitted or optional headers cleanly.
    • Preserves the existing graceful server fallback warning when setAll is undefined, and ensures createBrowserClient enforces setAll presence at construction time.

Verification

  • pnpm exec vitest run: 125/125 tests pass (5 new unit tests added covering all cases).
    • pnpm run build: both tsc builds (ESM & CJS) compile cleanly with 0 errors.
    • pnpm exec eslint: 0 lint errors or warnings.
    • pnpm exec prettier --check src/cookies.ts src/cookies.spec.ts src/createBrowserClient.spec.ts: cleanly formatted.

Ensure cookie methods (get, getAll, set, remove, setAll) are functions rather than merely checking property existence with the in operator, which evaluates to true for explicitly undefined properties.

Guard the setAll server wrapper against undefined or omitted headers to prevent TypeError in Object.keys.

Forward setAll calls to preserve the cookie adapter method receiver, fixing supabase#299.

Add unit tests verifying behavior when accessors are explicitly undefined, when headers are omitted, and preserving receiver on stateful adapters.
@VG31OP
VG31OP requested review from a team as code owners October 13, 2026 14:22

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant