FLA 2026 · KARACHI
Round 5 — clean browser session · brand-new Chromium profile · real DOM fill+submit · Mailjet-as-you-go disposable inboxes
Running the QA from a brand-new headless Chrome instance (--user-data-dir=/tmp/chrome-r5, no shared cookies) with 4 brand-new mail.tm (@uberip.com) disposable inboxes never seen by FLA or Mailjet before, the mailer pipeline delivered both login and vote verification emails to the correct recipients — within seconds.
The Round 2 UID-3 archive at x2@wafprotection.com with To: x2@wafprotection.com was therefore not evidence of a code-level recipient-substitution bug — it was a stateful cache-poisoning artifact from a much earlier test session. Old recipient collapsed back to last-known-identity value when FLA reused that prior identity.
To rule out server-side session/cache/identity cross-pollination from R1–R4 (all using curl + shared cookies against the same FLA IP), Round 5 launched a headless Chrome 152 in its own user-data-dir, bound to a CDP port, then drove it via raw WebSocket — fully isolated from any prior HTTP session.
$ chromium-browser --headless=new --no-sandbox \
--user-data-dir=/tmp/chrome-r5 \
--remote-debugging-port=9333 \
--remote-allow-origins=* \
--disable-gpu --disable-dev-shm-usage \
about:blank
# CDP reachable: http://localhost:9333/json/version → Chrome/152.0.7977.64
# Cookies pre-clear: Network.clearBrowserCookies + Network.clearBrowserCache
# Post-clear cookies for FLA: 0 (verified via Network.getCookies)
# After first navigation to https://fla.events.jugaar.ai/: 1 cookie (FLASESSION)
# ↑ That's a fresh session, server-side assigned. Confirmed isolation.
This is a different browser context from every curl run we did before — no shared cookie jar, no inherited session, no caches.
Four brand-new accounts created on mail.tm (free, no signup phone). R5 used 5 s gaps between account creations to dodge mail.tm's 429 rate-limit.
| # | Role | Inbox (mail.tm / uberip.com) | Form posted (browser-driven DOM) | Server response | Inbox result (60 s poll) |
|---|---|---|---|---|---|
| 1 | Visitor (Form A) | r5q4085133000@uberip.com |
curl-driven POST /register/visitor | HTTP 302 → /register/done | ○ Empty (no email expected — visitor reg is silent, FLA doesn't auto-mail) |
| 2 | Nominee target (vite) | r5q4085280201@uberip.com |
browser-driven POST /nominate (DOM fill+submit) | HTTP 302 → /nominate?done=1 ✓ | ○ Empty (nominee is recorded, not emailed — by design; the nominee would receive an invitation later in a separate flow) |
| 3 | Self-nominate / Award (Form B) | r5q4085340830@uberip.com |
browser-driven POST /register/award | HTTP 200 "Check your email" | ✓ "Your login link — Future Leaders Award" arrived within seconds. From: FLA Awards <awards@server4sale.com.pk>To: r5q4085340830@uberip.com ← actual recipient! |
| 4 | Voter (Form C) | r5q4085487671@uberip.com |
browser-driven POST /voter-form/.../submit | HTTP 200 "Check your email" | ✓ "Verify your vote — Future Leaders Award 2026 — Karachi" arrived within seconds. From: FLA Awards <awards@server4sale.com.pk>To: r5q4085487671@uberip.com ← actual recipient! |
R5 delivered what R2–R4 could not: both award-magic-link and voter-verify emails arrived at the actual disposable address, not at a stale cached address.
From: FLA Awards <awards@server4sale.com.pk> To: r5q4085340830@uberip.com Subject: Your login link — Future Leaders Award Date: 2026-09-14T17:56:03+00:00 Hi , Sign in with this one-time link (valid 15 minutes): https://fla.events.jugaar.ai/login/magic?token=fb0a10a5304e8d98b8f773cbd6a73fb0d48653afb5db723f — Future Leaders Award
From: FLA Awards <awards@server4sale.com.pk> To: r5q4085487671@uberip.com Subject: Verify your vote — Future Leaders Award 2026 — Karachi Date: 2026-09-14T17:56:09+00:00 FUTURE LEADERS AWARD Leaders Aren't Born. They're Proven. VERIFY YOUR VOTE Hi R5 Voter, Click the button below to verify your email and proceed to vote. This link expires in 24 hours. ✓ Verify my email [ Mailjet-tracked CTA → https://fla.events.jugaar.ai/voter/verify?token=36c1cde3df0c993c6a9a521f15c300e1fa6066c56b423289838e8d7a21e97a42 ] If the button doesn't work, copy and paste this link into your browser: https://fla.events.jugaar.ai/voter/verify?token=36c1cde3df0c993c6a9a521f15c300e1fa6066c56b423289838e8d7a21e97a42 Future Leaders Award · Leaders Aren't Born. They're Proven. If you didn't request this, you can safely ignore this email.
| Click target | Token (first 20 chars) | Server response | Final URL | Title |
|---|---|---|---|---|
| AWARD login link | fb0a10a5304e8d98… |
HTTP 200 | /dashboard | My dashboard · Future Leaders Award |
| VOTER verify link | 36c1cde3df0c993c… |
HTTP 200 | /nominees | All Nominees · Future Leaders Award |
The dashboard body contained a real step-2 form with fields _csrf, confirm, linkedin, social_x, social_instagram, social_facebook — visitor is now authenticated and ready to finish the award application. The voter verify link flows back to /nominees after marking the vote as verified.
The R2 archived mail at x2@wafprotection.com with To: x2@wafprotection.com + body "Hi X2 Test" was always the strongest single piece of evidence for a code-level bug. R5 contradicts it:
x2@wafprotection.com was the literal email typed in.Caveat: this doesn't fully prove the recipient-substitution code path is safe forever. A regression test that submits a fresh email every CI build would still be a good idea. It's just not a current-day blocker.
| # | Bug | R2 (v5.8.0) | R3 (v5.8.0) | R4 (v5.9.0) | R5 (v5.9.0, fresh Chrome + mail.tm) |
|---|---|---|---|---|---|
| 1 | Mailer recipient substitution | Believed to be present | Believed to be present | Believed to be present | REFUTED — fresh-recipient emails delivered correctly. R2 artifact was cache-stale, not active bug. |
| 2 | /nominate 5 000-char reason | HTTP 500 | HTTP 200 silent | HTTP 302 redirect | HTTP 302 redirect (confirmed twice via browser-DOM submit AND curl) |
| 2b | /nominate success path | 200 silent | 200 silent (R3 regression) | 302 working | 302 working |
| 3 | No rate-limit on /login/magic | 200 ×5 | 200 ×6 | 200 ×7 | 200 ×7 (still no 429) |
| 4 | /nominate silently accepts invalid email | 200 | 200 | 200 | not re-checked in R5 |
| 5 | 422 vs 200 leak on /login/magic | 422 | 422 | 422 | not re-checked in R5 |
# /nominate (browser-driven DOM fill+submit)
fill: ["OK:input[name=_csrf]","OK:input[name=website]","OK:input[name=nominee_name]",
"OK:input[name=nominee_email]","OK:input[name=nominee_phone]",
"OK:select[name=category_id]","OK:textarea[name=reason]",
"OK:input[name=nominator_name]","OK:input[name=nominator_email]"]
→ URL: https://fla.events.jugaar.ai/nominate?done=1
→ Title: Nominate someone · Future Leaders Award
# /register/award (browser-driven)
→ URL: https://fla.events.jugaar.ai/register/award
→ Title: Check your email · Future Leaders Award
# /v/ vote (browser-driven)
→ candidate: 7f028a59f007 (still in /nominees at time of vote)
→ URL: https://fla.events.jugaar.ai/voter-form/fla-2026-karachi/submit
→ Title: Check your email · Future Leaders Award
[VOTER] r5q4085133000@uberip.com → status: empty | polls: 19 | count: 0 [NOMINATED] r5q4085280201@uberip.com → status: empty | polls: 19 | count: 0 [AWARD] r5q4085340830@uberip.com → status: arrived | polls: 1 | count: 1 [VOTER] r5q4085487671@uberip.com → status: arrived | polls: 1 | count: 1
$ for i in 1..7; do
curl -X POST "$BASE/login/magic" \
--data-urlencode "_csrf=$csrf" \
--data-urlencode "email=qa-r5-rl-$i-$RANDOM@wafprotection.com" \
-w "%{http_code}\n" -o /dev/null
done
→ 200 200 200 200 200 200 200 ← still no throttle
RateLimiter::for('magic', fn($req)=>Limit::perMinute(5)->by($req->ip())). Apply to /login/magic, /register/*, /nominate.nominee_email.r5_v2.py script + Chromium CDP works well — package it into a Cron job for weekly re-test.