[Bug] WebAuthn passkey registration blocked on rpIds with TLDs longer than 6 characters (.accountant, .technology, etc.) — isValidDomain regex too strict

[Bug] WebAuthn passkey registration blocked on rpIds with TLDs longer than 6 characters (.accountant, .technology, etc.) — isValidDomain regex too strict

Hi,

Filing on behalf of an enterprise customer where Zoho Vault is deployed across the company. The Chrome extension blocks WebAuthn passkey registration on legitimate sites whose Relying Party ID (rpId) has a TLD longer than 6 letters. This affects every post-2012 ICANN gTLD: .accountant, .technology, .consulting, .engineering, .management, .business, .finance, .lawyer, .museum, .travel, etc.

Reproduction

  • Browser: Chrome (also Edge), Windows.
  • Extension: Zoho Vault from Chrome Web Store (igkpcodhieompeloncfnbekccinhapdb).
  • Signed into Zoho Vault with the passkey feature enabled.
  • Visit any WebAuthn registration whose rp.id ends in a TLD with 7+ letters, served from a same-origin page (so the W3C origin/rpId check would pass via equality).
  • Click the register-passkey button.
  • navigator.credentials.create() rejects synchronously with: DOMException("Passkey request is blocked due to an insecure or mismatched website address. Please check your website address and try logging in again.", "SecurityError")

Pausing the extension on the same site, or replacing navigator.credentials.create with the unwrapped CredentialsContainer.prototype.create from the page console, lets registration succeed via Windows Hello. So the underlying WebAuthn call is fine; the extension is the gatekeeper.

Root cause (visible in your content script)

Your wrapper around navigator.credentials.create calls PasskeyHelper.isValidRpId(rp.id), which calls PasskeyHelper.isValidDomain(rpId). The latter is:

static isValidDomain = (str) => {
let regexp = /^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6}$/i;
return regexp.test(str);
};

The {2,6} cap on the final label rejects every TLD with 7+ letters. For example, "secure.app.boosted.accountant" passes the W3C WebAuthn rules but fails this regex, so isValidDomain returns false, isValidRpId returns false, and createPasskey throws SecurityError.

In createPasskey itself:

if (!PasskeyHelper.isValidRpId(options.publicKey.rp.id)) {
throw new DOMException(errorTexts[VI18N.PASSKEY_SECURITY_ERROR],
PasskeyError.SecurityError);
}

There is no fallback to the native API on this branch. Other failure paths in the same function (not signed in, passkey unavailable, NotAllowedError from the background script) correctly fall through to originalCredentials.create.apply(this, arguments) so the OS provider (Windows Hello, security key) can handle the call. The isValidRpId branch does not.

Per W3C WebAuthn L2 §5.1.3, an rpId is valid when it equals, or is a registrable suffix of, the calling document's effective domain. There is no spec restriction on TLD length.

Asks

  1. Replace the regex in PasskeyHelper.isValidDomain. The minimal fix is to drop the upper bound, e.g. /^[a-z0-9]+([\-\.][a-z0-9]+)*\.[a-z]{2,}$/i. Better: align with the WebAuthn L2 algorithm (origin equality OR registrable-suffix via the Public Suffix List).
  2. More important: when isValidRpId returns false, fall through to originalCredentials.create.apply(this, arguments) instead of throwing. You already do this for the other fallback paths. Throwing makes the user unable to use any passkey provider at all — Vault has effectively hijacked WebAuthn for that origin and refused, with no escape hatch short of pausing the extension. A one-line change.

Impact

Enterprise customers who standardise on Zoho Vault cannot register passkeys on any site whose rpId uses a non-legacy TLD. Workaround today is "pause Vault for the site," which doesn't scale to a full organisation.

Sanity check anyone can run in a browser console:

/^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6}$/i.test("secure.app.boosted.accountant")  // false
/^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6}$/i.test("example.com") // true

Happy to provide more details, screenshots, or do a screenshare. Thanks.