Passkey Cross-Origin Abuse: rpId, Origin, and Confused Deputies
Passkeys bind to an RP ID, not to "the brand." Mis-set rpId values and related-origin experiments can let a sibling site exercise credentials meant for the login host.
You need two origins you control in scope—or two in-scope hostnames the program owns—before this is more than theory.
Check what the ceremony claims
During registration, note rp.id and the origin in clientDataJSON. During login on a subdomain, see whether the same credential still works. login.example.com with rpId: example.com is normal. rpId: com or an unrelated sibling is not.
Related Origin Requests and /.well-known/webauthn files expand where a credential may be used. Read that file. If it lists a marketing site, a partner portal, or a wildcard you can XSS, the blast radius grew.
I've filed findings where an old staging hostname stayed in the related-origins list and still accepted production credentials. Boring config bug. Real account takeover path when staging was weaker.
Also diff registration rpId across web, iOS, and Android wrappers. Native layers sometimes register under an app facet that the web stack later confuses with a site origin during hybrid flows.
Subdomain takeovers on hosts listed in related-origins are the dream chain. Even without takeover, an XSS on a listed marketing origin can start a ceremony that the login host honors. Scope both hosts before you invest a week.
Iframes and parent confusion
Embedded WebAuthn in iframes is restricted on purpose. When a site punches holes—custom permission UX, native wrappers, or publicKey created in a parent then shipped to a child—re-check origin validation on the server. The authenticator signs what the browser saw; the server must still match its expected origins allowlist.
Mobile WebViews that load arbitrary https URLs under the same app bridge are cousins of this problem. Credential use inside the WebView may present an unexpected origin string. Log it from your lab build before you claim cross-origin success.
Proof without account theft theatrics
Register on origin A. Attempt ceremony on origin B with the same credential id. Capture success or the exact failure. If B is attacker-controlled within scope (subdomain takeover, XSS, partner), chain that.
Spell out cookie scope after success. A passkey that signs on a cookie-less partner origin may still mint a session cookie for the parent domain through a poorly checked token exchange—that is the impact paragraph.
Recommend least-privilege rpId, tight related-origin lists, monitoring for unexpected origins in assertion logs, and treating staging as a separate RP.
When related-origins change, old credentials do not magically shrink their trust circle on every authenticator implementation the same way. Re-test after config edits; do not assume a removed hostname is gone from every ceremony path overnight.
If the well-known file is cached at a CDN with a long TTL, note the cache headers in the report. Stale allowlists are still allowlists until they expire.
Cross-origin passkey bugs are config and binding failures. Show the two hosts and the one credential that crossed the line.