#13495·next-auth

GitHub provider: emails[0] read unguarded throws on an empty /user/emails response

Author: NitjsefnieCreated Sep 9, 2026Updated Sep 9, 2026

Provider type

GitHub

Environment

  • @auth/core 0.41.3 (the version pinned by next-auth 5.0.0-beta.32), from npm
  • Node.js 24.17.0, standalone script, no framework involved
  • packages/core/src/providers/github.ts on main as of 2026-09-09 still contains the same unguarded read, so this is not a 0.41.x-only regression

Reproduction URL

https://github.com/Nitjsefnie/next-auth-github-emails-repro

Describe the issue

When a GitHub profile has no public email, the GitHub provider's userinfo.request always calls the authenticated GET /user/emails endpoint. If that endpoint answers 200 with an empty list — which GitHub can return, e.g. for some bot/service and org-restricted accounts — the provider throws instead of returning the profile (providers/github.ts, the fallback block):

javascript
const emails: GitHubEmail[] = await res.json()
profile.email = (emails.find((e) => e.primary) ?? emails[0]).email

On an empty array emails.find(...) ?? emails[0] is undefined, so reading .email throws TypeError: Cannot read properties of undefined (reading 'email'). The request is also spent unconditionally: nothing checks whether the granted scope actually includes user:email before calling the endpoint.

Related: #13494 (same defect, closed by triage for a missing reproduction link — this issue supersedes it with the linked public repo).

How to reproduce

Clone the linked reproduction repository and run:

bash
npm install
npm start

The script stubs fetch, returns an email-less /user profile and a 200 with [] from /user/emails, and calls the provider's userinfo.request — the same two responses GitHub serves an account with no email on file.

Observed output:

THREW: TypeError: Cannot read properties of undefined (reading 'email')
CALLS: https://api.github.com/user | https://api.github.com/user/emails

Expected behavior

An empty /user/emails response should leave profile.email unset — the profile itself is valid and the sign-in should proceed without an email, the same as when /user carries no email and the email endpoint is never consulted. The natural fix is to guard the index before reading .email:

javascript
const emails: GitHubEmail[] = await res.json()
const primary = emails.find((e) => e.primary) ?? emails[0]
if (primary) profile.email = primary.email