Runtime Response Security Headers
Learn how the runtime adds security headers like X-Content-Type-Options and a restrictive Content-Security-Policy to all API responses to mitigate risks.
Overview
The ResponseSecurityHeadersFilter is a servlet filter that automatically adds security-related HTTP headers to every response generated by the API runtime. Its primary purpose is to mitigate security vulnerabilities that could arise if a backend service returns an HTML response (e.g., an error page) that is then rendered by a browser in the context of a privileged user session, such as an administrator's.
This filter runs for every request and has the highest execution precedence, ensuring that its security headers are applied to all responses, including early rejections from other filters and container-generated error pages. It adds two key headers: X-Content-Type-Options and Content-Security-Policy.
By applying a strict, sandboxing Content Security Policy, the filter neutralizes potentially malicious active content (like JavaScript) without modifying the response body or the Content-Type header from the backend. This preserves the byte-fidelity contract of the API gateway while hardening the platform against cross-site scripting (XSS) and other content injection attacks.
How It Works
The ResponseSecurityHeadersFilter is implemented as a Spring OncePerRequestFilter and is registered to run first in the servlet filter chain for every incoming request.
The process for each request is as follows:
- The
ResponseSecurityHeadersFilterintercepts the request before any other application logic. - It immediately adds the
X-Content-Type-OptionsandContent-Security-Policyheaders to theHttpServletResponse. - It then wraps the
HttpServletResponseobject with an internalSecurityHeadersGuardwrapper. - Finally, it passes the request and the wrapped response to the next filter in the chain.
The SecurityHeadersGuard wrapper is critical to the filter's function. It prevents any downstream component—such as the gateway handler relaying headers from a backend SOAP service—from overriding or duplicating the security headers set by this filter.
- The wrapper intercepts calls to
setHeader()andaddHeader(). If the header name matchesX-Content-Type-OptionsorContent-Security-Policy(case-insensitively), the call is silently ignored. - The wrapper also intercepts calls to
reset(). If the response is reset, the wrapper first calls the underlyingreset()method and then immediately re-applies the two security headers to the cleared response.
This mechanism guarantees that every response, whether successful or an error, leaves the runtime with these specific security policies enforced.
sequenceDiagram
participant C as API Consumer
participant F as ResponseSecurityHeadersFilter
participant G as SecurityHeadersGuard Wrapper
participant D as Downstream Filters & Handlers
C->>F: HTTP Request
activate F
F->>G: Creates wrapper for response
Note over F,G: Sets initial security headers
F->>G: setHeader("X-Content-Type-Options", "nosniff")
F->>G: setHeader("Content-Security-Policy", "...")
F->>D: Forwards request with wrapped response
activate D
Note over D: Logic attempts to set a<br/>conflicting backend header
D->>G: setHeader("Content-Security-Policy", "backend-policy")
activate G
Note over G: Ignores request to<br/>overwrite owned header
deactivate G
D-->>F: Returns
deactivate D
F-->>C: HTTP Response with<br/>guaranteed security headers
deactivate FIMPORTANT
This filter is also configured to apply to error dispatches. This ensures that container-generated error pages (e.g., for a 404 or 500 error that occurs before the application can write a response) are also protected by these security headers.
Response Headers
The filter adds the following two HTTP headers to all runtime responses. These headers are not externally configurable.
| Header Name | Value | Description |
|---|---|---|
X-Content-Type-Options | nosniff | Instructs browsers not to perform MIME-type sniffing. This forces the browser to adhere to the Content-Type header provided by the server, preventing it from misinterpreting a response as renderable HTML or script. |
Content-Security-Policy | default-src 'none'; frame-ancestors 'none'; sandbox | Applies a strict Content Security Policy with three directives:<ul><li>default-src 'none': Blocks the loading of any sub-resources (scripts, stylesheets, images, etc.).</li><li>frame-ancestors 'none': Prevents the response from being embedded in a <frame>, <iframe>, <embed>, or <object>, mitigating clickjacking attacks.</li><li>sandbox: Renders the content in a sandboxed environment, disabling scripts, form submissions, plugins, and other potentially dangerous capabilities.</li></ul> |
Example Headers
An API consumer will see these headers on every response from the runtime, including both successful API calls and error pages.
HTTP/1.1 200 OK
Content-Type: application/json
Content-Security-Policy: default-src 'none'; frame-ancestors 'none'; sandbox
X-Content-Type-Options: nosniff
...
{
"data": "..."
}
Troubleshooting
Backend Headers Are Not Propagated
If a backend service returns its own X-Content-Type-Options or Content-Security-Policy header, it will be dropped by the SecurityHeadersGuard wrapper. The platform intentionally enforces its own uniform, strict policy for these headers on all runtime responses. This behavior is by design and cannot be overridden. If you are an API publisher, do not rely on the runtime to propagate custom CSP or X-Content-Type-Options headers from your backend services to the API consumer.
See Also
- The
TenantContextFilter, which is another security-related filter that runs immediately afterResponseSecurityHeadersFilter. - The Gateway SOAP Handler, which relays responses from backend services and whose relayed headers are subject to the policies enforced by this filter.
