{"record":{"id":"9aa52921cd1ab21f","repo":"angular/angular-cli","slug":"header-headername-contains-an-invalid-value-a","errorCode":null,"errorMessage":"Header \"${headerName}\" contains an invalid value and cannot be parsed.","messagePattern":"Header \"(.+?)\" contains an invalid value and cannot be parsed\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/angular/ssr/src/utils/validation.ts","lineNumber":141,"sourceCode":"    : request;\n}\n\n/**\n * Validates a specific host header value against the allowed hosts.\n *\n * @param headerName - The name of the header to validate (e.g., 'host', 'x-forwarded-host').\n * @param headerValue - The value of the header to validate.\n * @param allowedHosts - A set of allowed hostnames.\n * @throws Error if the header value is invalid or the hostname is not in the allowlist.\n */\nfunction 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.","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/angular/angular-cli/blob/bb72145f9ab45aee29f523236b3a25cd0813a841/packages/angular/ssr/src/utils/validation.ts#L123-L159","documentation":"verifyHostAllowed interprets a forwarded-host header value (e.g. X-Forwarded-Host) by parsing it as 'http://<value>'. If the value cannot be parsed as a URL at all (it contains characters illegal in a hostname), it throws instead of trusting it. This prevents malformed header injection from reaching host validation.","triggerScenarios":"A client sends a Host-related header such as X-Forwarded-Host containing characters that make 'http://<value>' unparseable — e.g. spaces, control characters, multiple comma-joined values with junk, or '@'/'%' sequences that break URL parsing.","commonSituations":"Malicious or buggy proxies appending junk to X-Forwarded-Host; clients sending a full URL (including scheme) in the header; fuzzing/scanning traffic hitting a public SSR endpoint.","solutions":["Find the client/proxy sending the malformed header and fix or drop it (configure the proxy to sanitize X-Forwarded-Host).","Send only a bare hostname (no scheme, no path) in X-Forwarded-Host.","If the header is not needed, remove it at the reverse proxy so validateHeaders sees a clean request."],"exampleFix":"// before (client request)\nfetch(url, { headers: { 'X-Forwarded-Host': 'https://example.com' } });\n// after\nfetch(url, { headers: { 'X-Forwarded-Host': 'example.com' } });","handlingStrategy":"validation","validationCode":"const fwh = request.headers.get('x-forwarded-host');\nif (fwh && !URL.canParse(`http://${fwh}`)) {\n  return new Response('Bad Request', { status: 400 });\n}","typeGuard":"function isParsableHostHeader(value: string): boolean {\n  return URL.canParse(`http://${value}`);\n}","tryCatchPattern":"try {\n  await render(request);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('cannot be parsed.')) {\n    return new Response('Bad Request: malformed host header', { status: 400 });\n  } throw e;\n}","preventionTips":["Send only bare hostnames (no scheme, path, or credentials) in X-Forwarded-Host.","Sanitize or strip forwarded headers at the edge proxy before they reach the SSR server.","Only trust X-Forwarded-* from known proxy IPs; drop them from external clients."],"tags":["angular","ssr","security","http-headers","url-parsing"],"backgroundTag":"malformed-forwarded-header","analyzedSha":"bb72145f9ab45aee29f523236b3a25cd0813a841","analyzedAt":"2026-08-30T02:47:34.745Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}