From 032a707184d71533489fb0963d637524eeb086c9 Mon Sep 17 00:00:00 2001 From: bartes Date: Fri, 25 Sep 2020 20:52:06 +0200 Subject: [PATCH] switch to allowlist and denylist --- CHANGELOG.md | 2 ++ README.md | 26 +++++++++++----------- lib/castle/configuration.rb | 18 +++++++-------- lib/castle/extractors/headers.rb | 20 ++++++++--------- spec/lib/castle/configuration_spec.rb | 16 ++++++------- spec/lib/castle/extractors/headers_spec.rb | 22 +++++++++--------- 6 files changed, 53 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f7a0ef1..629333f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## master +- [#203](https://github.com/castle/castle-ruby/pull/203) switch to denylist and allowlist + ## 4.3.0 (2020-05-22) - [#197](https://github.com/castle/castle-ruby/pull/197) add `trusted_proxy_depth` and `trust_proxy_chain` configuration options diff --git a/README.md b/README.md index 7bd4562b..2b7bafc9 100644 --- a/README.md +++ b/README.md @@ -65,26 +65,26 @@ Castle.configure do |config| # Castle::RequestError is raised when timing out in milliseconds (default: 500 milliseconds) config.request_timeout = 2000 - # Whitelisted and Blacklisted headers are case insensitive and allow to use _ and - as a separator, http prefixes are removed - # Whitelisted headers + # Allowlisted and Denylisted headers are case insensitive and allow to use _ and - as a separator, http prefixes are removed + # Allowlisted headers # By default, the SDK sends all HTTP headers, except for Cookie and Authorization. - # If you decide to use a whitelist, the SDK will: + # If you decide to use a allowlist, the SDK will: # - always send the User-Agent header - # - send scrubbed values of non-whitelisted headers - # - send proper values of whitelisted headers. + # - send scrubbed values of non-allowlisted headers + # - send proper values of allowlisted headers. # @example - # config.whitelisted = ['X_HEADER'] + # config.allowlisted = ['X_HEADER'] # # will send { 'User-Agent' => 'Chrome', 'X_HEADER' => 'proper value', 'Any-Other-Header' => true } # - # We highly suggest using blacklist instead of whitelist, so that Castle can use as many data points - # as possible to secure your users. If you want to use the whitelist, this is the minimal + # We highly suggest using denylist instead of allowlist, so that Castle can use as many data points + # as possible to secure your users. If you want to use the allowlist, this is the minimal # amount of headers we recommend: - config.whitelisted = Castle::Configuration::DEFAULT_WHITELIST + config.allowlisted = Castle::Configuration::DEFAULT_ALLOWLIST - # Blacklisted headers take precedence over whitelisted elements - # We always blacklist Cookie and Authentication headers. If you use any other headers that - # might contain sensitive information, you should blacklist them. - config.blacklisted = ['HTTP-X-header'] + # Denylisted headers take precedence over allowlisted elements + # We always denylist Cookie and Authentication headers. If you use any other headers that + # might contain sensitive information, you should denylist them. + config.denylisted = ['HTTP-X-header'] # Castle needs the original IP of the client, not the IP of your proxy or load balancer. # The SDK will only trust the proxy chain as defined in the configuration. diff --git a/lib/castle/configuration.rb b/lib/castle/configuration.rb index 206d78f3..27e5bcf3 100644 --- a/lib/castle/configuration.rb +++ b/lib/castle/configuration.rb @@ -23,9 +23,9 @@ class Configuration \Aunix: /ix].freeze - # @note this value is not assigned as we don't recommend using a whitelist. If you need to use + # @note this value is not assigned as we don't recommend using a allowlist. If you need to use # one, this constant is provided as a good default. - DEFAULT_WHITELIST = %w[ + DEFAULT_ALLOWLIST = %w[ Accept Accept-Charset Accept-Datetime @@ -45,7 +45,7 @@ class Configuration ].freeze attr_accessor :host, :port, :request_timeout, :url_prefix, :trust_proxy_chain - attr_reader :api_secret, :whitelisted, :blacklisted, :failover_strategy, :ip_headers, + attr_reader :api_secret, :allowlisted, :denylisted, :failover_strategy, :ip_headers, :trusted_proxies, :trusted_proxy_depth def initialize @@ -59,8 +59,8 @@ def reset self.host = HOST self.port = PORT self.url_prefix = URL_PREFIX - self.whitelisted = [].freeze - self.blacklisted = [].freeze + self.allowlisted = [].freeze + self.denylisted = [].freeze self.api_secret = ENV.fetch('CASTLE_API_SECRET', '') self.ip_headers = [].freeze self.trusted_proxies = [].freeze @@ -72,12 +72,12 @@ def api_secret=(value) @api_secret = value.to_s end - def whitelisted=(value) - @whitelisted = (value ? value.map { |header| @formatter.call(header) } : []).freeze + def allowlisted=(value) + @allowlisted = (value ? value.map { |header| @formatter.call(header) } : []).freeze end - def blacklisted=(value) - @blacklisted = (value ? value.map { |header| @formatter.call(header) } : []).freeze + def denylisted=(value) + @denylisted = (value ? value.map { |header| @formatter.call(header) } : []).freeze end # sets ip headers diff --git a/lib/castle/extractors/headers.rb b/lib/castle/extractors/headers.rb index d23a190c..a2a6d602 100644 --- a/lib/castle/extractors/headers.rb +++ b/lib/castle/extractors/headers.rb @@ -4,18 +4,18 @@ module Castle module Extractors # used for extraction of cookies and headers from the request class Headers - # Headers that we will never scrub, even if they land on the configuration blacklist. - ALWAYS_WHITELISTED = %w[User-Agent].freeze + # Headers that we will never scrub, even if they land on the configuration denylist. + ALWAYS_ALLOWLISTED = %w[User-Agent].freeze - # Headers that will always be scrubbed, even if whitelisted. - ALWAYS_BLACKLISTED = %w[Cookie Authorization].freeze + # Headers that will always be scrubbed, even if allowlisted. + ALWAYS_DENYLISTED = %w[Cookie Authorization].freeze - private_constant :ALWAYS_WHITELISTED, :ALWAYS_BLACKLISTED + private_constant :ALWAYS_ALLOWLISTED, :ALWAYS_DENYLISTED # @param headers [Hash] def initialize(headers) @headers = headers - @no_whitelist = Castle.config.whitelisted.empty? + @no_allowlist = Castle.config.allowlisted.empty? end # Serialize HTTP headers @@ -33,10 +33,10 @@ def call # @param value [String] # @return [TrueClass | FalseClass | String] def header_value(name, value) - return true if ALWAYS_BLACKLISTED.include?(name) - return value if ALWAYS_WHITELISTED.include?(name) - return true if Castle.config.blacklisted.include?(name) - return value if @no_whitelist || Castle.config.whitelisted.include?(name) + return true if ALWAYS_DENYLISTED.include?(name) + return value if ALWAYS_ALLOWLISTED.include?(name) + return true if Castle.config.denylisted.include?(name) + return value if @no_allowlist || Castle.config.allowlisted.include?(name) true end diff --git a/spec/lib/castle/configuration_spec.rb b/spec/lib/castle/configuration_spec.rb index 36e36927..4ce62464 100644 --- a/spec/lib/castle/configuration_spec.rb +++ b/spec/lib/castle/configuration_spec.rb @@ -89,34 +89,34 @@ end end - describe 'whitelisted' do + describe 'allowlisted' do it do - expect(config.whitelisted.size).to be_eql(0) + expect(config.allowlisted.size).to be_eql(0) end context 'with setter' do before do - config.whitelisted = ['header'] + config.allowlisted = ['header'] end it do - expect(config.whitelisted).to be_eql(['Header']) + expect(config.allowlisted).to be_eql(['Header']) end end end - describe 'blacklisted' do + describe 'denylisted' do it do - expect(config.blacklisted.size).to be_eql(0) + expect(config.denylisted.size).to be_eql(0) end context 'with setter' do before do - config.blacklisted = ['header'] + config.denylisted = ['header'] end it do - expect(config.blacklisted).to be_eql(['Header']) + expect(config.denylisted).to be_eql(['Header']) end end end diff --git a/spec/lib/castle/extractors/headers_spec.rb b/spec/lib/castle/extractors/headers_spec.rb index 0610b636..e8b740ab 100644 --- a/spec/lib/castle/extractors/headers_spec.rb +++ b/spec/lib/castle/extractors/headers_spec.rb @@ -16,11 +16,11 @@ end after do - Castle.config.whitelisted = %w[] - Castle.config.blacklisted = %w[] + Castle.config.allowlisted = %w[] + Castle.config.denylisted = %w[] end - context 'when whitelist is not set in the configuration' do + context 'when allowlist is not set in the configuration' do let(:result) do { 'Accept' => 'application/json', @@ -36,8 +36,8 @@ it { expect(headers).to eq(result) } end - context 'when whitelist is set in the configuration' do - before { Castle.config.whitelisted = %w[Accept OK] } + context 'when allowlist is set in the configuration' do + before { Castle.config.allowlisted = %w[Accept OK] } let(:result) do { @@ -54,7 +54,7 @@ it { expect(headers).to eq(result) } end - context 'when blacklist is set in the configuration' do + context 'when denylist is set in the configuration' do context 'with a User-Agent' do let(:result) do { @@ -68,7 +68,7 @@ } end - before { Castle.config.blacklisted = %w[User-Agent] } + before { Castle.config.denylisted = %w[User-Agent] } it { expect(headers).to eq(result) } end @@ -86,16 +86,16 @@ } end - before { Castle.config.blacklisted = %w[Accept] } + before { Castle.config.denylisted = %w[Accept] } it { expect(headers).to eq(result) } end end - context 'when a header is both whitelisted and blacklisted' do + context 'when a header is both allowlisted and denylisted' do before do - Castle.config.whitelisted = %w[Accept] - Castle.config.blacklisted = %w[Accept] + Castle.config.allowlisted = %w[Accept] + Castle.config.denylisted = %w[Accept] end it do