Deployments

Host Policy and Proxies

Host policy is a production boundary. Configure it before a public deployment because the Host header influences absolute URLs, redirects, cache keys, metadata routes, auth callbacks, CSP reports, and same-origin security decisions.

What host policy protects

Attackers can send arbitrary Host headers to many public HTTP endpoints. If an app trusts that value when building redirects, canonical URLs, password reset links, OAuth callbacks, or cache keys, the app can generate attacker-controlled origins.

Prefer a strict allow-list in production. Host policy and request scheme trust are separate controls: hostPolicy: "trusted-proxy" does not enable forwarded protocol trust.

Configure strict hosts

Set exact public hosts on the Node server, container process, or adapter. Include every hostname users can legitimately request, and keep staging hosts separate from production hosts.

HOST=0.0.0.0 \
MREACT_ROUTER_HOST_POLICY=strict \
MREACT_ROUTER_ALLOWED_HOSTS=app.example.com,www.example.com \
mreact-router start .mreact
import { startServer } from "@reckona/mreact-router";

await startServer({
  allowedHosts: ["app.example.com", "www.example.com"],
  hostPolicy: "strict",
  hostname: "0.0.0.0",
  outDir: ".mreact",
  port: Number(process.env.PORT ?? 3001),
});

Use hostPolicy: "strict" when your app is directly reachable from the internet or when you want the app server to reject unknown hosts even behind a load balancer.

Use trusted proxy intentionally

Use hostPolicy: "trusted-proxy" only when the platform-provided proxy is the only public entrypoint and it overwrites forwarded host headers. Do not enable it for traffic that can reach the Node server directly.

Node servers ignore X-Forwarded-Proto by default. Enable it separately only when the proxy overwrites the header and the Node port is inaccessible from untrusted networks. Mreact uses the TLS socket when it is secure; otherwise, opt-in mode reads the first forwarded value and treats only https as HTTPS. Missing or malformed values remain HTTP.

MREACT_ROUTER_TRUST_FORWARDED_PROTO=1 mreact-router start .mreact
await startServer({
  allowedHosts: ["app.example.com"],
  hostPolicy: "strict",
  hostname: "0.0.0.0",
  outDir: ".mreact",
  port: Number(process.env.PORT ?? 3001),
  trustForwardedProto: true,
});

This setting affects absolute request URLs and scheme-sensitive response behavior. For example, a configured Strict-Transport-Security header is emitted only when Mreact sees an HTTPS request. Never enable forwarded protocol trust merely to make HSTS appear in a direct HTTP test.

Cloud Run and many managed load balancers terminate TLS before the container. In that shape, the container normally binds HOST=0.0.0.0, receives the platform PORT, and uses a strict allowed host list for the public service URL. Use trusted proxy mode only after verifying how the platform sets forwarded headers.

AWS Lambda adapters receive normalized event data from API Gateway HTTP API v2 or Lambda Function URL payload format 2.0. Keep an allowed host list when the function is exposed through a custom domain, and avoid deriving user-facing origins from unvalidated headers.

Reverse proxy checklist

  • Publish only the reverse proxy or platform endpoint, not the internal Node port.
  • Normalize or overwrite Host, X-Forwarded-Host, X-Forwarded-Proto, and X-Forwarded-Port; remove client-supplied values rather than appending to them.
  • Reject unknown hosts at the edge before requests reach the app when the platform supports it.
  • Keep allowedHosts synchronized with DNS and custom domains.
  • Test redirects, metadata routes, canonical links, auth callbacks, and CSP report URLs through the public hostname.