{"record":{"id":"53e3ce44a0b465f4","repo":"angular/angular-cli","slug":"url-with-hostname-hostname-is-not-allowed","errorCode":null,"errorMessage":"URL with hostname \"${hostname}\" is not allowed.","messagePattern":"URL with hostname \"(.+?)\" is not allowed\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/angular/ssr/src/utils/validation.ts","lineNumber":85,"sourceCode":"): void {\n  validateHeaders(request, allowedHosts, disableHostCheck);\n\n  if (!disableHostCheck) {\n    validateUrl(new URL(request.url), allowedHosts);\n  }\n}\n\n/**\n * Validates that the hostname of a given URL is allowed.\n *\n * @param url - The URL object to validate.\n * @param allowedHosts - A set of allowed hostnames.\n * @throws Error if the hostname is not in the allowlist.\n */\nexport function validateUrl(url: URL, allowedHosts: ReadonlySet<string>): void {\n  const { hostname } = url;\n  if (!isHostAllowed(hostname, allowedHosts)) {\n    throw new Error(`URL with hostname \"${hostname}\" is not allowed.`);\n  }\n}\n\n/**\n * Sanitizes the proxy headers of a request by removing unallowed `X-Forwarded-*` headers.\n * If no headers need to be removed, the original request is returned unchanged.\n *\n * @param request - The incoming `Request` object to sanitize.\n * @param trustProxyHeaders - A set of allowed proxy headers.\n * @returns The sanitized request, or the original request if no changes were needed.\n */\nexport function sanitizeRequestHeaders(\n  request: Request,\n  trustProxyHeaders: ReadonlySet<string>,\n): Request {\n  let headersDeleted = false;\n  const headers = new Headers();\n","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/angular/angular-cli/blob/bb72145f9ab45aee29f523236b3a25cd0813a841/packages/angular/ssr/src/utils/validation.ts#L67-L103","documentation":"validateUrl guards the Angular SSR server against host-header attacks / DNS rebinding by checking that the incoming request URL's hostname is in the configured allowed-hosts allowlist. If the hostname is not allowed, the request is rejected rather than rendered.","triggerScenarios":"A request whose URL hostname (or a forwarded-host header resolved by render/validateRequest) is not present in the allowedHosts set — e.g. requesting via an IP address, localhost vs production domain mismatch, or an unexpected Host/X-Forwarded-Host header.","commonSituations":"Accessing the dev/prod server via 127.0.0.1 or an internal hostname while allowedHosts lists only the public domain; adding a custom domain or load balancer without updating the allowlist; CDN/proxy rewriting the Host header; testing behind a tunnel (ngrok) hostname.","solutions":["Add the hostname to the SSR allowedHosts configuration ('allowedHosts' in the server config / angular.json ssr options).","Access the app via an allowlisted hostname instead of an IP or ad-hoc tunnel host.","Check whether a proxy strips or rewrites the Host/X-Forwarded-Host header and configure it to forward the correct host."],"exampleFix":"// before (server config)\nssr: { allowedHosts: ['example.com'] }\n// after\nssr: { allowedHosts: ['example.com', 'www.example.com', 'localhost', '127.0.0.1'] }","handlingStrategy":"validation","validationCode":"const url = new URL(request.url);\nif (!allowedHosts.has(url.hostname)) {\n  return new Response('Forbidden', { status: 403 });\n}\nawait render(request);","typeGuard":"function isHostAllowed(hostname: string, allowedHosts: ReadonlySet<string>): boolean {\n  return allowedHosts.has(hostname.toLowerCase());\n}","tryCatchPattern":"try {\n  await render(request);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('is not allowed.')) {\n    return new Response('Forbidden: host not allowed', { status: 403 });\n  } throw e;\n}","preventionTips":["Keep allowedHosts in sync with every domain, subdomain, and proxy hostname that can reach the server.","Include localhost/127.0.0.1 entries for local development configs.","Ensure reverse proxies forward the real Host header instead of rewriting it.","Log rejected hostnames to spot missing allowlist entries quickly."],"tags":["angular","ssr","security","host-allowlist","host-header"],"backgroundTag":"host-not-allowed","analyzedSha":"bb72145f9ab45aee29f523236b3a25cd0813a841","analyzedAt":"2026-08-30T02:47:34.745Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}