Since 31 March 2026, Gmail users can rename their primary address. OAuth handlers that look up users by email create a duplicate account on the next login. authdrift runs Semgrep with a narrow ruleset that finds those handlers and nothing else.
pip install authdrift
The scan tells you where the pattern lives. The fix is usually one field.
# Install the CLI and its Semgrep dependency. $ pip install authdrift # Scan the current directory. $ authdrift scan ./ src/auth/google.ts 12:18 WARNING oauth-passport-email-as-primary-key This OAuth handler is using profile.emails[0].value as a user lookup key. When a user renames their Gmail address, this lookup will fail and your application will silently create a duplicate user record. Fix: use profile.id (the OIDC sub claim) as the immutable primary key. # Exit 0: clean. Exit 1: findings. Exit 2: error.
# Before — lookup on email, breaks on rename: const user = await db.findUser({ email: profile.emails[0].value, // mutable }); # After — lookup on the OIDC sub claim, stable forever: const user = await db.findUser({ google_sub: profile.id, // immutable }); # Email still lives on the user record as a contact attribute. # The primary key is the one thing that survives a rename.
The scan is read-only and narrow. It sits alongside Semgrep, trufflehog, and gitleaks without adding noise to the diff.
The OSS ruleset is enough for a fresh repo. A legacy codebase with a decade of OAuth surface often needs a hand sorting the findings and writing the migration.
Install in seconds. No API keys, no telemetry, no account required. MIT licensed and built on Semgrep.
pip install authdrift