Banno plugin frame: host ignores click-link in Garden; sandbox has no allow-popups

Plugin iframe in Garden: click-link, ready and request-resize all unanswered — and the frame sandbox has no allow-popups

We’re building an external-application plugin and testing it in Garden, the developer environment (top frame digital.garden-fi.com). Navigation out of the plugin doesn’t work, and after tracing it we’re stuck on two things we can’t resolve from our side. Hoping someone can confirm expected behavior.

Setup

  • Plugin is an iframed web app served from https://widgets.econocheck.net
  • Navigation uses postUniversalMessage from @jack-henry/banno-plugin-framework-bridge, sending click-link with external: true
  • Reproduced identically in Firefox and Chrome

What we observe

1. The host doesn’t respond to any plugin message.

We verified the message is well-formed and that it actually reaches the top frame — { type: "click-link", data: { href: "...", external: true } }, structured clone intact. Nothing happens: no navigation, no new tab, no popup-blocked indicator in the URL bar, no console warning. Silence.

We then tried three other message types to see whether anything is being consumed. Run from the plugin frame’s console:

// does the host act on any of our messages?
window.parent.postMessage({ type: "ready" }, "*");
window.parent.postMessage({ type: "request-resize", data: { height: 900 } }, "*");
window.parent.postMessage(
  { type: "click-link", data: { href: "https://example.com", external: true } },
  "*"
);
window.parent.postMessage(
  { type: "click-link", data: { href: "https://example.com", external: false } },
  "*"
);

All four dispatch without error. None produce any observable effect — the frame doesn’t resize, nothing navigates. We understand request-resize can legitimately be ignored depending on the plugin surface, but four message types with zero response across two browsers reads like no handler is bound at all.

2. The plugin iframe is sandboxed without allow-popups.

Reading the sandbox off the iframe element from the top frame (needs a shadow-DOM-piercing walk, since the host is a web-component app):

function allIframes(root = document, out = []) {
  root.querySelectorAll("*").forEach(el => {
    if (el.tagName === "IFRAME") out.push(el);
    if (el.shadowRoot) allIframes(el.shadowRoot, out);
  });
  return out;
}
allIframes().forEach(f => console.log(f.src, "| sandbox:", f.sandbox.value));

Result for our plugin frame:

sandbox="allow-top-navigation-by-user-activation allow-scripts allow-forms
         allow-same-origin allow-downloads allow-modals"

No allow-popups. So from inside the frame, window.open throws DOMException: A parameter or an operation is not supported by the underlying object in Firefox and returns null in Chrome, and <a target="_blank"> is inert for the same reason. The same window.open call works from the top frame, so it’s the sandbox, not a browser-level popup block.

We assume this is deliberate — the plugin frame shouldn’t be able to navigate away on its own, which is exactly why click-link exists. That’s fine. The problem is that it makes click-link the only way out, and click-link isn’t being handled here.

This appears to have fixed itself.