Class: Rack::Sanitizer

Inherits:
Object
  • Object
show all
Includes:
Sanitizers
Defined in:
lib/rack/sanitizer.rb

Defined Under Namespace

Modules: Sanitizers Classes: SanitizedRackInput

Constant Summary collapse

DEFAULT_STRATEGIES =
{
  replace: lambda do |input|
    input.
      force_encoding(Encoding::ASCII_8BIT).
      encode!(Encoding::UTF_8,
              invalid: :replace,
              undef:   :replace)
    input
  end,
  exception: lambda do |input|
    input.
      force_encoding(Encoding::ASCII_8BIT).
      encode!(Encoding::UTF_8)
    input
  end
}.freeze
URI_FIELDS =
%w(
    SCRIPT_NAME
    REQUEST_PATH REQUEST_URI PATH_INFO
    QUERY_STRING
    HTTP_REFERER
    ORIGINAL_FULLPATH
    ORIGINAL_SCRIPT_NAME
    SERVER_NAME
).freeze
SANITIZABLE_CONTENT_TYPES =
%w(
  text/plain
  application/x-www-form-urlencoded
  application/json
  text/javascript
).freeze
URI_ENCODED_CONTENT_TYPES =
%w(
  application/x-www-form-urlencoded
).freeze

Instance Method Summary collapse

Constructor Details

#initialize(app, options = {}) ⇒ Sanitizer

options Array options Array



10
11
12
13
14
15
# File 'lib/rack/sanitizer.rb', line 10

def initialize(app, options={})
  @app = app
  @strategy = build_strategy(options)
  @sanitizable_content_types = options[:sanitizable_content_types]
  @sanitizable_content_types ||= SANITIZABLE_CONTENT_TYPES + (options[:additional_content_types] || [])
end

Instance Method Details

#call(env) ⇒ Object



17
18
19
20
21
22
23
24
# File 'lib/rack/sanitizer.rb', line 17

def call(env)
  env = sanitize(env)
  begin
    @app.call(env)
  rescue SanitizedRackInput::FailedToReadBody
    return [400, { "Content-Type" => "text/plain" }, ["Bad Request"]]
  end
end

#sanitize(env) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/rack/sanitizer.rb', line 65

def sanitize(env)
  sanitize_rack_input(env)
  sanitize_cookies(env)
  env.each do |key, value|
    if URI_FIELDS.include?(key)
      if value.frozen?
        env[key] = sanitize_uri_encoded_string(value.dup).freeze
      else
        env[key] = sanitize_uri_encoded_string(value)
      end
    elsif key.to_s.start_with?("HTTP_")
      # Just sanitize the headers and leave them in UTF-8. There is
      # no reason to have UTF-8 in headers, but if it's valid, let it be.
      if value.frozen?
        env[key] = sanitize_string(value.dup).freeze
      else
        env[key] = sanitize_string(value)
      end
    end
  end
end