Security headers (CSP, HSTS)
Learn to configure Content-Security-Policy, HSTS and X-Content-Type-Options headers.
What does CSP do?
Content-Security-Policy (CSP) tells the browser which sources are allowed to load. default-src 'self' restricts every resource to the same origin; script-src, style-src and img-src give finer control. CSP blocks inline script and style by default; you must add a nonce or hash.
For reporting use the report-uri directive. CSP sharply reduces the impact of XSS; a single missed escape can still block script injection. In production, start small: run report-only first, fix violations, then enforce.
HSTS and X-Content-Type-Options
Strict-Transport-Security (HSTS) tells the browser to connect only over HTTPS; during the max-age window a downgrade attack is blocked. includeSubDomains covers every subdomain; preload asks the browser's built-in list to include the site. It works only over HTTPS.
X-Content-Type-Options: nosniff stops the browser from deviating from the declared MIME type; it closes a MIME sniffing XSS vector on legacy browsers. The two headers are sent together; the header() call must happen before any output.
Exercise Send three security headers
Send three headers with header(): Content-Security-Policy: default-src 'self'; object-src 'none', X-Content-Type-Options: nosniff and Strict-Transport-Security: max-age=31536000; includeSubDomains. Then print the $msg variable with echo.
Show example solution
default-src 'self'; object-src 'none'"); header("X-Content-Type-Options: nosniff"); header("Strict-Transport-Security: max-age=31536000; includeSubDomains");. Define $msg = "headers sent"; and print with echo $msg . "\n";.
Example solution:
<?php
header("Content-Security-Policy: default-src 'self'; object-src 'none'");
header("X-Content-Type-Options: nosniff");
header("Strict-Transport-Security: max-age=31536000; includeSubDomains");
$msg = "headers sent";
echo $msg . "\n";
Test yourself
-
Which header prevents MIME sniffing?
- X-Content-Type-Options: nosniff
- Content-Security-Policy: default-src 'self'
- Strict-Transport-Security: max-age=31536000
- X-Frame-Options: DENY
Show answer
X-Content-Type-Options: nosniff — Correct. X-Content-Type-Options: nosniff blocks MIME sniffing.
-
Match the security headers
- Content-Security-Policy
- Resource restriction
- Strict-Transport-Security
- HTTPS enforcement
- X-Content-Type-Options
- MIME sniffing block
- max-age=31536000
- One year HSTS
-
Send the X-Content-Type-Options header
header("____: nosniff");Show answer
header("X-Content-Type-Options: nosniff");