eToro CORS Bypass — Attacker-Origin PoC

Researcher: liamconner10 · header: X-Bug-Bounty: liamc
Served from , a third-party origin. The eToro edge CORS policy treats the regex www.etoro.com as a wildcard match (www<ANY>etoro<ANY>com) and reflects the attacker's Origin into Access-Control-Allow-Origin + Access-Control-Allow-Credentials: true. Same-origin policy across the entire eToro trading platform is therefore bypassed for any visitor.

Demo A — paste a real JWE → see what data the attacker page exfiltrates cross-origin

Paste the JWE (the Authorization header value the eToro SPA attaches to every authed request — copy from DevTools → Network → any /api/* request). The PoC is on a different origin from eToro; without the CORS bypass, the browser would block reading the response. With the bypass, the attacker page reads it.

Demo B — Salesforce LiveAgent chat-bot iframe abuse from attacker origin

The eToro page https://www.etoro.com/app/chat-bot serves no X-Frame-Options header, so it is iframeable from any origin. The page's window.onmessage handler accepts a {type:"chat-bot-start", accessToken, language, agentType, ...} message with no origin check, then invokes botAPI.liveAgentAPI.startChat, sending the fields verbatim to Salesforce LiveAgent including extraPrechatFormDetails.value: accessToken as STS_Token__c. An attacker page can therefore push arbitrary content (including a sentinel STS Token) into eToro's Salesforce support queue from any origin — this confirms the cross-origin postMessage path is wide open and the JWE travels to Salesforce as a transcript field.


Demo C — the regex matches every *.etoro.com: confirmed bypass-scope

The CORS regex is enforced at the Cloudflare edge layer, applied uniformly across the entire etoro.com zone. Below is a live OPTIONS-preflight sweep across known live subdomains (run via residential-proxy out-of-band; results frozen at the times the PoC was deployed). Green = attacker origin reflected with credentials. The list includes auth/STS issuers, trading APIs, the PCI deposit host, the cashier, the wallet, and many more.

Demo D — /embed/* and /app/chat-bot are iframeable (no X-Frame-Options)

eToro's main Angular SPA shell is also served from https://www.etoro.com/embed/, /embed/chat, /embed/widget — none carry XFO or frame-ancestors, so any origin can iframe them. Combined with the global postMessage firehose found in main.js (the postMessageService registers a single window.addEventListener("message", …) with no origin filter, then routes every message into multiple in-app subscribers), an attacker iframe controls the same-origin SPA's internal pubsub fabric — including chat-link-clicked$location.url(…) / window.open(…) sinks.

Demo E — JWE-mint probes (control: shows cookies-alone is NOT the chain partner)

Probes JWE-issuing endpoints with the visitor's cookies only (no JWE pasted). Shows that none of them auto-mint a JWE based on cookies alone — eToro auth is JWE-in-header (no eToro session cookie), so the chain partner has to be JWE-leakage, not a cookie-only mint. Reported to map the architecture.

What this bug means (summary)

PropertyState
Bypass scope~114 *.etoro.com hosts including www, sts, tapi-real, tapi-demo, kyc, billing-pci, cashier, wallet, public-api, signin, registration, raf-azure, news, embed, push-lightstreamer, plus the partner/affapi backend and the credit-card view SPA. The misconfig is at the CF edge, applied uniformly to the entire etoro.com zone.
Credentials reflectedAccess-Control-Allow-Credentials: true on every bypassed host — the browser SOP is removed.
What an attacker can do today (no chain)(1) From www0etoro.com (or any www<c>etoro<c>com the attacker registers), CORS-fetch every authed endpoint with the visitor's __cf_bm/__cflb cookies — DataDome and JWE-required endpoints reject, but every public/unauth endpoint becomes readable cross-origin with credentials, opening XS-Leak / oracle attacks. (2) Iframe /app/chat-bot from any origin and inject arbitrary "STS Tokens" into eToro's Salesforce LiveAgent support transcripts (see Demo B). (3) Iframe /embed/* and feed messages into the SPA's postMessageService firehose — internal pubsub events fire without origin verification.
What the bug enables when chainedAny JWE-leak primitive (a found XSS, an OAuth redirect mis-validation, a token-disclosure endpoint, the existing Salesforce transcript exposure) becomes full ATO from any third-party origin, on real-money brokerage accounts.
The single fixAnchor the regex (^https://www\.etoro\.com$) — or replace the regex with an exact-string allow-list. Restrict ACAC:true to legitimately first-party origins. Don't reflect arbitrary origins matching a loose pattern.