Restricted Backend Extra Headers
A reference of HTTP headers that are not allowed in backend profiles. These headers are restricted to prevent bypassing virtual host selection and
Overview
The platform's runtime enforces a list of restricted HTTP headers that cannot be set as "extra headers" within a backend profile. This mechanism acts as a security and stability control, ensuring that requests are routed to the correct upstream virtual host as intended by the profile's dedicated hostHeader field.
This restriction prevents an extra header from overriding the Host header or other host-selecting headers, which could bypass the platform's virtual host matching logic and associated credential lookups.
The primary validation for these headers occurs when a backend profile is saved via the Admin API. The runtime check described here serves as a send-time backstop for any profiles that were created before the Admin API validation was implemented. When the runtime detects a restricted header, it drops the header from the outgoing request and logs a warning.
How it works
When the runtime processes a request to a backend service, it inspects each header defined in the corresponding backend profile's "extra headers" list. The RestrictedExtraHeaders.allowed() method determines whether each header can be sent.
The logic follows these steps:
- The header name is checked. If the name is
null, it is allowed (as there is no header to send). - The header name is trimmed of leading and trailing whitespace.
- The trimmed name is checked against two conditions:
- HTTP/2 Pseudo-headers: If the name begins with a colon (
:), it is a restricted pseudo-header. - Restricted List: The name is converted to lower-case (using
Locale.ROOT) and checked against a predefined set of restricted header names.
- HTTP/2 Pseudo-headers: If the name begins with a colon (
- If the header name matches either restriction, the
allowed()method returnsfalse. The runtime drops the header and logs aWARNevent. The header's value is never logged. - If the header is not restricted,
allowed()returnstrue, and the runtime includes the header in the request to the backend.
This process is case-insensitive. For example, Host, host, and HOST are all treated as the same restricted header.
flowchart TD
A[Runtime prepares request to backend] --> B{For each extra header in profile};
B --> C{Is header name restricted?};
C -- No --> D[Include header in request];
C -- Yes --> E[Drop header];
E --> F[Log WARN event: backend_extra_header_dropped];
F --> G[Continue processing other headers];
D --> G;
G --> B;
B -- All headers processed --> H[Send request to backend];Restricted Header Names
The platform will not send any extra header whose name, after trimming whitespace and converting to lower-case, is one of the following.
hostx-forwarded-hostforwardedx-original-hostx-hostx-forwarded-serverx-http-host-override
Additionally, any header name that begins with a colon (:), which denotes an HTTP/2 pseudo-header, is also restricted and will be dropped.
Troubleshooting
Dropped Backend Extra Header
When the runtime drops a restricted header from an outgoing request, it logs a warning message.
- Log Event:
event=backend_extra_header_dropped header=<HEADER_NAME> reason=host_selecting_header fix="remove it from the backend profile's extra headers; use the Host Header field" - Trigger: A backend profile contains a header in its "extra headers" configuration that is on the restricted list. This log is generated at the time a request is sent to that backend.
- Impact: The specified header is removed from the request before it is sent to the upstream service. The request proceeds without it. This may cause unexpected behavior in the backend service if it relies on that header.
- Remediation: As the log message suggests, the API publisher should modify the backend profile to remove the offending header from the "extra headers" list. To control the host for virtual host routing, use the dedicated
Host Headerfield in the backend profile.
NOTE
The log message intentionally redacts any newline (\n) or carriage return (\r) characters from the header name to prevent log injection. The value of the header is never logged.
See Also
- Backend Profile Configuration
- Admin API Reference
