Security Headers
The Granit.Http.SecurityHeaders module provides centralized HTTP security response header
management. It suppresses the Kestrel Server header to prevent server fingerprinting
and injects defensive headers on every response per the
OWASP Secure Headers Project.
Included in Bundle.Essentials — active by default for all Granit applications.
Standards
Section titled “Standards”| Standard | Reference |
|---|---|
| OWASP Secure Headers Project | Response header best practices |
| OWASP ASVS V14.4 | HTTP Security Headers |
| ISO 27001 A.8.9 | Configuration management |
| CWE-200 | Information Exposure |
Headers managed
Section titled “Headers managed”| Header | Default value | Purpose |
|---|---|---|
Server | (removed) | Prevent fingerprinting |
X-Content-Type-Options | nosniff | Prevent MIME sniffing |
X-Frame-Options | DENY | Prevent clickjacking |
Strict-Transport-Security | max-age=31536000; includeSubDomains | Force HTTPS (1 year) |
Referrer-Policy | strict-origin-when-cross-origin | Control referrer leakage |
Permissions-Policy | camera=(), microphone=(), geolocation=(), payment=(), accelerometer=(), gyroscope=(), magnetometer=(), usb=() | Restrict browser features |
X-XSS-Protection | 0 | Disable legacy XSS auditor |
Cross-Origin-Opener-Policy | same-origin | Spectre isolation |
Cross-Origin-Resource-Policy | same-origin | Resource sharing control |
Cross-Origin-Embedder-Policy | (not set) | Optional Spectre isolation |
Content-Security-Policy | (not set) | Application-specific |
The module is included in Bundle.Essentials. Add the middleware in Program.cs:
app.UseGranitExceptionHandling(); // 1st — catch errorsapp.UseGranitSecurityHeaders(); // 2nd — headers on ALL responsesapp.UseRouting();app.UseAuthentication();app.UseAuthorization();Configuration
Section titled “Configuration”All headers are configurable via appsettings.json:
{ "SecurityHeaders": { "SuppressServerHeader": true, "EnableContentTypeOptions": true, "XFrameOptions": "DENY", "ReferrerPolicy": "strict-origin-when-cross-origin", "DisableXssProtection": true, "PermissionsPolicy": "camera=(), microphone=(), geolocation=(), payment=(), accelerometer=(), gyroscope=(), magnetometer=(), usb=()", "ContentSecurityPolicy": null, "EnableHsts": true, "HstsMaxAgeSeconds": 31536000, "HstsIncludeSubDomains": true, "HstsPreload": false, "CrossOriginOpenerPolicy": "same-origin", "CrossOriginEmbedderPolicy": null, "CrossOriginResourcePolicy": "same-origin" }}Disabling a header
Section titled “Disabling a header”Set the header value to null or the enable flag to false:
{ "SecurityHeaders": { "XFrameOptions": null, "EnableContentTypeOptions": false }}Content Security Policy
Section titled “Content Security Policy”CSP is highly application-specific and is not set by default. Configure it per application:
{ "SecurityHeaders": { "ContentSecurityPolicy": "default-src 'self'; script-src 'self'" }}The BFF module sets frame-ancestors 'none' on login/callback routes independently.
HSTS preload
Section titled “HSTS preload”To submit your domain to the HSTS Preload List:
{ "SecurityHeaders": { "HstsPreload": true, "HstsIncludeSubDomains": true, "HstsMaxAgeSeconds": 31536000 }}Cross-Origin-Embedder-Policy
Section titled “Cross-Origin-Embedder-Policy”COEP is not set by default because it can break cross-origin resources (fonts,
images, scripts). Enable it only when all cross-origin resources include
Cross-Origin-Resource-Policy:
{ "SecurityHeaders": { "CrossOriginEmbedderPolicy": "require-corp" }}Kestrel-only caveat
Section titled “Kestrel-only caveat”The Server header suppression applies only when the application runs on Kestrel.
When deployed behind a reverse proxy (nginx, Envoy, YARP), the proxy manages its
own Server header. Ensure the proxy is also configured to suppress it.
See also
Section titled “See also”- Security Overview — authentication, authorization, encryption modules
- BFF Security — clickjacking protection on BFF auth endpoints
- HTTP Conventions — CORS, caching, API versioning