Firstly, we check the definitions below.
server | This Server header seems to advertise the software being run on the server but you can remove or change this value. |
---|---|
permissions-policy | Permissions Policy is a new header that allows a site to control which features and APIs can be used in the browser. |
feature-policy | Feature Policy has been renamed to Permissions Policy, see the details here. |
set-cookie | There is no Cookie Prefix on this cookie. |
strict-transport-security | HTTP Strict Transport Security is an excellent feature to support on your site and strengthens your implementation of TLS by getting the User Agent to enforce the use of HTTPS. |
x-frame-options | X-Frame-Options tells the browser whether you want to allow your site to be framed or not. By preventing a browser from framing your site you can defend against attacks like clickjacking. |
x-content-type-options | X-Content-Type-Options stops a browser from trying to MIME-sniff the content type and forces it to stick with the declared content-type. The only valid value for this header is “X-Content-Type-Options: nosniff”. |
x-xss-protection | X-XSS-Protection sets the configuration for the XSS Auditor built into older browsers. The recommended value was “X-XSS-Protection: 1; mode=block” but you should now look at Content Security Policy instead. |
referrer-policy | Referrer Policy is a new header that allows a site to control how much information the browser includes with navigations away from a document and should be set by all sites. |
content-security-policy | Content Security Policy is an effective measure to protect your site from XSS attacks. By whitelisting sources of approved content, you can prevent the browser from loading malicious assets. Analyse this policy in more detail. You can sign up for a free account on Report URI to collect reports about problems on your site. |
I. Permissions-Policy
Permissions Policy is a new header that allows a site to control which features and APIs can be used in the browser.
As we can see above, the feature-policy has been changed to permissions-policy. I’m working on ruby 3.0.0 and rails 7.0.2 and encountered this issue. We easily find in config/initializers/permissions_policy.rb
Rails.application.config.permissions_policy do |f|
f.camera :none
f.gyroscope :none
f.microphone :none
f.usb :none
f.fullscreen :self
f.payment :self, "https://secure.example.com"
end
However, if we check it in https://securityheaders.com it still failed. It’s because rails set Feature-policy instead of permissions-policy. We fix it by adding before_action in ApplicationController.
def set_permission_policy
response.headers["Permissions-Policy"] = response.headers["feature-policy"]
end
II. Strict-Transport-Security
HTTP Strict Transport Security is an excellent feature to support on your site and strengthens your implementation of TLS by getting the User Agent to enforce the use of HTTPS.
config.force_ssl = true
III. X-Frame-Options
X-Frame-Options tells the browser whether you want to allow your site to be framed or not. By preventing a browser from framing your site you can defend against attacks like clickjacking.
Use secure_headers gem and configure as below.
config.x_frame_options = "DENY"
IV. X-Content-Type-Options
X-Content-Type-Options stops a browser from trying to MIME-sniff the content type and forces it to stick with the declared content-type. The only valid value for this header is “X-Content-Type-Options: nosniff”.
config.x_content_type_options = "nosniff"
V. Referrer-Policy
Referrer Policy is a new header that allows a site to control how much information the browser includes with navigations away from a document and should be set by all sites.
config.referrer_policy = "strict-origin-when-cross-origin"
VI. Content-Security-Policy
Content Security Policy is an effective measure to protect your site from XSS attacks. By whitelisting sources of approved content, you can prevent the browser from loading malicious assets. Analyse this policy in more detail. You can sign up for a free account on Report URI to collect reports about problems on your site.
Set as default of secure_headers gem. Recommend to remove “unsafe-inline” which mean removing the script inside html. This is insecured maner.
config.csp = {
# "meta" values. these will shape the header, but the values are not included in the header.
preserve_schemes: true, # default: false. Schemes are removed from host sources to save bytes and discourage mixed content.
disable_nonce_backwards_compatibility: true, # default: false. If false, `unsafe-inline` will be added automatically when using nonces. If true, it won't. See #403 for why you'd want this.
# directive values: these values will directly translate into source directives
default_src: %w('none'),
base_uri: %w('self'),
child_src: %w('self'), # if child-src isn't supported, the value for frame-src will be set.
connect_src: %w(wss:),
font_src: %w('self' data:),
form_action: %w('self' github.com),
frame_ancestors: %w('none'),
img_src: %w(mycdn.com data:),
manifest_src: %w('self'),
media_src: %w(utoob.com),
object_src: %w('self'),
sandbox: true, # true and [] will set a maximally restrictive setting
plugin_types: %w(application/x-shockwave-flash),
script_src: %w('self'),
script_src_elem: %w('self'),
script_src_attr: %w('self'),
style_src: %w('unsafe-inline'),
style_src_elem: %w('unsafe-inline'),
style_src_attr: %w('unsafe-inline'),
worker_src: %w('self'),
upgrade_insecure_requests: true, # see https://www.w3.org/TR/upgrade-insecure-requests/
report_uri: %w(https://report-uri.io/example-csp)
}
VII. CORS
Should control Origin and disable OPTIONS method if not using frontend framework.
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins /https?:\/\/.*\.youdomain\.com\.sg/
resource '*', headers: :any, methods: [:get, :post, :patch, :put],
expose: ['Access-Control-Allow-Origin']
end
end
Bonus
I found an issue that I can’t access back link after clicking link in email. I navigated to login page but after logged in, it went to home page instead of back link in email. The reason is that cookie_store we set. If no mention about same_site, it’s default “Strict”.
SameSite=Lax: Allows cookies in top-level navigations but blocks them in third-party contexts, which is generally a secure default.
SameSite=Strict: Completely blocks cookies in any cross-site context, even for top-level navigations.
SameSite=None: Allows cookies in cross-site contexts but requires Secure to be set as well, meaning the site must use HTTPS.
We clarify the same_site as lax to allow this feature.
config.session_store :cookie_store, key: '_your_app_session', same_site: :lax