Skip to content

Instantly share code, notes, and snippets.

@davidlj95
Last active May 5, 2024 15:48
Show Gist options
  • Save davidlj95/3b516c403b41eb35bacc2227d46dbafc to your computer and use it in GitHub Desktop.
Save davidlj95/3b516c403b41eb35bacc2227d46dbafc to your computer and use it in GitHub Desktop.
HTTP response with all security headers for a CSR/SSR/SSG Angular app - davidlj95.com
HTTP/2 200
date: Sun, 05 May 2024 15:39:06 GMT
content-type: text/html; charset=utf-8
cache-control: public, max-age=0, must-revalidate
report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=ZNcUyO8%2FNm1megeD0GbqGongpd3IiRZ7OizUiPtTDwjeFbtsiQmY%2F0xbwB%2F87Vpm1IK6Oje3JneArNv6fSQad3wC37ZwuqNjIunCyd4nh9p2YX0pLnBTXiM8TafWlw%2Fz"}],"group":"cf-nel","max_age":604800}
nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
vary: Accept-Encoding
cf-cache-status: DYNAMIC
strict-transport-security: max-age=15552000; preload
expect-ct: max-age=86400, enforce
referrer-policy: same-origin
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-xss-protection: 1; mode=block
access-control-allow-origin: https://davidlj95.com
content-security-policy: default-src 'self'; script-src-attr 'unsafe-inline'; style-src 'self' 'unsafe-inline'; media-src 'none'; object-src 'none'; frame-src 'none'; frame-ancestors 'none'; sandbox allow-same-origin allow-scripts allow-popups
permissions-policy: accelerometer=(), autoplay=(), camera=(), cross-origin-isolated=(), display-capture=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), xr-spatial-tracking=(), clipboard-read=(), clipboard-write=(), idle-detection=(), serial=(), window-management=(), window-placement=()
server: cloudflare
cf-ray: 87f1d2426b12063a-CDG
alt-svc: h3=":443"; ma=86400
@davidlj95
Copy link
Author

davidlj95 commented May 5, 2024

HTTP Response with all security headers set

As example of all HTTP security headers that can be set.

This leads to an A+ score on securityheaders.com

Cloudflare's managed security headers

Strict Transport Security

Set by SSL/TLS -> Edge Certificates -> HSTS configuration

Managed transform rule

Cloudflare sets a subset of those thanks to security headers managed transform rule. Just a checkbox to tick and all your HTTP responses now include those :)

Specifically:

  • x-content-type-options: nosniff
  • x-xss-protection: 1; mode=block
  • x-frame-options: SAMEORIGIN
  • referrer-policy: same-origin
  • expect-ct: max-age=86400, enforce

I wouldn't include:

Manually set headers

  • access-control-allow-origin. Set to the domain itself given we don't expect for now that assets are used from other places (and only assets in there for now)
  • content-security-policy. Generated with https://report-uri.com/home/generate . Considering Angular's advice on CSP. With the specific that script-src-attr is used instead of script-src. Given the only use is CSS inlining by Critters. Which uses the onload=this.media='all' trick to load CSS in an async fashion. So no need to set all script-src to unsafe-inline if just script-src-attr is enough. Unused features like media, object, frame and frame-ancestors are disabled. Sandbox one needs allow-same-origin and allow-scripts to load resources and scripts. Though that triggers a warning in Chrome DevTools: An iframe which has both allow-scripts and allow-same-origin for its sandbox attribute can escape its sandboxing.. This N/A for this case as (i)frames have been blocked. allow-popups is to allow mailto: and tel: links. In theory allow-top-navigation-to-custom-protocols should be enough according to MDN but doesn't work with latest Chrome version. Doesn't work either if using allow-top-navigation. Chrome explicitly says allow-popups must be enabled. So leaving it like that.
  • permissions-policy. As not using anything, safe to set everything to disabled. It's a bit long but currently there's no way to set everything to disabled or define a default like in CSP headers (where default would be set to disabled). In other words, no way to turn this into a closed by default policy. Or to be an allow list instead of a deny list. Generated using permissionspolicy.com . However, had to remove some of them as they aren't implemented yet and Chrome DevTools reports issues when a feature specified in that header isn't recognized by the browser. To do so, removed the ones appearing in warnings whilst checking the official list of features and its support. A quirk: window-placement is deprecated, but window-management isn't supported yet. So both need to be included to avoid warnings in Chrome DevTools. If window-management is set without the deprecated placement, the permissions policy header parser complains about not recognizing it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment