| title | Security: SRI, CSP, CORS |
|---|---|
| description | Pin and verify every remote module — Subresource Integrity, CSP, and CORS guidance. |
Loading code from another origin at runtime is powerful and dangerous. knitkit's headline guidance: pin and verify every remote module's hash.
knitkit build computes a sha384 hash for each shared asset and records it in the manifest:
"shared": {
"react": { "version": "18.3.1", "requiredVersion": "^18.0.0", "singleton": true,
"url": "./shared/react-18.3.1.js", "integrity": "sha384-…" }
}How that hash is enforced depends on the environment:
- Browser, shared deps — the negotiated import map carries the
integritykey, so the browser natively refuses a tampered shared module. Available in Chrome 127 / Firefox 138 / Safari 18.4 (re-verify at ship time). - Node SSR —
@knitkit/nodeverifies the hash itself before executing any fetched remote module. A mismatch throws a codedKNIT_ERR_SRI_MISMATCHand the module never runs. This is covered by tests in the package.
The platform has no integrity option on a dynamic import(). So an exposed module loaded
by loadRemote in the browser is only hash-verified if it goes through an import-map entry
that carries integrity. Options:
- Put exposed modules in the import map with integrity (so the browser enforces it), or
- Rely on
@knitkit/node's server-side verification (which always runs), or - Pin remotes you trust and serve them over HTTPS from an origin you control.
Manifest signing (verifying the manifest itself, not just the assets) is on the roadmap.
A federated page loads modules from one or more remote origins. Your CSP must allow them. A starting point (tighten to your actual origins):
Content-Security-Policy:
default-src 'self';
script-src 'self' https://cdn.example.com; /* remote module origins */
connect-src 'self' https://cdn.example.com; /* fetch() of manifests + modules */
require-trusted-types-for 'script'; /* optional, recommended */
Notes:
- The import map is an inline
<script type="importmap">. Under a strict CSP, allow it with anonce(preferred) rather than'unsafe-inline'. connect-srcmust include every origin youfetcha manifest or module from.- Prefer SRI + a small allowlist of remote origins over broad wildcards.
Cross-origin module fetches and manifest fetches require the remote to send CORS headers — a well-known footgun in older plugin-based setups. The remote's static host must respond with:
Access-Control-Allow-Origin: https://your-host.example.com /* or * for public assets */
for knit.manifest.json, exposed modules, and shared assets. If a remote 404s or omits CORS,
registerRemotes / loadRemote fail with a coded KNIT_ERR_LOAD_FAILED whose suggestion
points at CORS and reachability.
You are executing the remote's code with your page's privileges. Treat every remote origin as
part of your trusted computing base: serve over HTTPS, pin hashes, scope your CSP, and only
federate origins you control or have a contract with. Optional vm/ShadowRealm isolation for
SSR is a roadmap item.