{"record":{"id":"e9139e840a28ca17","repo":"angular/angular-cli","slug":"allowing-all-hosts-via-is-a-security-risk-thi","errorCode":null,"errorMessage":"Allowing all hosts via \"*\" is a security risk. This configuration should only be used when validation for \"Host\" and \"X-Forwarded-Host\" headers is performed in another layer, such as a load balancer or reverse proxy. For more information see: https://angular.dev/best-practices/security#preventing-server-side-request-forgery-ssrf","messagePattern":"Allowing all hosts via \"\\*\" is a security risk\\. This configuration should only be used when validation for \"Host\" and \"X-Forwarded-Host\" headers is performed in another layer, such as a load balancer or reverse proxy\\. For more information see: https://angular\\.dev/best-practices/security#preventing-server-side-request-forgery-ssrf","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/angular/ssr/src/app-engine.ts","lineNumber":128,"sourceCode":"   * A cache that holds entry points, keyed by their potential locale string.\n   */\n  private readonly entryPointsCache = new Map<string, Promise<EntryPointExports>>();\n\n  /**\n   * Creates a new instance of the Angular server application engine.\n   * @param options Options for the Angular server application engine.\n   */\n  constructor(options?: AngularAppEngineOptions) {\n    this.allowedHosts = this.getAllowedHosts(options);\n    this.trustProxyHeaders = normalizeTrustProxyHeaders(options?.trustProxyHeaders);\n  }\n\n  private getAllowedHosts(options: AngularAppEngineOptions | undefined): ReadonlySet<string> {\n    const allowedHosts = new Set([...(options?.allowedHosts ?? []), ...this.manifest.allowedHosts]);\n\n    if (allowedHosts.has('*')) {\n      // eslint-disable-next-line no-console\n      console.warn(\n        'Allowing all hosts via \"*\" is a security risk. This configuration should only be used when ' +\n          'validation for \"Host\" and \"X-Forwarded-Host\" headers is performed in another layer, such as a load balancer or reverse proxy. ' +\n          'For more information see: https://angular.dev/best-practices/security#preventing-server-side-request-forgery-ssrf',\n      );\n    }\n\n    return allowedHosts;\n  }\n\n  /**\n   * Handles an incoming HTTP request by serving prerendered content, performing server-side rendering,\n   * or delivering a static file for client-side rendered routes based on the `RenderMode` setting.\n   *\n   * @param request - The HTTP request to handle.\n   * @param requestContext - Optional context for rendering, such as metadata associated with the request.\n   * @returns A promise that resolves to the resulting HTTP response object, or `null` if no matching Angular route is found.\n   *\n   * @remarks A request to `https://www.example.com/page/index.html` will serve or render the Angular route","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/angular/angular-cli/blob/bb72145f9ab45aee29f523236b3a25cd0813a841/packages/angular/ssr/src/app-engine.ts#L110-L146","documentation":"Angular SSR's app engine computes the set of allowed `Host` values for SSRF protection. If `allowedHosts` contains the wildcard `\"*\"`, host validation is effectively disabled, so the engine warns that this is a security risk unless Host/X-Forwarded-Host validation happens in another layer (load balancer, reverse proxy).","triggerScenarios":"Constructing `AngularAppEngine` / starting SSR where either the `AngularAppEngineOptions.allowedHosts` option or the server manifest's `allowedHosts` includes `\"*\"`.","commonSituations":"Copy-pasted dev configs promoted to production, attempts to make a multi-domain deployment work quickly, or `allowedHosts: ['*']` left in `app.config.server.ts` / server bootstrap options.","solutions":["Replace `\"*\"` with the explicit list of hosts your app serves (e.g. `['example.com', 'www.example.com']`).","If `\"*\"` is truly needed, confirm Host/X-Forwarded-Host validation is enforced upstream (load balancer or reverse proxy allowlist) and document it.","Keep dev-only wildcard in a non-production manifest/options branch (e.g. environment-based configuration)."],"exampleFix":"// before\nnew AngularAppEngine({ allowedHosts: ['*'] })\n// after\nnew AngularAppEngine({ allowedHosts: ['example.com', 'www.example.com'] })","handlingStrategy":"validation","validationCode":"// validate allowedHosts before constructing the engine\nconst hosts = [...(options?.allowedHosts ?? []), ...manifest.allowedHosts];\nif (hosts.includes('*')) throw new Error('Remove \"*\" from allowedHosts in production; list explicit hosts.');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never ship `allowedHosts: ['*']` to production; enumerate real hosts.","Enforce Host-header allowlisting at the load balancer/reverse proxy if wildcard is unavoidable.","Add a config test asserting the manifest's allowedHosts has no wildcard."],"tags":["security","ssrf","ssr","configuration"],"backgroundTag":"wildcard-host-allowlist","analyzedSha":"bb72145f9ab45aee29f523236b3a25cd0813a841","analyzedAt":"2026-08-30T02:47:34.745Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}