Three years are about to pass since this site moved to Hugo.
I configured the HTTP security headers for the site, which had been left alone for a while.
They are directives used by web applications to configure security measures in the web browser, and they are used to defend against things like cross-site scripting and clickjacking
This article covers the configuration for the Hugo + Netlify environment that this site uses
Also, I will leave out explanations of the configuration terminology
Configuring it the usual way, such as with .htaccess
Normally, in an environment where .htaccess can be used, such as under Apache, adding settings like the ones below should be enough
This does assume that the mod_headers module is enabled
# Security Headers
Header always set Content-Security-Policy "upgrade-insecure-requests"
Header always set X-XSS-Protection "1; mode=block"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy: "no-referrer-when-downgrade"
Header always set Expect-CT "max-age=7776000, enforce"
Header always append X-Frame-Options "SAMEORIGIN"
Header always set Permissions-Policy "geolocation=(); midi=();notifications=();push=();sync-xhr=();accelerometer=(); gyroscope=(); magnetometer=(); payment=(); camera=(); microphone=();usb=(); xr=();speaker=(self);vibrate=();fullscreen=(self);"
Header always set Strict-Transport-Security: "max-age=31536000"
# End Security Headers
Deliberately putting a blank line on the last line is what matters!
This configuration also takes effect on a WordPress server just by appending it
Note that .htaccess takes effect per directory or through inheritance, so to apply it to the whole system you configure it in httpd.conf on Apache or default.conf on Nginx
Security headers with Hugo + Netlify
Now, in the Hugo and Netlify environment of this site, Netlify cannot use .htaccess, so a bit of ingenuity was needed
_headers
Create the file /static/_headers with the content below
Change the settings to match your own environment
/**
Content-Security-Policy = "upgrade-insecure-requests"
Expect-CT = "max-age=7776000, enforce"
Referrer-Policy = "strict-origin-when-cross-origin"
Strict-Transport-Security = "max-age=31536000"
X-Content-Type-Options = "nosniff"
X-Frame-Options = "SAMEORIGIN"
X-XSS-Protection = "1; mode=block"
Permissions-Policy = "geolocation=(); midi=();notifications=();push=();sync-xhr=();accelerometer=(); gyroscope=(); magnetometer=(); payment=(); camera=(); microphone=();usb=(); xr=();speaker=(self);vibrate=();fullscreen=(self);"netlify.toml
Enter the contents of the _headers above into Netlify Playground
and press the Test rules button; it checks the syntax and shows the Netlify format at the bottom, so add that content to netlify.toml
Add the following to netlify.toml
[[headers]]
for = "/**"
[headers.values]
Content-Security-Policy = "upgrade-insecure-requests"
Expect-CT = "max-age=7776000, enforce"
Permissions-Policy = "geolocation=(); midi=();notifications=();push=();sync-xhr=();accelerometer=(); gyroscope=(); magnetometer=(); payment=(); camera=(); microphone=();usb=(); xr=();speaker=(self);vibrate=();fullscreen=(self);"
Referrer-Policy = "strict-origin-when-cross-origin"
Strict-Transport-Security = "max-age=31536000"
X-Content-Type-Options = "nosniff"
X-Frame-Options = "SAMEORIGIN"
X-XSS-Protection = "1; mode=block"Then, if you have it connected to Gitlab or Github, update the repository and deploy
Checking
It is easy to check on this site
If you are a curl user, curl --head works too

