Background
The HTTP response headers provide huge levels of protection, and it's important that sites deploy them. Below are few benefits of using them:
Prevent malicious content: By defining allowed sources for scripts, images, and other content, security headers can stop attackers from embedding malicious code on a webpage.
Enforce HTTPS: Headers like HTTP Strict Transport Security (HSTS) force browsers to always connect to a website using HTTPS, preventing man-in-the-middle attacks.
Control content embedding: Headers like X-Frame-Options can prevent clickjacking attacks by restricting how a website can be embedded within other websites.
Improve user trust: Implementing security headers demonstrates a commitment to security, building user confidence in a website.
Compliance with standards: Properly configured security headers can help businesses comply with security regulations.
Security Headers Explanations
1. Cache-Control
The Cache-Control header is used to define caching policies for web resources. It determines how and for how long the browser or intermediary caches (like proxies and CDNs) store the resource. Proper use of this header ensures optimized performance and avoids stale or insecure data being served.
Directives
no-store
Prevents the storage of a resource in any cache. no-cache
Forces revalidation of the resource with the server before using it, even if cached. public
Indicates that the resource can be cached by any cache (e.g., browser, proxy). private
Restricts caching to the user's browser only; intermediary caches are prohibited. max-age
Specifies the maximum amount of time (in seconds) a resource is considered fresh. must-revalidate
Ensures the cache must validate the resource with the origin server once it's stale.
2. X-Content-Type-Options
Prevents browsers from interpreting files as a different MIME type than declared. This setting determines whether CloudFront adds the X-Content-Type-Options
header to responses. When this setting is enabled, CloudFront adds the X-Content-Type-Options: nosniff
header to responses. Otherwise, CloudFront doesn't add this header.
Origin override determines how CloudFront behaves when the response from the origin contains this header:
When Origin override is selected and the origin response contains this header, CloudFront adds the header to the response that it sends to viewers according to the settings in the policy. It ignores the header that it received from the origin.
When Origin override isn't selected and the origin response contains this header, CloudFront includes the header that it received from the origin in the response that it sends to the viewer.
When the origin response doesn't contain this header, CloudFront adds the header to the response that it sends to viewers according to the settings in the policy. This is the case if Origin override is selected or not selected.
X-Content-Type-Options: nosniff
Directives
nosniff
Disables MIME-type sniffing and ensures the browser only processes files as the declared MIME type. This ensures the browser doesn’t execute a file as a script unless explicitly declared as such.
3. Content-Security-Policy
This is a Content Security Policy (CSP) directives that defines which sources of content types are trusted and allowed to execute on a webpage.
CSP Evaluator
CSP Evaluator checks are based on a large-scale empirical study and are aimed to help developers to harden their CSP:
https://chromewebstore.google.com/detail/csp-evaluator/fjohamlofnakbnbfjkohkbdigoodcejf?pli=1
https://csp-evaluator.withgoogle.com
Content-Security-Policy-Report-Only: default-src ‘self’ # Will report only.
Content-Security-Policy: default-src ‘self’ # Will block.
Directives
default-src
Specifies the default source for all content types unless overridden by other directives.
script-src
: Specifies allowed sources for JavaScript.
style-src
Specifies allowed sources for CSS.img-src
: Specifies allowed sources for images.connect-src
: Specifies allowed endpoints for network requests (e.g., XHR, WebSocket, fetch).frame-ancestors
: Restricts which URLs can embed the resource using<iframe>
.report-uri
: Defines where violation reports are sent.
4. Strict-Transport-Security (HSTS)
The Strict-Transport-Security header enforces secure (HTTPS) connections to a website. This prevents HTTP-based attacks like man-in-the-middle (MITM) by ensuring all future requests to the domain use HTTPS. It also makes it challenging to revert to HTTP-only traffic temporarily.
Specify the directives and settings for CloudFront to use as the value for the Strict-Transport-Security
response header. For this setting, you can specify the following:
Directives
max-age
Specifies the duration (in seconds) for which the browser should enforce HTTPS. Recommended value is 31536000 (1 year), with a maximum value of 2,147,483,647 (68 year) seconds. This defines the number of seconds CloudFront uses as the value for themax-age
directive.includeSubDomains
Applies the policy to all subdomains of the domain. This ensures any subdomain inherits the HSTS policy, but caution is required as misconfigured subdomains (e.g., legacy systems or test environments) will break under HSTS enforcement. In CloudFront, this determines whether theincludeSubDomains
directive is included in the header's value.preload
Indicates the domain should be included in browsers' preloaded HSTS list. This requires a separate submission to the HSTS preload list. In CloudFront, enabling this includes thepreload
directive in the header's value.
Origin override determines how CloudFront behaves when the response from the origin contains this header:
When Origin override is selected and the origin response contains this header, CloudFront adds the header to the response that it sends to viewers according to the settings in the policy. It ignores the header that it received from the origin.
When Origin override isn't selected and the origin response contains this header, CloudFront includes the header that it received from the origin in the response it sends to the viewer.
When the origin response doesn't contain this header, CloudFront adds the header to the response that it sends to viewers according to the settings in the policy. This is the case if Origin override is selected or not selected.
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
curl -v <http://x.com>
* Host x.com:80 was resolved.
* IPv6: (none)
* IPv4: 10.0.0.0
* Trying 10.0.0.0:80...
* Connected to x.com (10.0.0.0) port 80
> GET / HTTP/1.1
> Host: x.com
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 301 Moved Permanently
< Server: nginx
< Date: Wed, 22 Jan 2025 22:38:25 GMT
< Content-Type: text/html
< Content-Length: 162
< Connection: keep-alive
< Keep-Alive: timeout=20
< Location: <http://x.com/>
< Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
< X-FRAME-OPTIONS: SAMEORIGIN
<
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx</center>
</body>
</html>
* Connection #0 to host x.com left intact
curl -v <http://www.x.com>
* Host x.com:80 was resolved.
* IPv6: (none)
* IPv4: 10.0.0.0
* Trying 10.0.0.0:80...
* Connected to x.com (10.0.0.0) port 80
> GET / HTTP/1.1
> Host: www.x.com
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 301 Moved Permanently
< Server: nginx
< Date: Wed, 22 Jan 2025 22:38:31 GMT
< Content-Type: text/html
< Content-Length: 162
< Connection: keep-alive
< Keep-Alive: timeout=20
< Location: <https://www.x.com/>
< Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
< X-FRAME-OPTIONS: SAMEORIGIN
<
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx</center>
</body>
</html>
* Connection #0 to host www.x.com left intact
https://hstspreload.org/?domain=x.com
5. Referrer-Policy
Controls how much referrer information is shared when navigating to another page. Sensitive information in URLs, such as query strings or paths, is not leaked to third-party sites.
Directives:
strict-origin-when-cross-origin
: Sends the full referrer for same-origin requests, but only the origin for cross-origin requests.
no-referrer
: No Referer
header is sent at all.
no-referrer-when-downgrade
: Full URL is sent to HTTPS destinations but not to HTTP destinations.
origin:
Only the origin (protocol + domain) is sent for all requests.
strict-origin:
The origin is sent unless the request goes from HTTPS to HTTP, in which case no Referer
header is sent.
origin-when-cross-origin
: Full URL is sent for same-origin requests, but only the origin is sent for cross-origin requests.
6. X-XSS-Protection
Protects against reflected XSS attacks. Activates the browser's built-in XSS filter to detect and mitigate reflected XSS attacks.
Directive: enabled; mode=block
— Activates browser’s XSS filter and blocks malicious content from rendering. Detects malicious scripts in the browser's response and takes action (e.g., blocking the page or sanitizing the script). With proper CSP configuration, this header is not very effective. specially in modern browsers.
7. X-Frame-Options
According to Mozilla, this header is being depreciated: For more comprehensive options than offered by this header, see the frame-ancestors
directive in a Content-Security-Policy
header.
Directives
DENY
The page cannot be displayed in a frame, regardless of the site attempting to do so.
SAMEORIGIN
The page can only be displayed if all ancestor frames are same origin to the page itself.
8. Permissions Policy (new)
Permissions Policy is similar to Content Security Policy but controls features instead of security behavior.
Recommendations
When we enable Managed-SecurityHeadersPolicy in Cloudfront Distribution, below security headers are being added to every response:
X-Content-Type-Options:
nosniff
Strict-Transport-Security:
max-age=31536000
include=subdomainsX-Frame-Options some might find useful.
SKIP: X-Frame-Options:
SAMEORIGIN
Added by AWS managed security policy:
SKIP: Referrer-Policy:
strict-origin-when-cross-origin
SKIP: NOT RECOMMENDED: X-XSS-Protection:
1; mode=block
CSP in reporting mode is recommended.
References
https://www.cloudflare.com/learning/cdn/glossary/what-is-cache-control
https://www.feroot.com/education-center/what-is-a-content-security-policy-csp
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers
https://scotthelme.co.uk/content-security-policy-an-introduction
https://www.serpworx.com/check-security-headers/?url=x.com
https://content-security-policy.com
https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html
https://blog.mozilla.org/security/2016/08/26/mitigating-mime-confusion-attacks-in-firefox