A shard that adds an extra layer of protection to Kemal apps by setting various HTTP headers.
MIT License
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.
Add the dependency to your shard.yml
:
dependencies:
kemal-shield:
github: henrikac/kemal-shield
Run shards install
require "kemal"
require "kemal-shield"
Kemal::Shield.activate # => adds handlers with their default settings
get "/" do
"Home"
end
Kemal.run
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.
There are two ways of removing a Kemal::Shield::Handler
.
Kemal::Shield.remove_handler
if you just need to remove a single handlerKemal::Shield.deactivate
if you want to remove all Kemal::Shield::Handler
.Kemal::Shield.remove_handler Kemal::Shield::ExpectCT
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
.
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
Option | Description | Default |
---|---|---|
csp_on | Set Content-Security-Policy header | true |
csp_defaults | Add CSP default directives | true |
csp_directives | CSP directives | DEFAULT_DIRECTIVES |
csp_report_only | Set Content-Security-Policy-Report-Only header | false |
coep_on | Set Cross-Origin-Embedder-Policy header | true |
coop_on | Set Cross-Origin-Opener-Policy header | true |
coop | Cross-Origin-Opener-Policy policy | "same-origin" |
corp_on | Set Cross-Origin-Resource-Policy header | true |
corp | Cross-Origin-Resource-Policy policy | "same-origin" |
expect_ct | Set Expect-CT header | true |
expect_ct_max_age | Seconds the user agent should regard the host of the received message as a known Expect-CT host | 0 |
expect_ct_enforce | Whether the user agent should enforce compliance with the Certificate Transparency policy | false |
expect_ct_report_uri | The URI where the user agent should report Expect-CT failures | "" |
hide_powered_by | Whether to remove the X-Powered-By header | true |
no_sniff | Set X-Content-Type-Options header | true |
oac | Set Origin-Agent-Cluster header | true |
referrer_on | Set Referrer-Policy header | true |
referrer_policy | The Referrer-Policy policy | ["no-referrer"] |
sts_on | Set Strict-Transport-Security | true |
sts_max_age | Seconds that the browser should remember that a site is only to be accessed using HTTPS | 15_552_000 |
sts_include_sub | Add rule to subdomains | true |
sts_preload | Preloading STS | false |
x_dns_prefetch_control_on | Set X-DNS-Prefetch-Control header | true |
x_dns_prefetch_control | Enable DNS prefetching | false |
x_download_options | Set X-Download-Options header | true |
x_frame_options_on | Set X-Frame-Options | true |
x_frame_options | X-Frame-Options directive | "SAMEORIGIN" |
x_permitted_cross_domain_policies_on | Set X-Permitted-Cross-Domain-Policies header | true |
x_permitted_cross_domain_policies | X-Permitted-Cross-Domain-Policies directive | none |
x_xss_protection | Enable X-XSS-Protection header | false |
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;
ContentSecurityPolicy
CrossOriginEmbedderPolicy
CrossOriginOpenerPolicy
CrossOriginResourcePolicy
ExpectCT
OriginAgentCluster
ReferrerPolicy
StrictTransportSecurity
XContentTypeOptions
XDNSPrefetchControl
XDownloadOptions
XFrameOptions
XPermittedCrossDomainPolicies
XPoweredBy
XXSSProtection
git checkout -b my-new-feature
)git commit -am 'Add some feature'
)git push origin my-new-feature
)