diff --git a/keepassxc-browser/background/keepass.js b/keepassxc-browser/background/keepass.js index 72a5cad8..06a6ac13 100755 --- a/keepassxc-browser/background/keepass.js +++ b/keepassxc-browser/background/keepass.js @@ -662,7 +662,7 @@ keepass.passkeysGet = async function(tab, args = []) { const nonce = keepassClient.getNonce(); const [ publicKey, origin ] = args; const passkeyPublicKey = JSON.parse(JSON.stringify(publicKey)); - const relatedOrigins = await keepass.getPasskeysRelatedOrigins(passkeyPublicKey?.rp?.id); + const relatedOrigins = await keepass.getPasskeysRelatedOrigins(passkeyPublicKey?.rpId); const messageData = { action: kpAction, @@ -920,11 +920,30 @@ keepass.getPasskeysRelatedOrigins = async function(rpId) { } try { + let hostname; + try { + hostname = new URL(`https://${rpId}`).hostname; + } catch { } + + if (hostname !== rpId) { + logError(`getRelatedOrigins error: "${rpId}" is wrong rpId`); + return []; + } + const response = await fetch(`https://${rpId}/.well-known/webauthn`, { signal: AbortSignal.timeout(DEFAULT_FETCH_TIMEOUT), + cache: 'no-store', + credentials: 'omit', + referrerPolicy: 'no-referrer', }); // Basic reply validation, see: https://www.w3.org/TR/webauthn-3/#sctn-validating-relation-origin + + if (response.status !== 200) { + logError(`getRelatedOrigins error: HTTP status code is ${response.status}`); + return []; + } + const isJson = response?.headers?.get('content-type')?.includes('application/json'); if (!isJson) { logError('getRelatedOrigins error: Content-Type is not JSON'); diff --git a/keepassxc-browser/content/passkeys-utils.js b/keepassxc-browser/content/passkeys-utils.js index b2854125..8fd21ba0 100644 --- a/keepassxc-browser/content/passkeys-utils.js +++ b/keepassxc-browser/content/passkeys-utils.js @@ -23,7 +23,7 @@ const checkErrors = function(pkOptions, sameOriginWithAncestors) { throw new DOMException('Cross-origin register or authentication is not allowed.', DOMException.NotAllowedError); } - if (pkOptions.challenge.length < 16) { + if (!Number.isSafeInteger(pkOptions.challenge?.byteLength) || pkOptions.challenge.byteLength < 16) { throw new TypeError('challenge is shorter than required minimum length.'); } };