Skip to content

Add iframe attributes for allow and sandbox configurations before ins… - #395

Open
Albert LI (albertli-msft) wants to merge 1 commit into
microsoft:masterfrom
albertli-msft:dev/albert-msft/msft-fab-iframe-attrs-before-insert
Open

Add iframe attributes for allow and sandbox configurations before ins…#395
Albert LI (albertli-msft) wants to merge 1 commit into
microsoft:masterfrom
albertli-msft:dev/albert-msft/msft-fab-iframe-attrs-before-insert

Conversation

@albertli-msft

@albertli-msft Albert LI (albertli-msft) commented Aug 28, 2026

Copy link
Copy Markdown

Two upstream PRs, in this order. The powerbi-models change must ship and be
consumed before the PowerBI-JavaScript change will typecheck.


PR 1 of 2 — microsoft/powerbi-models

Title: Add iframeAllow / iframeSandbox to IBootstrapEmbedConfiguration

What

Two optional string fields on IBootstrapEmbedConfiguration, inherited by every
embed configuration type:

// Applied before the iframe is inserted; see the note in Embed.setIframe.
iframeAllow?: string;
iframeSandbox?: string;

Why

powerbi-client creates the embed iframe internally, sets src, and appends it to
the container. Consumers therefore have no opportunity to put an allow or
sandbox attribute on the element before it is inserted.

That matters because Chromium snapshots both the sandbox flags and the
permissions-policy container when the frame is inserted. Setting either
attribute after powerbi.embed() returns updates the DOM but has no effect on the
document that loads. Consumers doing this today are silently getting neither the
delegation nor the sandboxing they think they configured.

These fields give powerbi-client a supported way to receive the values in time.
See PR 2 for the consuming change and the real-world failure that motivated it.

Notes

  • No validator changes needed. MultipleFieldsValidator only validates fields it is
    given, so unknown properties are ignored rather than rejected.
  • Purely additive and optional; no behavior change for existing consumers.

PR 2 of 2 — microsoft/PowerBI-JavaScript

Title: Apply iframe allow / sandbox before inserting the frame

What

In Embed.setIframe, before appendChild:

      iframeContent.setAttribute("allowfullscreen", "true");
+
+     // Sandbox flags and the permissions-policy container are snapshotted when the frame is
+     // inserted, so these must be set before appendChild to affect the document that loads.
+     if (this.config.iframeAllow) {
+       iframeContent.setAttribute("allow", this.config.iframeAllow);
+     }
+
+     if (this.config.iframeSandbox) {
+       iframeContent.setAttribute("sandbox", this.config.iframeSandbox);
+     }
+
      const node = this.element;

Why

Chromium 142 shipped Local Network Access. A request from a public origin to an
RFC1918 address is now gated behind a permission that is a policy-controlled feature
with a default allowlist of 'self'. Under Workspace-level Private Link, Fabric
backend hostnames resolve through the privatelink.* zone to a Private Endpoint IP
in 10.0.0.0/8, so ordinary backend calls from an embed iframe are reclassified as
local network requests and blocked:

Access to XMLHttpRequest at 'https://<workspace>.z<N>.w.dailyapi.fabric.microsoft.com/metadata/...'
from origin 'https://daily.powerbi.com' has been blocked by CORS policy:
Permission was denied for this request to access the `local` address space.

(The message arrives on the CORS channel but is not a CORS problem.)

The host must delegate the feature with <iframe allow="local-network-access">.
Consumers can only do that after powerbi.embed() returns, by which point the
frame is already inserted and its policy container already snapshotted. The
attribute is then plainly visible in DevTools while having had no effect — which is
what makes this so hard to diagnose.

Evidence (live Private Link repro, Edge 151):

Check Result
allow attribute present on the iframe in the DOM yes
allowsFeature('local-network-access') in the parent frame true
allowsFeature('local-network-access') in the embed frame false
After forcing re-navigation with iframe.src = iframe.src allowsFeaturetrue, and the backend call succeeds

Re-navigation re-snapshots the container policy from the now-present attribute,
confirming both the mechanism and the fix.

Impact

Not specific to any one embed type — report, dashboard, tile, qna and datahub embed
all share this code path and all have the same Private Link exposure. It also
restores sandbox for consumers who set it post-embed and are currently not
sandboxed at all.

Risk

No behavior change when the fields are unset; both branches are guarded.

Dependencies / open items

  • Requires the powerbi-models version from PR 1.
  • iframeAllow / iframeSandbox will be included in the /report/load postMessage
    payload, since Embed.load() posts the whole config. Harmless, but happy to strip
    them if reviewers prefer.
  • Not yet built or unit-tested locally.

Follow-up (not yet written) — PowerBI-JavaScript-Datahub

Once the above ship, setIframeAttributes can be deleted outright:

config.iframeAllow = 'local-network-access';
if (shouldSandbox) {
  config.iframeSandbox = 'allow-scripts';
}
const datahubEmbed = powerbi.embed(element, config);

Port the same change to the PowerBIClients mirror at
trident/libs/datahub-client-test/src/embed.ts. Note that embed-e2e does not call
embed(), so it will not cover any of this.


References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant