{"record":{"id":"6b782800c0eda56f","repo":"angular/angular-cli","slug":"header-headername-with-value-headervalue-6b7828","errorCode":null,"errorMessage":"Header \"${headerName}\" with value \"${headerValue}\" is not allowed.","messagePattern":"Header \"(.+?)\" with value \"(.+?)\" is not allowed\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/angular/ssr/src/utils/validation.ts","lineNumber":152,"sourceCode":"function verifyHostAllowed(\n  headerName: string,\n  headerValue: string,\n  allowedHosts: ReadonlySet<string>,\n): void {\n  const url = `http://${headerValue}`;\n  if (!URL.canParse(url)) {\n    throw new Error(`Header \"${headerName}\" contains an invalid value and cannot be parsed.`);\n  }\n\n  const { hostname, pathname, search, hash, username, password } = new URL(url);\n  if (pathname !== '/' || search || hash || username || password) {\n    throw new Error(\n      `Header \"${headerName}\" with value \"${headerValue}\" contains characters that are not allowed.`,\n    );\n  }\n\n  if (!isHostAllowed(hostname, allowedHosts)) {\n    throw new Error(`Header \"${headerName}\" with value \"${headerValue}\" is not allowed.`);\n  }\n}\n\n/**\n * Checks if the hostname is allowed.\n * @param hostname - The hostname to check.\n * @param allowedHosts - A set of allowed hostnames.\n * @returns `true` if the hostname is allowed, `false` otherwise.\n */\nfunction isHostAllowed(hostname: string, allowedHosts: ReadonlySet<string>): boolean {\n  if (allowedHosts.has('*') || allowedHosts.has(hostname)) {\n    return true;\n  }\n\n  for (const allowedHost of allowedHosts) {\n    if (!allowedHost.startsWith('*.')) {\n      continue;\n    }","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/angular/angular-cli/blob/bb72145f9ab45aee29f523236b3a25cd0813a841/packages/angular/ssr/src/utils/validation.ts#L134-L170","documentation":"Angular SSR validates the `host` and `x-forwarded-host` headers against an allowlist of trusted hostnames to prevent host header injection attacks (cache poisoning, password-reset poisoning). When `verifyHostAllowed` is called from `validateHeaders` and the hostname is not in `allowedHosts`, the request is rejected with this error naming the header and value.","triggerScenarios":"A request reaches the SSR server whose `host` or `x-forwarded-host` header (or the `forwarded` header's `host` parameter) resolves to a hostname not present in the configured allowedHosts set.","commonSituations":"Accessing a locally served app via 127.0.0.1 or LAN IP while localhost is the only allowed host; deploying behind a proxy/CDN that rewrites the Host header; forgetting to add a staging/custom domain to allowedHosts for SSR (`allowedHosts` / `allowedHostsHeader` server config).","solutions":["Add the offending hostname to the `allowedHosts` list in the Angular SSR server configuration.","Access the app using a hostname that is already allowlisted (e.g. configured custom domain instead of raw IP).","If the host header comes from a trusted proxy, trust/forward it correctly (configure `trustProxyHeaders` and the proxy's X-Forwarded-Host) so validation sees the right value.","If a proxy strips the host, configure the proxy to pass the original Host/X-Forwarded-Host headers."],"exampleFix":"// before\nserverContextConfig = { allowedHosts: ['localhost'] };\n// after\nserverContextConfig = { allowedHosts: ['localhost', 'myapp.example.com'] };","handlingStrategy":"validation","validationCode":"const allowed = new Set(['localhost', 'myapp.example.com']);\nconst host = new URL(request.url).hostname;\nif (!allowed.has(host)) throw new Error(`Refusing request for host \"${host}\"; add it to allowedHosts.`);","typeGuard":null,"tryCatchPattern":"try {\n  await handleRequest(req);\n} catch (e) {\n  if ((e as Error).message.includes('is not allowed')) {\n    res.status(403).end('Host not allowed');\n  } else { throw e; }\n}","preventionTips":["Keep allowedHosts in sync with every domain, IP, and internal hostname that can reach the SSR server.","Test with curl -H 'Host: <each-host>' before deploying.","Configure proxies to forward the original Host/X-Forwarded-Host consistently."],"tags":["angular","ssr","security","host-header","validation"],"backgroundTag":"host-header-not-allowed","analyzedSha":"bb72145f9ab45aee29f523236b3a25cd0813a841","analyzedAt":"2026-08-30T02:47:34.745Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}