From 4c5d82c94c2e6dbdcf168be5f9262ebaae425ae4 Mon Sep 17 00:00:00 2001 From: Aleksandr Kolbasov Date: Sat, 7 Feb 2026 03:20:24 +0300 Subject: [PATCH 1/2] Passkeys: Permissions Policy support --- keepassxc-browser/content/passkeys-inject.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/keepassxc-browser/content/passkeys-inject.js b/keepassxc-browser/content/passkeys-inject.js index 3ffb1fb..1462fd0 100644 --- a/keepassxc-browser/content/passkeys-inject.js +++ b/keepassxc-browser/content/passkeys-inject.js @@ -63,7 +63,18 @@ const enablePasskeys = async function() { } }; - const isSameOriginWithAncestors = function () { + /** + * @param {'create' | 'get'} action + * @returns {boolean} + */ + const isAllowedByPolicy = function (action) { + // https://www.w3.org/TR/webauthn-2/#sctn-permissions-policy + const policy = document.featurePolicy || document.permissionsPolicy; + if (policy) { + return policy.allowsFeature(`publickey-credentials-${action}`); + } + + // fallback to sameOriginWithAncestors try { return window.origin === window.top.origin; } catch (_err) { @@ -80,14 +91,14 @@ const enablePasskeys = async function() { if (ev.detail.action === 'passkeys_create') { const publicKey = kpxcPasskeysUtils.buildCredentialCreationOptions( ev.detail.publicKey, - isSameOriginWithAncestors(), + isAllowedByPolicy('create'), ); passkeysLogDebug('Passkey request', publicKey); await sendResponse('passkeys_register', publicKey); } else if (ev.detail.action === 'passkeys_get') { const publicKey = kpxcPasskeysUtils.buildCredentialRequestOptions( ev.detail.publicKey, - isSameOriginWithAncestors(), + isAllowedByPolicy('get'), ); passkeysLogDebug('Passkey request', publicKey); await sendResponse('passkeys_get', publicKey); From aea8ac548c1e6521347360bd182d90a17e7c7399 Mon Sep 17 00:00:00 2001 From: Aleksandr Kolbasov Date: Thu, 12 Feb 2026 23:01:11 +0300 Subject: [PATCH 2/2] Add debug logs to `isAllowedByPolicy()` --- keepassxc-browser/content/passkeys-inject.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/keepassxc-browser/content/passkeys-inject.js b/keepassxc-browser/content/passkeys-inject.js index 1462fd0..a43a66f 100644 --- a/keepassxc-browser/content/passkeys-inject.js +++ b/keepassxc-browser/content/passkeys-inject.js @@ -7,7 +7,8 @@ const PASSKEYS_WAIT_FOR_LIFETIMER = 30; // Apply a script to the page for intercepting Passkeys (WebAuthn) requests const enablePasskeys = async function() { const passkeysLogDebug = function(message, extra) { - if (kpxcPasskeysUtils.debugLogging) { + // `global.js` runs at `document_idle` + if (kpxcPasskeysUtils.debugLogging && typeof debugLogMessage === 'function') { debugLogMessage(message, extra); } }; @@ -71,11 +72,13 @@ const enablePasskeys = async function() { // https://www.w3.org/TR/webauthn-2/#sctn-permissions-policy const policy = document.featurePolicy || document.permissionsPolicy; if (policy) { + passkeysLogDebug('Checking Permissions Policy'); return policy.allowsFeature(`publickey-credentials-${action}`); } // fallback to sameOriginWithAncestors try { + passkeysLogDebug('Checking sameOriginWithAncestors'); return window.origin === window.top.origin; } catch (_err) { return false;