The Module Federation Trust Model

Webpack Module Federation enables a shell application (host) to load JavaScript modules from remote applications (remotes) at runtime. The host's webpack.config.js defines remote URLs from which module manifests and chunks are fetched and executed. This happens without any CSP or SRI enforcement by default β€” the loaded code executes immediately in the host's JavaScript context.

From a browser security perspective, this is functionally equivalent to including a third-party <script> tag that points to a domain you do not own. The remote module has the same access to the DOM, the same access to localStorage and sessionStorage, the same access to cookies (without HttpOnly), and the same ability to make fetch calls as any first-party code in the shell. The architectural separation that micro-frontends provide at the team and deployment level does not exist at the browser security level.

Runtime loading is permanent XSS: If a remote host serving a federated module is compromised β€” through a DNS hijacking, a CDN compromise, or a deployment pipeline attack β€” every user of the shell application loads the malicious code for the duration of the compromise. Unlike a stored XSS that requires a user to visit a specific page, a compromised federation remote affects every page that loads the remote module.

Remote Module XSS and Code Execution

The most direct attack on a Module Federation setup is compromising a remote host to serve malicious JavaScript. The attacker's code executes as trusted first-party code in the shell application's origin. From that context, an attacker can: read all cookies accessible to JavaScript (session tokens, CSRF tokens), read localStorage and sessionStorage (auth tokens, user preferences), intercept and modify network requests (credential harvesting from forms), inject additional DOM elements (phishing overlays, fake login forms), and exfiltrate data through WebSocket or fetch channels.

// Module Federation host config β€” remote URL is loaded as trusted code new ModuleFederationPlugin({ name: "host", remotes: { // Everything served from this URL executes as trusted code in the host checkout: "checkout@https://checkout-team.example.com/remoteEntry.js", payments: "payments@https://payments-team.example.com/remoteEntry.js", // If payments-team.example.com is compromised, so is the entire app } });

The attack surface is multiplied by the number of remote hosts. Each additional remote is an additional external dependency whose compromise propagates to the shell application. Large micro-frontend architectures with 10+ remote teams have 10+ potential entry points for this class of attack.

Shared State and Context Poisoning

Module Federation supports sharing libraries between the host and remotes to avoid duplicate code loading β€” React, a state management library, an authentication context. Shared libraries are loaded once and referenced by all modules. This means a malicious remote can interact with the shared state store, the shared authentication context, and the shared event bus β€” not just its own rendered component tree.

An attacker who controls a remote module can read authentication state (user tokens, session data stored in shared React context), dispatch malicious actions to the shared state store (resetting user state, triggering purchases, modifying cart contents), and poison the shared event bus with false events that trigger unintended behaviour in other micro-frontends.

CDN and Hosting Dependency Risks

Remote modules are frequently deployed to CDNs or static hosting services (AWS CloudFront, Cloudflare Pages, Vercel). The security of each remote module depends on the security of its hosting infrastructure. A CDN configuration error that allows unauthorized file replacement, a Vercel project misconfiguration that allows any team member to deploy to a production environment, or an S3 bucket with overly permissive write policies can allow an attacker to replace a remote module's remoteEntry.js without breaking the manifest's format β€” silently serving malicious code to all users of the shell application.

Remote manifest caching: CDNs often cache remote entry manifests aggressively. A compromised remote entry file served from the CDN edge may continue to be served to users for hours after the origin is restored, due to CDN cache TTLs. Plan for cache purging as part of your incident response process for Module Federation compromises.

Content Security Policy Challenges

CSP should restrict which origins can execute JavaScript on your application's origin. But Module Federation fundamentally requires loading scripts from remote origins at runtime β€” which conflicts with a strict CSP. Teams either disable CSP, use overly permissive script-src policies that allow all trusted remote origins, or use 'unsafe-eval' which is required by some Module Federation configurations. Each of these mitigations weakens CSP to the point where it provides limited protection.

Subresource Integrity for federated modules: SRI hashes on <script> tags prevent loading of tampered resources. But Module Federation's dynamic loading mechanism does not use SRI by default. Custom Webpack plugins can add integrity checking to module loading, but this is not standard and requires ongoing hash management as remote modules are updated.

Federation Security Hardening

  1. Treat each remote URL as a third-party dependency: Apply the same scrutiny to remote hosts as you apply to npm packages. Audit the deployment pipeline and access controls for each remote host. A remote team with weak CI security is a weak point in your security model.
  2. Implement integrity verification for remote manifests: Build or adopt a Webpack plugin that validates remote module integrity on load. Generate expected hashes during deployment and verify them client-side before executing federated modules.
  3. Do not share authentication state through federated contexts: Auth tokens and session data should not be accessible to federated remote modules through shared React context or global state. Authenticate each module independently or use a message-passing pattern through a controlled interface.
  4. Apply strict deployment controls to remote hosting: Require branch protection, deployment approval, and deployment audit logs for all remote module hosting environments. Treat deployment to a remote host with the same governance as deployment to the shell application.
  5. Monitor for unexpected remote manifest changes: Implement monitoring that alerts on changes to remote entry manifests outside of known deployment windows. An unexpected manifest change is a strong signal of hosting compromise.
  6. Design micro-frontends with capability minimisation: Do not give remote modules access to APIs, data, or capabilities they do not need. Pass data to remotes through explicit props rather than shared context wherever possible, limiting what a compromised remote can access.