What changed, and why it matters
This commit removes code that restricted cross-frame messaging to a specific trusted website origin. It now allows messages from any origin ('*') when sending, and only accepts messages from frames with an 'opaque' (null) origin when receiving. This appears to be a security cleanup that reduces the risk of malicious plugin frames tricking the host into trusting their origin, but the change is partial and the full context is unclear without more references.
Review the plugin manager's iframe sandbox attributes to confirm every plugin/details frame is created without `allow-same-origin`, ensuring the 'null' origin assumption holds. Add regression tests and update documentation describing the security model. Monitor for any follow-up commits that harden or revert this behavior.
Security signals we found
postMessage target origin changed from conditional origin to '*'
Inbound origin check narrowed to 'null' (opaque origin)
Removal of origin-derived trust decision
Sandboxed iframe origin policy change
Evidence from the diff
The patch deletes pluginBuilderOrigin derivation and the usesOpaqueOrigin() helper. Previously, postMessage to plugin frames targeted either ‘’ (for sandboxed/opaque-origin frames) or the plugin directory origin (for non-sandboxed frames), and incoming messages were accepted only from the matching expected origin. After the change, all outbound host-context messages use ‘’ and inbound messages are accepted only when event.origin === 'null'. This enforces that plugin frames must be sandboxed without allow-same-origin (opaque origin) to communicate, eliminating a code path where a non-sandboxed plugin frame could be trusted based on its real origin. However, the patch is small and lacks tests or documentation explaining the threat model, so we cannot fully verify whether all callers now enforce the opaque-origin sandbox.
Changed components
BTCPayServer/wwwroot/plugins/PluginManager/plugins-embed.jsPlugin manager iframe messagingbtcpay:host-context postMessage channelInspect captured patch +2 / −9
diff --git a/BTCPayServer/wwwroot/plugins/PluginManager/plugins-embed.js b/BTCPayServer/wwwroot/plugins/PluginManager/plugins-embed.js
index fc8cdaa..a10157e 100644
--- a/BTCPayServer/wwwroot/plugins/PluginManager/plugins-embed.js
+++ b/BTCPayServer/wwwroot/plugins/PluginManager/plugins-embed.js
@@ -35,7 +35,6 @@
showDirectoryError();
return;
}
- const pluginBuilderOrigin = new URL(pluginDirectoryUrl).origin;
function startDirectory() {
directoryReady = false;
@@ -128,10 +127,6 @@
return detailsFrame?.contentWindow === sourceWindow ? detailsFrame : null;
}
- function usesOpaqueOrigin(frame) {
- return !frame.sandbox.contains("allow-same-origin");
- }
-
function syncSelectedSlugUrl(slug) {
const url = new URL(window.location.href);
if (slug) {
@@ -203,7 +198,7 @@
type: "btcpay:host-context",
hiddenPluginIdentifiers: hiddenPluginIdentifiers,
colorMode: getHostColorMode()
- }, usesOpaqueOrigin(frame) ? "*" : pluginBuilderOrigin);
+ }, "*");
}
function postHostContext() {
@@ -266,9 +261,7 @@
return;
}
- // Frames without allow-same-origin have an opaque origin serialized as "null".
- const expectedOrigin = usesOpaqueOrigin(sourceFrame) ? "null" : pluginBuilderOrigin;
- if (event.origin !== expectedOrigin) {
+ if (event.origin !== "null") {
return;
}
Why this scored 65/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.