Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions lib/raven/backports/uri.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# :stopdoc:

# Stolen from ruby core's uri/common.rb, with modifications to support 1.8.x
#
# https://github.com/ruby/ruby/blob/trunk/lib/uri/common.rb
#
#

module URI
TBLENCWWWCOMP_ = {} # :nodoc:
256.times do |i|
TBLENCWWWCOMP_[i.chr] = '%%%02X' % i
end
TBLENCWWWCOMP_[' '] = '+'
TBLENCWWWCOMP_.freeze
TBLDECWWWCOMP_ = {} # :nodoc:
256.times do |i|
h, l = i>>4, i&15
TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr
TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr
TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr
TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr
end
TBLDECWWWCOMP_['+'] = ' '
TBLDECWWWCOMP_.freeze

# Encode given +s+ to URL-encoded form data.
#
# This method doesn't convert *, -, ., 0-9, A-Z, _, a-z, but does convert SP
# (ASCII space) to + and converts others to %XX.
#
# This is an implementation of
# http://www.w3.org/TR/html5/forms.html#url-encoded-form-data
#
# See URI.decode_www_form_component, URI.encode_www_form
def self.encode_www_form_component(s)
str = s.to_s
if RUBY_VERSION < "1.9" && $KCODE =~ /u/i
str.gsub(/([^ a-zA-Z0-9_.-]+)/) do
'%' + $1.unpack('H2' * Rack::Utils.bytesize($1)).join('%').upcase
end.tr(' ', '+')
else
str.gsub(/[^*\-.0-9A-Z_a-z]/) {|m| TBLENCWWWCOMP_[m]}
end
end

# Decode given +str+ of URL-encoded form data.
#
# This decodes + to SP.
#
# See URI.encode_www_form_component, URI.decode_www_form
def self.decode_www_form_component(str, enc=nil)
raise ArgumentError, "invalid %-encoding (#{str})" unless /\A(?:%[0-9a-fA-F]{2}|[^%])*\z/ =~ str
str.gsub(/\+|%[0-9a-fA-F]{2}/) {|m| TBLDECWWWCOMP_[m]}
end

# Generate URL-encoded form data from given +enum+.
#
# This generates application/x-www-form-urlencoded data defined in HTML5
# from given an Enumerable object.
#
# This internally uses URI.encode_www_form_component(str).
#
# This method doesn't convert the encoding of given items, so convert them
# before call this method if you want to send data as other than original
# encoding or mixed encoding data. (Strings which are encoded in an HTML5
# ASCII incompatible encoding are converted to UTF-8.)
#
# This method doesn't handle files. When you send a file, use
# multipart/form-data.
#
# This is an implementation of
# http://www.w3.org/TR/html5/forms.html#url-encoded-form-data
#
# URI.encode_www_form([["q", "ruby"], ["lang", "en"]])
# #=> "q=ruby&lang=en"
# URI.encode_www_form("q" => "ruby", "lang" => "en")
# #=> "q=ruby&lang=en"
# URI.encode_www_form("q" => ["ruby", "perl"], "lang" => "en")
# #=> "q=ruby&q=perl&lang=en"
# URI.encode_www_form([["q", "ruby"], ["q", "perl"], ["lang", "en"]])
# #=> "q=ruby&q=perl&lang=en"
#
# See URI.encode_www_form_component, URI.decode_www_form
def self.encode_www_form(enum)
enum.map do |k,v|
if v.nil?
encode_www_form_component(k)
elsif v.respond_to?(:to_ary)
v.to_ary.map do |w|
str = encode_www_form_component(k)
unless w.nil?
str << '='
str << encode_www_form_component(w)
end
end.join('&')
else
str = encode_www_form_component(k)
str << '='
str << encode_www_form_component(v)
end
end.join('&')
end
end
5 changes: 5 additions & 0 deletions lib/raven/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
require 'raven/processor/removecircularreferences'
require 'raven/processor/utf8conversion'

major, minor, patch = RUBY_VERSION.split('.').map(&:to_i)
if (major == 1 && minor < 9) || (major == 1 && minor == 9 && patch < 2)
require 'raven/backports/uri'
end

module Raven
class << self
# The client object is responsible for delivering formatted data to the Sentry server.
Expand Down
10 changes: 9 additions & 1 deletion lib/raven/processor/sanitizedata.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ def sanitize(k,v)
if v.is_a?(Hash)
process(v)
elsif v.is_a?(Array)
v.map{|a| sanitize(nil, a)}
v.map{|a| sanitize(k, a)}
elsif k == 'query_string'
sanitize_query_string(v)
elsif v.is_a?(String) && (json = parse_json_or_nil(v))
#if this string is actually a json obj, convert and sanitize
json.is_a?(Hash) ? process(json).to_json : v
Expand All @@ -28,6 +30,12 @@ def sanitize(k,v)

private

def sanitize_query_string(query_string)
query_hash = CGI::parse(query_string)
processed_query_hash = process(query_hash)
URI.encode_www_form(processed_query_hash)
end

def fields_re
@fields_re ||= /(#{(DEFAULT_FIELDS + @sanitize_fields).join("|")})/i
end
Expand Down
55 changes: 55 additions & 0 deletions spec/raven/processors/sanitizedata_processor_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,59 @@

expect(result["array"][0]['password']).to eq(Raven::Processor::SanitizeData::STRING_MASK)
end

context "query strings" do
it 'sanitizes' do
data = {
'sentry.interfaces.Http' => {
'data' => {
'query_string' => 'foo=bar&password=secret'
}
}
}

result = @processor.process(data)

vars = result["sentry.interfaces.Http"]["data"]
expect(vars["query_string"]).to_not include("secret")
end

it 'handles multiple values for a key' do
data = {
'sentry.interfaces.Http' => {
'data' => {
'query_string' => 'foo=bar&foo=fubar&foo=barfoo'
}
}
}

result = @processor.process(data)

vars = result["sentry.interfaces.Http"]["data"]
query_string = vars["query_string"].split('&')
expect(query_string).to include("foo=bar")
expect(query_string).to include("foo=fubar")
expect(query_string).to include("foo=barfoo")
end

it 'handles url encoded keys and values' do
encoded_query_string = 'Bio+4%24=cA%24%7C-%7C+M%28%29n3%5E'
data = {
'sentry.interfaces.Http' => {
'data' => {
'query_string' => encoded_query_string
}
}
}

result = @processor.process(data)

vars = result["sentry.interfaces.Http"]["data"]
expect(vars["query_string"]).to eq(encoded_query_string)
end

it 'handles url encoded values' do

end
end
end