It is safe only as far as you trust every team that can publish a remote. Remote JavaScript loaded into a host page runs with the host's full privileges, and a different download origin does not sandbox it. Treat permission to publish a remote as permission to change the running app.
What the problem is
Micro frontends combine independently deployed features in a host application, often called the shell. Separate repositories and separate deployment teams feel like separation. OWASP's Micro Frontend Security Cheat Sheet explains why they are not: the same origin policy separates origins, not individual features within a page.
How each composition choice behaves
| Composition | Security reality |
|---|---|
| Remote JavaScript loaded into the host, including Module Federation | Trust the remote with the host page's privileges. A different download origin does not sandbox executing code |
| Web components in the host page | Part of the same application. Shadow DOM and scoped styles do not isolate their scripts |
| Cross-origin iframe | Separates the feature from the host's DOM and origin storage when capabilities are restricted |
| HTML fragments assembled on a server or at the edge | Review as host content. Assembly before delivery does not create a browser boundary |
If a feature has a lower trust level, such as a partner widget, OWASP recommends serving it from a dedicated origin in an iframe, applying the sandbox attribute and granting only the capabilities it needs. It warns against combining allow-scripts and allow-same-origin for content on the host's own origin, since that can let the embedded app remove its sandbox.
Controls for remotes that run in the host
OWASP lists several, which map neatly to a checklist.
- Load only approved HTTPS remote URLs from host controlled configuration. Never let a query parameter choose executable code.
- Select immutable, reviewed releases, including entry scripts and the chunks they load, and keep a known good release for rollback.
- Separate deployment credentials for the shell and each remote. This limits direct changes to other deployments, but does not contain a compromised remote that is already trusted.
- Use Subresource Integrity where the loader supports it, and verify coverage of dynamically loaded chunks. Checking only an entry script does not verify what it later loads.
- Apply the host's Content Security Policy to remote loading. A permitted source is still trusted code, and CSP does not isolate one allowed micro frontend from another.
Integrity checks detect changed bytes. They do not detect malicious behavior in a release you approved.
Messaging and authorization
For communication between the host and frames, OWASP says to set an exact target origin, match the sender origin exactly, validate message data, and define a small message contract for each pair. It also stresses server side authorization: origin separation does not authorize backend requests, and data you send to a frame is not confidential from that frame. See postMessage has no default access control for the basics.
A decision question
Ask of each remote: if its owner's pipeline were compromised tomorrow, what could it read and do on our page? If the answer is "everything the user can", either move it to a sandboxed cross-origin frame or tighten who can publish.
Quick check
Does a separate repository make a remote a security boundary?
No. Repository and team separation are organizational. In the browser, a remote loaded into the page shares the host's privileges.
Does Subresource Integrity make a remote safe?
It detects changed bytes in a file you pinned. It does not tell you the approved release is benign, and it must cover dynamically loaded chunks too.
Safeguard's dependency scanning and free scan at gold.safeguard.sh/scan help you see the packages that each front-end build pulls in.
Sources
Last reviewed: 19 October 2026.