angular/angular-cli · error · Error
Header "forwarded" proto parameter must be either "http" or
Error message
Header "forwarded" proto parameter must be either "http" or "https".
What it means
Angular SSR validates the `forwarded` header's `proto` parameter against `/^https?$/i` when the header is trusted. If the parameter is missing-or-invalid (anything other than http/https, case-insensitive), the request is rejected. This guards against proxy-supplied `forwarded` headers containing malformed or malicious protocol values used for open-redirect or scheme-confusion attacks.
Source
Thrown at packages/angular/ssr/src/utils/validation.ts:209
allowedHosts: ReadonlySet<string>,
disableHostCheck: boolean,
): void {
const headers = request.headers;
for (const headerName of HOST_HEADERS_TO_VALIDATE) {
const headerValue = getFirstHeaderValue(headers.get(headerName));
if (headerValue && !disableHostCheck) {
verifyHostAllowed(headerName, headerValue, allowedHosts);
}
}
const forwarded = headers.get('forwarded');
if (forwarded) {
const forwardedParams = parseForwardedHeader(forwarded);
if (forwardedParams.host && !disableHostCheck) {
verifyHostAllowed('Forwarded "host"', forwardedParams.host, allowedHosts);
}
if (forwardedParams.proto && !VALID_PROTO_REGEX.test(forwardedParams.proto)) {
throw new Error('Header "forwarded" proto parameter must be either "http" or "https".');
}
}
const xForwardedPort = getFirstHeaderValue(headers.get('x-forwarded-port'));
if (xForwardedPort && !VALID_PORT_REGEX.test(xForwardedPort)) {
throw new Error('Header "x-forwarded-port" must be a numeric value.');
}
const xForwardedProto = getFirstHeaderValue(headers.get('x-forwarded-proto'));
if (xForwardedProto && !VALID_PROTO_REGEX.test(xForwardedProto)) {
throw new Error('Header "x-forwarded-proto" must be either "http" or "https".');
}
const xForwardedPrefix = getFirstHeaderValue(headers.get('x-forwarded-prefix'));
if (xForwardedPrefix && !VALID_PREFIX_REGEX.test(xForwardedPrefix)) {
throw new Error(
'Header "x-forwarded-prefix" is invalid. It must start with a "/" and contain ' +
'only alphanumeric characters, hyphens, and underscores, separated by single slashes.',View on GitHub (pinned to bb72145f9a)
Solutions
- Fix the upstream proxy to emit `proto=http` or `proto=https` in its Forwarded header.
- Have the proxy overwrite (not append) client-supplied Forwarded headers.
- Remove `forwarded` from `trustProxyHeaders` if you rely on `x-forwarded-proto` instead.
- In tests, send a valid value like `Forwarded: for=1.2.3.4;host=example.com;proto=https`.
Example fix
// before curl -H 'Forwarded: for=1.2.3.4;proto=HTTP/2' http://localhost:4200/ // after curl -H 'Forwarded: for=1.2.3.4;proto=https' http://localhost:4200/
Defensive patterns
Strategy: validation
Validate before calling
const fwd = request.headers.get('forwarded');
const proto = fwd?.match(/proto=([^;]+)/i)?.[1]?.trim();
if (proto && !/^(http|https)$/i.test(proto)) throw new Error(`Invalid forwarded proto: ${proto}`); Try / catch
try {
validateHeaders(headers, allowedHosts, disableHostCheck);
} catch (e) {
if ((e as Error).message.startsWith('Header "forwarded"')) {
return res.status(400).end('Invalid Forwarded header');
}
throw e;
} Prevention
- Configure the reverse proxy to overwrite, never append, Forwarded headers.
- Only trust `forwarded` from networks you control.
- Include malformed-header cases in integration tests.
When it happens
Trigger: A request carrying a `forwarded` header (e.g. `forwarded: for=1.2.3.4;proto=ftp` or `proto=HTTP/2`, or `proto=` empty) passes through validation while the `forwarded` header is included in `trustProxyHeaders`.
Common situations: A misconfigured reverse proxy emitting non-standard values in the forwarded proto field; manually crafted curl/test requests; a proxy that forwards the raw client-supplied `forwarded` header instead of overwriting it.
Related errors
- Header "x-forwarded-port" must be a numeric value.
- Header "x-forwarded-proto" must be either "http" or "https".
- Header "x-forwarded-prefix" is invalid. It must start with a
- URL with hostname "${hostname}" is not allowed.
- Header "${headerName}" contains an invalid value and cannot
AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30).
Data as JSON: /api/errors/2118a0754438ac54.
Report an issue: GitHub.