Skip to content

Registration accepts any string as email: no EmailStr validation means junk addresses and unbounded account data #394

Description

@usmanimamu17-create

Problem

RegisterRequest.email (app/models/auth.py) is a plain str:

class RegisterRequest(LoginRequest):
    full_name: str = Field(..., min_length=1)
    role: Role = Role.engineer

with no EmailStr type or format validator. AuthStore.register uses it directly as the primary identity and the sessions/audit/GDPR join key.

Consequences:

  • Junk identities are first-class accounts: "a", "not-an-email", or "x"*500 all register; the email becomes the unique key for sessions, token families, audit events, and GDPR lookups, so malformed emails pollute every auth-adjacent table.
  • GDPR erase/export are keyed on the email: erase_user_data and export_user_data filter audit rows by email == user.email — a garbage email that happens to substring-match or equal another user's malformed input can cross-match, and duplicate malformed emails are rejected only by the users.email unique index (an opaque 500 via IntegrityError instead of a clean 400).
  • The API promises registration semantics it does not validate: OpenAPI shows email: string with no format, so clients cannot rely on server-side email validation existing.

Root cause

The auth models were written before (or without) Pydantic's EmailStr/format validation, and the register endpoint never added a manual check.

Why this is architecturally hard

  1. The fix (an EmailStr field or field_validator) is small, but it changes the 422 validation behavior for existing clients that may have sent non-email strings; the change must be documented in the OpenAPI snapshot.
  2. Email normalization (lowercase? trim?) is a related decision: get_by_email is exact-match, so User@X.com and user@x.com are different accounts today; choosing normalization affects dedupe and session lookups.
  3. A test must assert registration rejects malformed emails and that the error is a structured 422, not an IntegrityError 500 on duplicates — the repo has no such test.

Proposed design

Use EmailStr (or an explicit validator) for RegisterRequest.email/LoginRequest.email, decide and implement normalization, and add tests for malformed, duplicate, and case-variant emails.

Acceptance criteria

Service

  • Malformed emails are rejected with a structured 422.
  • Duplicate registration returns a clean error, never an IntegrityError 500.

Tests

  • Tests cover malformed, duplicate, and case-variant emails.
  • Existing auth tests pass.

Out of scope

Role assignment (tracked separately) and password policy.

Getting started

pytest tests/test_auth*.py tests/test_be_205_228_236_238.py -q
make typecheck

Good first files to read: app/models/auth.py, app/api/v1/endpoints/auth.py, app/services/auth_store.py.

Activity

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

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardStellar WaveIssues in the Stellar wave programThird CampaignCampaign: Third Campaignarea/authAuthentication, tokens, sessions, RBAC, account lockoutpriority/mediumStandard backlog item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions