about summary refs log tree commit diff
path: root/app
diff options
context:
space:
mode:
authorAkihiko Odaki <akihiko.odaki.4i@stu.hosei.ac.jp>2018-02-25 03:16:11 +0900
committerEugen Rochko <eugen@zeonfederated.com>2018-02-24 19:16:11 +0100
commit2e8a492e8843aa958c53636b24cf4d344e7ca47d (patch)
treee921f2ad9ecde98d57f7a65ff3d729ff003ec5d4 /app
parent7cb49eaa3aad03b60a1e1620d2f700d6ed2b3ea0 (diff)
Raise Mastodon::HostValidationError when host for HTTP request is private (#6410)
Diffstat (limited to 'app')
-rw-r--r--app/lib/exceptions.rb1
-rw-r--r--app/lib/request.rb19
-rw-r--r--app/lib/sidekiq_error_handler.rb11
3 files changed, 30 insertions, 1 deletions
diff --git a/app/lib/exceptions.rb b/app/lib/exceptions.rb
index b2489711d..95e3365c2 100644
--- a/app/lib/exceptions.rb
+++ b/app/lib/exceptions.rb
@@ -4,6 +4,7 @@ module Mastodon
   class Error < StandardError; end
   class NotPermittedError < Error; end
   class ValidationError < Error; end
+  class HostValidationError < ValidationError; end
   class RaceConditionError < Error; end
 
   class UnexpectedResponseError < Error
diff --git a/app/lib/request.rb b/app/lib/request.rb
index 7671f4ffc..5776b3d78 100644
--- a/app/lib/request.rb
+++ b/app/lib/request.rb
@@ -1,5 +1,8 @@
 # frozen_string_literal: true
 
+require 'ipaddr'
+require 'socket'
+
 class Request
   REQUEST_TARGET = '(request-target)'
 
@@ -8,7 +11,7 @@ class Request
   def initialize(verb, url, **options)
     @verb    = verb
     @url     = Addressable::URI.parse(url).normalize
-    @options = options
+    @options = options.merge(socket_class: Socket)
     @headers = {}
 
     set_common_headers!
@@ -87,4 +90,18 @@ class Request
   def http_client
     HTTP.timeout(:per_operation, timeout).follow(max_hops: 2)
   end
+
+  class Socket < TCPSocket
+    class << self
+      def open(host, *args)
+        address = IPSocket.getaddress(host)
+        raise Mastodon::HostValidationError if PrivateAddressCheck.private_address? IPAddr.new(address)
+        super address, *args
+      end
+
+      alias new open
+    end
+  end
+
+  private_constant :Socket
 end
diff --git a/app/lib/sidekiq_error_handler.rb b/app/lib/sidekiq_error_handler.rb
new file mode 100644
index 000000000..23785cf05
--- /dev/null
+++ b/app/lib/sidekiq_error_handler.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class SidekiqErrorHandler
+  def call(*)
+    yield
+  rescue Mastodon::HostValidationError => e
+    Rails.logger.error "#{e.class}: #{e.message}"
+    Rails.logger.error e.backtrace.join("\n")
+    # Do not retry
+  end
+end