package

github.com/henrikac/kemal-shield

0.4.0 / published Jul 6, 2021 / repository

A shard that adds an extra layer of protection to Kemal apps by setting various HTTP headers.

kemal-shield

This is a shard that adds an extra layer of protection to your Kemal app. This is done by setting various HTTP headers.

This shard is inspired by Helmet.

Installation

  1. Add the dependency to your shard.yml:

    dependencies:
      kemal-shield:
        github: henrikac/kemal-shield
  2. Run shards install

Usage

Basic usage

require "kemal"
require "kemal-shield"

Kemal::Shield.activate # => adds handlers with their default settings

get "/" do
  "Home"
end

Kemal.run

Managing handlers

Add handlers

The handlers can also be added individually as you would add any other handler. The recommended way of adding handlers is to use Kemal::Shield.add_handler instead of Kemal's built-in add_handler. The reason for using Kemal::Shield.add_handler over Kemal's built-in add_handler is that Kemal::Shield.add_handler keeps track of all Kemal::Shield::Handler. It also makes sure that no dublicate Kemal::Shield::Handler is being added.

Kemal::Shield.add_handler Kemal::Shield::XPoweredBy.new
Kemal::Shield.add_handler Kemal::Shield::XFrameOptions.new("DENY")

A Kemal::Shield::DublicateHandlerError is raised if a dublicate handler is added.

Remove handlers

There are two ways of removing a Kemal::Shield::Handler.

  1. Kemal::Shield.remove_handler if you just need to remove a single handler
  2. Kemal::Shield.deactivate if you want to remove all Kemal::Shield::Handler.
Kemal::Shield.remove_handler Kemal::Shield::ExpectCT

Custom handler

Creating a new handler works just as creating a regular Kemal handler. The only difference is that the new handlers should inherit from Kemal::Shield::Handler instead of Kemal::Handler.

class CustomHandler < Kemal::Shield::Handler
  def call(context)
    # code ...
    call_next context
  end
end

This makes it possible to add handlers using Kemal::Shield.add_handler and/or remove handlers using Kemal::Shield.remove_handler or Kemal::Shield.deactivate.

Configuration

The different headers can be configured in the same way as Kemal:

Kemal::Shield.config do |config|
  config.csp_on = true
  config.hide_powered_by = true
  config.no_sniff = true
  config.referrer_policy = ["no-referrer"]
  config.x_xss_protection = false
end

or

Kemal::Shield.config.hide_powered_by = true

Configuration should be done before calling Kemal::Shield.activate. This is to make sure that the handlers will use the custom configurations.

Kemal::Shield.config.corp = "cross-origin" # => Good: This will be used when calling .activate

Kemal::Shield.activate

Kemal::Shield.config.corp = "same-site" # => Bad: Handlers has already been initialized
OptionDescriptionDefault
csp_onSet Content-Security-Policy headertrue
csp_defaultsAdd CSP default directivestrue
csp_directivesCSP directivesDEFAULT_DIRECTIVES
csp_report_onlySet Content-Security-Policy-Report-Only headerfalse
coep_onSet Cross-Origin-Embedder-Policy headertrue
coop_onSet Cross-Origin-Opener-Policy headertrue
coopCross-Origin-Opener-Policy policy"same-origin"
corp_onSet Cross-Origin-Resource-Policy headertrue
corpCross-Origin-Resource-Policy policy"same-origin"
expect_ctSet Expect-CT headertrue
expect_ct_max_ageSeconds the user agent should regard the host of the received message as a known Expect-CT host0
expect_ct_enforceWhether the user agent should enforce compliance with the Certificate Transparency policyfalse
expect_ct_report_uriThe URI where the user agent should report Expect-CT failures""
hide_powered_byWhether to remove the X-Powered-By headertrue
no_sniffSet X-Content-Type-Options headertrue
oacSet Origin-Agent-Cluster headertrue
referrer_onSet Referrer-Policy headertrue
referrer_policyThe Referrer-Policy policy["no-referrer"]
sts_onSet Strict-Transport-Securitytrue
sts_max_ageSeconds that the browser should remember that a site is only to be accessed using HTTPS15_552_000
sts_include_subAdd rule to subdomainstrue
sts_preloadPreloading STSfalse
x_dns_prefetch_control_onSet X-DNS-Prefetch-Control headertrue
x_dns_prefetch_controlEnable DNS prefetchingfalse
x_download_optionsSet X-Download-Options headertrue
x_frame_options_onSet X-Frame-Optionstrue
x_frame_optionsX-Frame-Options directive"SAMEORIGIN"
x_permitted_cross_domain_policies_onSet X-Permitted-Cross-Domain-Policies headertrue
x_permitted_cross_domain_policiesX-Permitted-Cross-Domain-Policies directivenone
x_xss_protectionEnable X-XSS-Protection headerfalse

ContentSecurityPolicy::DEFAULT_DIRECTIVES:

default-src 'self';
base-uri 'self';
block-all-mixed-content;
font-src 'self' https: data:;
frame-ancestors 'self';
img-src 'self' data:;
object-src 'none';
script-src 'self';
script-src-attr 'none';
style-src 'self' https: 'unsafe-inline';
upgrade-insecure-requests;

Handlers

  • ContentSecurityPolicy
  • CrossOriginEmbedderPolicy
  • CrossOriginOpenerPolicy
  • CrossOriginResourcePolicy
  • ExpectCT
  • OriginAgentCluster
  • ReferrerPolicy
  • StrictTransportSecurity
  • XContentTypeOptions
  • XDNSPrefetchControl
  • XDownloadOptions
  • XFrameOptions
  • XPermittedCrossDomainPolicies
  • XPoweredBy
  • XXSSProtection

Contributing

  1. Fork it (https://github.com/henrikac/kemal-shield/fork)
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors

API