if provider.name == "github":
email = None
email_resp = await client.get(
"https://api.github.com/user/emails", headers=headers
)
if email_resp.status_code == 200:
emails = email_resp.json()
primary = next((e for e in emails if e.get("primary")), None)
email = primary["email"] if primary else None
(src/fim_one/web/oauth.py:172-183)
GitHub's /user/emails returns each email with both primary and verified flags. The current code only filters by primary — a user can have an unverified primary email (e.g., they changed their primary and haven't confirmed the new one yet). Accepting an unverified email opens an account-takeover surface:
- Attacker creates a GitHub account with target's email as a "secondary, unverified" entry.
- Marks it primary (GitHub allows this without verification in some flows).
- Logs into the fim-one app via GitHub OAuth.
- Now controls the target's fim-one account.
GitHub's docs explicitly recommend filtering on verified=True as well. Fix:
primary = next((e for e in emails if e.get("primary") and e.get("verified")), None)
Severity
High — account-takeover-class issue, even if the exploit path is narrow.
(
src/fim_one/web/oauth.py:172-183)GitHub's
/user/emailsreturns each email with bothprimaryandverifiedflags. The current code only filters byprimary— a user can have an unverified primary email (e.g., they changed their primary and haven't confirmed the new one yet). Accepting an unverified email opens an account-takeover surface:GitHub's docs explicitly recommend filtering on
verified=Trueas well. Fix:Severity
High — account-takeover-class issue, even if the exploit path is narrow.