-
Notifications
You must be signed in to change notification settings - Fork 11.9k
CommonEngine: allow dynamic or per-request allowedHosts for multi-tenant apps with custom domains #32910
Description
Which @angular/* package(s) are relevant/related to the feature request?
No response
Description
Angular SSR (CommonEngine / @angular/ssr) validates the request URL hostname against allowedHosts to reduce SSRF risk. Configuration is limited to the CommonEngine constructor, NG_ALLOWED_HOSTS at process startup, and build options in angular.json.
Many multi-tenant products (e.g. storefronts) let each tenant use their own hostname. Those hosts are often unknown at build time and grow over time. A static list is hard to maintain: it ties every new domain to a redeploy, a process restart, or a regenerated environment variable. Wildcard entries only help when all custom domains share a predictable suffix; they do not cover arbitrary customer-owned domains (e.g. customer.com, shop.otherbrand.com.br).
Today, allowedHosts is fixed for the lifetime of the CommonEngine instance, with no supported way to authorize a hostname using per-request logic (for example after resolving the tenant from Host and verifying it with a backend).
Proposed solution
Introduce a supported way to authorize hostnames for SSR in these setups, for example one or more of:
Per-render overrides — allow passing additional allowedHosts (or a merged policy) on render() / equivalent render options so a single engine instance can accept validated hosts without a full process restart.
Documented callback — e.g. (hostname, request) => boolean | Promise with clear security guidance, so the application can implement tenant resolution + backend checks while Angular keeps a safe default when the callback is not used.
Documented proxy-only pattern — if the team considers it valid when Host / X-Forwarded-Host are fully controlled by a trusted reverse proxy, official guidance (and any API hooks needed) would help teams that already terminate TLS and normalize headers at the edge.
The goal is to keep strong defaults for SSRF while not requiring an exhaustive static list of every tenant hostname.
Alternatives considered
Wildcard allowedHosts — works only for domains under a suffix the platform controls; not viable for arbitrary customer CNAMEs.
Large / generated NG_ALLOWED_HOSTS — operational overhead (restarts, deployment pipelines) and does not scale smoothly with self-service custom domains.
Static lists in angular.json or environment files — same limitation: known only at build/deploy time.
Relying on undocumented behavior (e.g. mutating internal allowlist structures) — fragile across Angular versions and not appropriate for production.
None of these fully address multi-tenant SSR where hostname authorization depends on runtime tenant resolution or a backend call.
Thanks for considering this use case.