Summary
<AutoConnect> consumes in-app-wallet auth material directly from the page URL on every load, with no check that the app initiated the flow. getUrlToken() reads authCookie / authResult / authFlow / walletId from the query string or the hash and hands them to the connection flow, which persists the cookie and signs the browser into whatever wallet the token names. There is no origin, nonce, state, or signature validation on this path.
Because the same params are what a redirect OAuth login legitimately returns, an integrator who mounts <AutoConnect> globally (the documented pattern) cannot distinguish a real redirect return from an attacker-supplied link. A link of the shape https://app.example/…?walletId=inApp&authCookie=… (or authFlow=link&authResult=…) therefore causes an unsolicited wallet connection: the visitor is silently connected to a wallet chosen by whoever crafted the link, or the link flow attaches an external profile onto the active account. The params are then scrubbed from the address bar via pushState, so nothing is visible to the user.
This is a request to add a built-in provenance control (or an opt-out) so integrators are not each forced to reimplement one.
Where (v5.119.4)
packages/thirdweb/src/wallets/in-app/web/lib/get-url-token.ts — reads the params from window.location.search and the hash; a grep for nonce|state|origin|verify|signature in this file returns only the pushState that scrubs them.
packages/thirdweb/src/wallets/connection/autoConnectCore.ts — authFlow === "link" → handleLinkingFlow; authCookie → clientStorage.saveAuthCookie(...); then connects the wallet. No provenance gate.
The clientId domain allowlist does not mitigate this: the malicious link loads the integrator's own allowlisted origin, so every downstream call carries an allowed Origin natively.
Impact class
Phishing link → the victim's browser adopts an attacker-named in-app wallet (any value the victim then deposits or approves flows to the attacker), or an attacker profile is linked onto the victim's account. Pre-conditions are only: <AutoConnect> mounted (default guidance) and the victim opening a link.
Requested change (any one would resolve it)
- Provenance gate in the SDK. When initiating a redirect login, persist a one-time nonce and echo it on the return
redirectUrl; on load, honor a URL token only if the nonce matches, else ignore/strip it. This is the redirect-OAuth-safe version of "don't trust URL auth material you didn't ask for."
- An explicit opt-out, e.g.
<AutoConnect readUrlToken={false} /> (or a wallet-level flag), so apps that don't use redirect login can disable URL-token consumption entirely.
- At minimum, documented guidance that URL-token consumption is on by default and how to gate it.
Option 2 is the smallest and unblocks apps that use popup/OTP/passkey only.
Context
We implemented an integrator-side guard (a nonce-bound marker set at redirect initiation, stripping any unmatched URL token before <AutoConnect> mounts), so this is not urgent for us, but it belongs in the SDK — most integrators won't know the URL path is load-bearing until they audit it. Happy to share the approach or a PR if useful.
Summary
<AutoConnect>consumes in-app-wallet auth material directly from the page URL on every load, with no check that the app initiated the flow.getUrlToken()readsauthCookie/authResult/authFlow/walletIdfrom the query string or the hash and hands them to the connection flow, which persists the cookie and signs the browser into whatever wallet the token names. There is no origin, nonce,state, or signature validation on this path.Because the same params are what a redirect OAuth login legitimately returns, an integrator who mounts
<AutoConnect>globally (the documented pattern) cannot distinguish a real redirect return from an attacker-supplied link. A link of the shapehttps://app.example/…?walletId=inApp&authCookie=…(orauthFlow=link&authResult=…) therefore causes an unsolicited wallet connection: the visitor is silently connected to a wallet chosen by whoever crafted the link, or thelinkflow attaches an external profile onto the active account. The params are then scrubbed from the address bar viapushState, so nothing is visible to the user.This is a request to add a built-in provenance control (or an opt-out) so integrators are not each forced to reimplement one.
Where (v5.119.4)
packages/thirdweb/src/wallets/in-app/web/lib/get-url-token.ts— reads the params fromwindow.location.searchand the hash; a grep fornonce|state|origin|verify|signaturein this file returns only thepushStatethat scrubs them.packages/thirdweb/src/wallets/connection/autoConnectCore.ts—authFlow === "link"→handleLinkingFlow;authCookie→clientStorage.saveAuthCookie(...); then connects the wallet. No provenance gate.The clientId domain allowlist does not mitigate this: the malicious link loads the integrator's own allowlisted origin, so every downstream call carries an allowed
Originnatively.Impact class
Phishing link → the victim's browser adopts an attacker-named in-app wallet (any value the victim then deposits or approves flows to the attacker), or an attacker profile is linked onto the victim's account. Pre-conditions are only:
<AutoConnect>mounted (default guidance) and the victim opening a link.Requested change (any one would resolve it)
redirectUrl; on load, honor a URL token only if the nonce matches, else ignore/strip it. This is the redirect-OAuth-safe version of "don't trust URL auth material you didn't ask for."<AutoConnect readUrlToken={false} />(or a wallet-level flag), so apps that don't use redirect login can disable URL-token consumption entirely.Option 2 is the smallest and unblocks apps that use popup/OTP/passkey only.
Context
We implemented an integrator-side guard (a nonce-bound marker set at redirect initiation, stripping any unmatched URL token before
<AutoConnect>mounts), so this is not urgent for us, but it belongs in the SDK — most integrators won't know the URL path is load-bearing until they audit it. Happy to share the approach or a PR if useful.