Class: Honeybadger::Util::Sanitizer Private

Inherits:
Object
  • Object
show all
Defined in:
lib/honeybadger/util/sanitizer.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Sanitizer sanitizes data for sending to Honeybadger's API. The filters are based on Rails' HTTP parameter filter.

API:

  • private

Constant Summary collapse

/[;,]\s?/
"=".freeze
"; ".freeze
ENCODE_OPTS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

API:

  • private

{invalid: :replace, undef: :replace, replace: "?".freeze}.freeze
BASIC_OBJECT =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

API:

  • private

"#<BasicObject>".freeze
DEPTH =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

API:

  • private

"[DEPTH]".freeze
FILTERED =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

API:

  • private

"[FILTERED]".freeze
RAISED =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

API:

  • private

"[RAISED]".freeze
RECURSION =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

API:

  • private

"[RECURSION]".freeze
TRUNCATED =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

API:

  • private

"[TRUNCATED]".freeze
IMMUTABLE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

API:

  • private

[NilClass, FalseClass, TrueClass, Symbol, Numeric, Method].freeze
MAX_STRING_SIZE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

API:

  • private

65536
VALID_ENCODINGS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

API:

  • private

[Encoding::UTF_8, Encoding::ISO_8859_1].freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(max_depth: 20, filters: []) ⇒ Sanitizer

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of Sanitizer.

API:

  • private



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/honeybadger/util/sanitizer.rb', line 34

def initialize(max_depth: 20, filters: [])
  @filters = !filters.empty?
  @max_depth = max_depth

  strings, @regexps, @blocks = [], [], []

  filters.each do |item|
    case item
    when Proc
      @blocks << item
    when Regexp
      @regexps << item
    else
      strings << Regexp.escape(item.to_s)
    end
  end

  @deep_regexps, @regexps = @regexps.partition { |r| r.to_s.include?('\\.'.freeze) }
  deep_strings, @strings = strings.partition { |s| s.include?('\\.'.freeze) }

  @regexps << Regexp.new(strings.join("|".freeze), true) unless strings.empty?
  @deep_regexps << Regexp.new(deep_strings.join("|".freeze), true) unless deep_strings.empty?
end

Class Method Details

.sanitize(data) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

API:

  • private



29
30
31
32
# File 'lib/honeybadger/util/sanitizer.rb', line 29

def self.sanitize(data)
  @sanitizer ||= new
  @sanitizer.sanitize(data)
end

Instance Method Details

#filter_cookies(raw_cookies) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

API:

  • private



132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/honeybadger/util/sanitizer.rb', line 132

def filter_cookies(raw_cookies)
  return raw_cookies unless filters?

  cookies = []

  raw_cookies.to_s.split(COOKIE_PAIRS).each do |pair|
    name, values = pair.split(COOKIE_SEP, 2)
    values = FILTERED if filter_key?(name)
    cookies << "#{name}=#{values}"
  end

  cookies.join(COOKIE_PAIR_SEP)
end

#filter_url(url) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

API:

  • private



146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/honeybadger/util/sanitizer.rb', line 146

def filter_url(url)
  return url unless filters?

  filtered_url = url.to_s.dup

  filtered_url.scan(/(?:^|&|\?)([^=?&]+)=([^&]+)/).each do |m|
    next unless filter_key?(m[0])
    filtered_url.gsub!(/#{Regexp.escape(m[1])}/, FILTERED)
  end

  filtered_url
end

#sanitize(data, depth = 0, stack = nil, parents = []) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

API:

  • private



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/honeybadger/util/sanitizer.rb', line 58

def sanitize(data, depth = 0, stack = nil, parents = [])
  return BASIC_OBJECT if basic_object?(data)

  if recursive?(data)
    return RECURSION if stack&.include?(data.object_id)

    stack = stack ? stack.dup : Set.new
    stack << data.object_id
  end

  case data
  when Hash
    return DEPTH if depth >= max_depth

    hash = data.to_hash
    new_hash = {}

    hash.each_pair do |key, value|
      parents.push(key) if deep_regexps
      key = key.is_a?(Symbol) ? key : sanitize(key, depth + 1, stack, parents)

      if filter_key?(key, parents)
        new_hash[key] = FILTERED
      else
        value = sanitize(value, depth + 1, stack, parents)

        if blocks.any? && !recursive?(value)
          key = key.dup if can_dup?(key)
          value = value.dup if can_dup?(value)
          blocks.each { |b| b.call(key, value) }
        end

        new_hash[key] = value
      end

      parents.pop if deep_regexps
    end

    new_hash
  when Array, Set
    return DEPTH if depth >= max_depth

    data.to_a.map do |value|
      sanitize(value, depth + 1, stack, parents)
    end
  when Numeric, TrueClass, FalseClass, NilClass
    data
  when String
    sanitize_string(data)
  when ->(d) { d.respond_to?(:to_honeybadger) }
    return DEPTH if depth >= max_depth

    begin
      data = data.to_honeybadger
    rescue
      return RAISED
    end

    sanitize(data, depth + 1, stack, parents)
  else # all other objects
    klass = data.class

    begin
      data = String(data)
    rescue
      return RAISED
    end

    return "#<#{klass.name}>" if inspected?(data)

    sanitize_string(data)
  end
end