mirror of
https://github.com/stripe/stripe-ruby.git
synced 2025-06-12 00:00:31 -04:00
We were previously using a bit of a hack to get a free deep copy implementation through Ruby's marshaling framework. Lint call this out as a security problem though, and rightfully so: when combined with unsanitized user input, unmarshaling can result in very serious security breaches involving arbitrary code execution. This patch removes all uses of marshal/unmarshal in favor of implementing a deep copy method for `StripeObject`. I also reworked some of the constants around what keys are available for `opts`. I'm still not completely happy with the results, but I think it's going to need a slightly larger refactor in order to get somewhere truly good. There is what could be a breaking change for people doing non-standard stuff with the library: the opts that we copy with an object are now whitelisted, so if they were being used to pass around extraneous data, that might not work as expected anymore. But because this is a contract that we never committed to, I don't think I'd bump the major version for change.
56 lines
1.5 KiB
Ruby
56 lines
1.5 KiB
Ruby
module Stripe
|
|
module APIOperations
|
|
module Request
|
|
module ClassMethods
|
|
def request(method, url, params = {}, opts = {})
|
|
warn_on_opts_in_params(params)
|
|
|
|
opts = Util.normalize_opts(opts)
|
|
opts[:client] ||= StripeClient.active_client
|
|
|
|
headers = opts.clone
|
|
api_key = headers.delete(:api_key)
|
|
api_base = headers.delete(:api_base)
|
|
client = headers.delete(:client)
|
|
# Assume all remaining opts must be headers
|
|
|
|
resp, opts[:api_key] = client.execute_request(
|
|
method, url,
|
|
api_base: api_base, api_key: api_key,
|
|
headers: headers, params: params
|
|
)
|
|
|
|
# Hash#select returns an array before 1.9
|
|
opts_to_persist = {}
|
|
opts.each do |k, v|
|
|
opts_to_persist[k] = v if Util::OPTS_KEYS_TO_PERSIST.include?(k)
|
|
end
|
|
|
|
[resp, opts_to_persist]
|
|
end
|
|
|
|
private
|
|
|
|
def warn_on_opts_in_params(params)
|
|
Util::OPTS_USER_SPECIFIED.each do |opt|
|
|
if params.key?(opt)
|
|
$stderr.puts("WARNING: #{opt} should be in opts instead of params.")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def self.included(base)
|
|
base.extend(ClassMethods)
|
|
end
|
|
|
|
protected
|
|
|
|
def request(method, url, params = {}, opts = {})
|
|
opts = @opts.merge(Util.normalize_opts(opts))
|
|
self.class.request(method, url, params, opts)
|
|
end
|
|
end
|
|
end
|
|
end
|