--- checkId: check.security.headers plugin: stellaops.doctor.security severity: warn tags: [security, headers, web] --- # Security Headers ## What It Checks Validates that HTTP security headers are properly configured. The check inspects `Security:Headers:*` and `Headers:*` configuration sections for five critical headers: | Header | Setting | Issue if missing/wrong | |---|---|---| | **HSTS** | `Hsts:Enabled` | Not enabled — browsers won't enforce HTTPS | | **X-Frame-Options** | `XFrameOptions` | Not configured — clickjacking vulnerability | | **X-Frame-Options** | Set to `ALLOWALL` | Provides no protection | | **Content-Security-Policy** | `ContentSecurityPolicy` / `Csp` | Not configured — XSS and injection risks | | **X-Content-Type-Options** | `XContentTypeOptions` | Not enabled — MIME type sniffing vulnerability | | **Referrer-Policy** | `ReferrerPolicy` | Not configured — referrer information leaks | The check reports a warning listing all unconfigured headers. ## Why It Matters Security headers are a defense-in-depth measure that protects against common web attacks: - **HSTS**: Forces browsers to use HTTPS, preventing SSL-stripping attacks. - **X-Frame-Options**: Prevents the UI from being embedded in iframes on malicious sites (clickjacking). - **Content-Security-Policy**: Prevents cross-site scripting (XSS) and other code injection attacks. - **X-Content-Type-Options**: Prevents browsers from interpreting files as a different MIME type. - **Referrer-Policy**: Controls how much referrer information is included with requests, preventing data leaks. ## Common Causes - HSTS not enabled (common in development environments) - X-Frame-Options header not configured or set to ALLOWALL - Content-Security-Policy header not defined - X-Content-Type-Options: nosniff not enabled - Referrer-Policy header not configured - Security headers middleware not added to the ASP.NET Core pipeline ## How to Fix ### Docker Compose Set security headers via environment variables: ```yaml environment: Security__Headers__Hsts__Enabled: "true" Security__Headers__XFrameOptions: "DENY" Security__Headers__ContentSecurityPolicy: "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'" Security__Headers__XContentTypeOptions__Enabled: "true" Security__Headers__ReferrerPolicy: "strict-origin-when-cross-origin" ``` ### Bare Metal / systemd Edit `appsettings.json`: ```json { "Security": { "Headers": { "Hsts": { "Enabled": true }, "XFrameOptions": "DENY", "ContentSecurityPolicy": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'", "XContentTypeOptions": { "Enabled": true }, "ReferrerPolicy": "strict-origin-when-cross-origin" } } } ``` ### Kubernetes / Helm Set in Helm values: ```yaml security: headers: hsts: enabled: true xFrameOptions: "DENY" contentSecurityPolicy: "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'" xContentTypeOptions: enabled: true referrerPolicy: "strict-origin-when-cross-origin" ``` Alternatively, configure at the ingress level: ```yaml ingress: annotations: nginx.ingress.kubernetes.io/configuration-snippet: | add_header X-Frame-Options "DENY" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; ``` ## Verification ``` stella doctor run --check check.security.headers ``` ## Related Checks - `check.security.cors` — CORS headers are another critical web security mechanism - `check.security.tls.certificate` — HSTS requires a valid TLS certificate