Class: CC::Service::SafeWebhook
- Inherits:
-
Object
- Object
- CC::Service::SafeWebhook
- Defined in:
- lib/cc/service/safe_webhook.rb
Constant Summary collapse
- InvalidWebhookURL =
Class.new(StandardError)
- PRIVATE_ADDRESS_SUBNETS =
[ IPAddr.new("10.0.0.0/8"), IPAddr.new("172.16.0.0/12"), IPAddr.new("192.168.0.0/16"), IPAddr.new("fd00::/8"), IPAddr.new("127.0.0.1"), IPAddr.new("0:0:0:0:0:0:0:1"), ].freeze
Class Method Summary collapse
Instance Method Summary collapse
-
#initialize(url) ⇒ SafeWebhook
constructor
A new instance of SafeWebhook.
-
#validate!(request) ⇒ Object
Resolve the Host to an IP address, validate that it doesn’t point to anything internal, then alter the request to be for the IP directly with an explicit Host header given.
Constructor Details
#initialize(url) ⇒ SafeWebhook
Returns a new instance of SafeWebhook.
25 26 27 |
# File 'lib/cc/service/safe_webhook.rb', line 25 def initialize(url) @url = url end |
Class Method Details
.getaddress(host) ⇒ Object
20 21 22 23 |
# File 'lib/cc/service/safe_webhook.rb', line 20 def self.getaddress(host) @resolv ||= Resolv::DNS.new @resolv.getaddress(host).to_s end |
Instance Method Details
#validate!(request) ⇒ Object
Resolve the Host to an IP address, validate that it doesn’t point to anything internal, then alter the request to be for the IP directly with an explicit Host header given.
See blog.fanout.io/2014/01/27/how-to-safely-invoke-webhooks/#ip-address-blacklisting
34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/cc/service/safe_webhook.rb', line 34 def validate!(request) uri = URI.parse(url) address = self.class.getaddress(uri.host) if internal?(address) raise_invalid("resolves to a private IP address") end alter_request(request, uri, address) rescue URI::InvalidURIError, Resolv::ResolvError, Resolv::ResolvTimeout => ex raise_invalid(ex.) end |