Skip to content

[Bug] GET-based unsubscribe leaks email enumeration — returns different error for missing vs invalid token #1028

@Pcmhacker-piro

Description

@Pcmhacker-piro

Description

The GET unsubscribe endpoint (/subscribe/unsubscribe) at subscribe.py:89-113 returns different error messages depending on whether the email exists in the database:

  • If email not found: {"message": "Subscription not found or already inactive."}
  • If token doesn't match: {"message": "Invalid unsubscribe link."}

An attacker can enumerate which email addresses are subscribed to the weekly digest by observing the error message. This is an information disclosure vulnerability.

Additionally, the unsubscribe flow uses GET requests with email and token as URL query parameters, which leak the unsubscribe token in server logs, browser history, and via referrer headers.

Affected Files

  • backend/app/routers/subscribe.py:89-113

Expected Behavior

  1. Both "not found" and "invalid token" cases should return the same generic message (e.g., "Unsubscribe link is invalid or expired.") to prevent enumeration.
  2. The unsubscribe action should use POST (not GET) to prevent token leakage via URL.

Labels

type:bug, level:intermediate, gssoc2026

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions