{"record":{"id":"caf4ee27bb1f4922","repo":"angular/angular-cli","slug":"received-key-header-but-trustproxyheaders-w","errorCode":null,"errorMessage":"Received \"${key}\" header but \"trustProxyHeaders\" was not set up to allow it.\nFor more information, see https://angular.dev/best-practices/security#configuring-trusted-proxy-headers","messagePattern":"Received \"(.+?)\" header but \"trustProxyHeaders\" was not set up to allow it\\.\nFor more information, see https://angular\\.dev/best-practices/security#configuring-trusted-proxy-headers","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/angular/ssr/src/utils/validation.ts","lineNumber":109,"sourceCode":" * 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\n  for (const [key, value] of request.headers) {\n    const lowerKey = key.toLowerCase();\n    const isProxyHeader = lowerKey === 'forwarded' || lowerKey.startsWith('x-forwarded-');\n    if (isProxyHeader && !isProxyHeaderAllowed(lowerKey, trustProxyHeaders)) {\n      // eslint-disable-next-line no-console\n      console.warn(\n        `Received \"${key}\" header but \"trustProxyHeaders\" was not set up to allow it.\\n` +\n          `For more information, see https://angular.dev/best-practices/security#configuring-trusted-proxy-headers`,\n      );\n      headersDeleted = true;\n    } else {\n      headers.set(key, value);\n    }\n  }\n\n  return headersDeleted\n    ? new Request(request, {\n        headers,\n      })\n    : request;\n}\n\n/**\n * Validates a specific host header value against the allowed hosts.","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/angular/angular-cli/blob/bb72145f9ab45aee29f523236b3a25cd0813a841/packages/angular/ssr/src/utils/validation.ts#L91-L127","documentation":"Angular SSR sanitizes incoming request headers to prevent header-based SSRF/proxy spoofing. `Forwarded` and `X-Forwarded-*` headers are stripped unless `trustProxyHeaders` explicitly allows them; when such a header arrives and is not allowed, it warns and deletes the header from the sanitized request.","triggerScenarios":"A request reaches the SSR server carrying `Forwarded` or `X-Forwarded-*` headers (from a reverse proxy or a malicious client) while the server's `trustProxyHeaders` configuration does not include that specific header key.","commonSituations":"Deploying behind nginx/CloudFront/CDN that injects `X-Forwarded-For`/`X-Forwarded-Host` without configuring `trustProxyHeaders` in the Angular server options; local proxies like Vite dev proxy forwarding hop headers.","solutions":["If the proxy is trusted, explicitly allow the headers in server config, e.g. `trustProxyHeaders: ['x-forwarded-host', 'x-forwarded-proto']`.","If not needed, do nothing — the header is safely stripped; configure the upstream proxy to not forward hop-by-hop headers.","Restrict the allowlist to only headers your app actually consumes (never blanket-allow when clients can reach the server directly)."],"exampleFix":"// before (server bootstrap)\nbootstrapApplication(AppComponent, { ... }) // trustProxyHeaders unset\n// after\nbootstrapApplication(AppComponent, {\n  providers: [provideServerRendering()],\n  // or engine options:\n});\n// with AngularAppEngineOptions:\nnew AngularAppEngine({ trustProxyHeaders: ['x-forwarded-host', 'x-forwarded-proto'] })","handlingStrategy":"validation","validationCode":"// ensure every forwarded header your proxy sends is in the trust list\nconst PROXY_HEADERS = ['forwarded', 'x-forwarded-host', 'x-forwarded-proto', 'x-forwarded-for'];\nconst trusted = new Set(trustProxyHeaders ?? []);\nconst untrusted = PROXY_HEADERS.filter((h) => !trusted.has(h));\nif (untrusted.length && DEPLOYED_BEHIND_PROXY) console.warn('Add to trustProxyHeaders:', untrusted);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Configure `trustProxyHeaders` to match exactly what your reverse proxy sends.","Never blanket-trust proxy headers on servers reachable directly by clients.","Document proxy topology and keep header forwarding minimal (`proxy_set_header` allowlist in nginx)."],"tags":["security","ssr","headers","proxy"],"backgroundTag":"untrusted-proxy-header","analyzedSha":"bb72145f9ab45aee29f523236b3a25cd0813a841","analyzedAt":"2026-08-30T02:47:34.745Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}