Skip to content

Security headers on IIS and Nginx: HSTS, CSP and the ones that matter

Verified 1 min read

Add HSTS, CSP, nosniff, frame protection and Referrer-Policy with IIS/Nginx, test them, and avoid breaking the app with a copied CSP.

Tested onStandard / Datacenter · Build 26100.33650 · x64
E1
Build
26100.33650
Edition
Standard / Datacenter
Architecture
x64
Support
Documentation (E1)
Evidence
E1Official documentation
Verified
2026-10-29
Page type
Task

Start with headers that rarely break apps:

Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Content-Security-Policy: frame-ancestors 'self'

Add a full CSP only after inventorying scripts/styles/frames. A copied CSP will break the app and get removed.

web.config:

<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Strict-Transport-Security" value="max-age=31536000; includeSubDomains" />
<add name="X-Content-Type-Options" value="nosniff" />
<add name="Referrer-Policy" value="strict-origin-when-cross-origin" />
<add name="Content-Security-Policy" value="frame-ancestors 'self'" />
<remove name="X-Powered-By" />
</customHeaders>
</httpProtocol>
</system.webServer>

IIS may add X-Powered-By; remove it. Do not add HSTS to HTTP responses; browsers ignore it, but it signals a config mistake.

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "frame-ancestors 'self'" always;
server_tokens off;

always applies to error responses too.

  • Only after every name on the host works over HTTPS.
  • includeSubDomains affects all subdomains; be sure.
  • Start with a short max-age in a pilot; raising it is easy, rolling back is slow (browsers cache it).
  • Do not add preload unless you understand the removal process.

Use report-only first:

Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self'; report-uri /csp-report

Then enforce with nonces/hashes for inline scripts. frame-ancestors is the modern replacement for X-Frame-Options; keep XFO only for old clients if needed.

Terminal window
curl.exe -I https://lab.example/
curl.exe -I https://lab.example/assets/app.js

Check headers on HTML, static assets and error pages. A header added only on 200 responses is incomplete.

E1. The lab did not apply these headers or run a CSP report collector; the snippets are the starting point to validate on Server 2025.

Sources