Security vulnerabilities

  • Status Closed
  • Assigned To
    cbay
  • Private
Attached to Project: Security vulnerabilities
Opened by hardikdevaliya7 - 25.09.2026
Last edited by cbay - 28.09.2026

FS#503 - Email-validation link consumed by unsafe HTTP methods (GET/HEAD) — CSRF-forceable, no user interact

Severity: Medium

Unauthenticated, single-request, 100% reproducible, maps directly to your own listed "Broken authentication" and "CSRF with security impact" categories. Bounded because it does not grant account takeover — I tried that escalation myself and it's cleanly ruled out (see below). Not theoretical either — 6 live examples of this exact failure already turned up in public web archives before this report was written.

Summary (plain words)

Your "Welcome to alwaysdata!" confirmation link is supposed to only activate when the real user clicks it. In practice it activates on any request that touches it — including a bare HEAD (a "does this URL exist" check, not a click) and including a request from a totally unrelated web page via a plain <img src="…"> tag, no login or cookies needed. So the single-use token gets silently burned by anything that merely touches the link — most commonly corporate email security gateways, antivirus scanners, and chat link-preview bots, which pre-fetch every link in every email automatically. The real user then clicks their own legitimate link and sees "An error occurred while verifying your registration," even though the account is already validated behind the scenes.

What this is NOT (tested and ruled out)

I tried escalating to full account takeover — took my own valid password-reset link and swapped in a different account's ID while keeping my own token. Server rejected it cleanly ("Le lien utilisé est invalide"). Tokens are properly bound to their account. This is a broken-auth/forceable-state-change bug, not a credential/session compromise.

Steps to reproduce

Part 1 — HEAD silently completes validation
1. Register a new account. You get a "Welcome" email with …/user/validate/?user_id=<ID>&token=<TOKEN>&expiration=<EXP>.
2. Don't click it — send only a HEAD request to that URL.
3. Now open the same link for real in a browser → "An error occurred while verifying your registration."
4. Log in with that account's credentials anyway → succeeds, proving the HEAD already completed validation.

Part 2 — forceable from any unrelated page
1. Same as above with a second account.
2. Build any page containing only <img src="https://admin.alwaysdata.com/user/validate/?user_id=<ID>&token=<TOKEN>&expiration=<EXP>">.
3. Open it — zero relationship to alwaysdata, zero cookies needed.
4. Real link now errors on click, but login still succeeds — the <img> alone did it.

curl commands (re-runnable — grab a fresh account each time, tokens are single-use)

# 1. Register at https://www.alwaysdata.com/en/register/, get user_id/token/expiration from the email.

# 2. HEAD only — before ever opening the link in a browser:
curl -I "https://admin.alwaysdata.com/user/validate/?user_id=<ID>&token=<TOKEN>&expiration=<EXP>"

# 3. Real GET — expect the error, not success:
curl -s "https://admin.alwaysdata.com/user/validate/?user_id=<ID>&token=<TOKEN>&expiration=<EXP>" | grep -i "erreur\|error"

# 4. Confirm it validated anyway via login:
curl -s -c jar.txt -b jar.txt "https://admin.alwaysdata.com/login/" -o login_page.html
CSRF=$(grep -oE 'name="csrfmiddlewaretoken" value="[^"]*"' login_page.html | grep -oE '"[A-Za-z0-9]{20,}"' | tr -d '"')
curl -s -c jar.txt -b jar.txt -X POST "https://admin.alwaysdata.com/login/" \

  1. -data-urlencode "csrfmiddlewaretoken=$CSRF" \
  2. -data-urlencode "login=<account email>" \
  3. -data-urlencode "password=<account password>" \
  4. D - -o /dev/null | grep -i "^location"

# "location: /" + 302 = login succeeded = already validated.

Impact

Real users' confirmation links can be silently invalidated by infrastructure outside their control before they ever see the email. An attacker who obtains a victim's link via any side channel (the same exposure that already leaked 6 real tokens into public archives) can deliberately kill that specific pending registration with one unauthenticated request. Not account takeover.

Real-world evidence

6 real historical validation/reset links (user_id+token+expiration) found in Wayback Machine/Common Crawl/URL-scan archives, spanning May 2025–May 2026, all now expired but proving this mechanism already fires in production.

Suggested fix

Add an explicit HEAD handler on the validate view that returns 200 without consuming the token, or require POST-based confirmation like /user/reset_password/ already correctly does.

Closed by  cbay
28.09.2026 09:04
Reason for closing:  Invalid
Admin
cbay commented on 28.09.2026 09:04

Hello,

The only thing that could happen is that the attacker would validate the validation email. That's absolutely harmless.

Kind regards,
Cyril

Loading...

Available keyboard shortcuts

Tasklist

Task Details

Task Editing