Class: RecipeScrapers::Http::AddressGuard

Inherits:
Faraday::Middleware
  • Object
show all
Defined in:
lib/recipe_scrapers/http/address_guard.rb

Overview

Refuses a request whose host resolves to no address, or to a loopback, private, link-local, multicast, CGNAT or unspecified one, so a URL from a user cannot reach the internal network. It pins the addresses it checked for Adapter, which closes the window where DNS could answer differently the second time. Registered as :recipe_scrapers_address_guard.

Constant Summary collapse

PIN_KEY =

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.

The key of the request context where the guard pins the addresses it checked.

:recipe_scrapers_resolve

Instance Method Summary collapse

Constructor Details

#initialize(app, allow_private: false, resolver: nil) ⇒ AddressGuard

Returns a new instance of AddressGuard.

Parameters:

  • app (#call)
  • allow_private (Boolean) (defaults to: false) —

    let every address through, for development

  • resolver (#call, nil) (defaults to: nil) —

    takes a host and returns IPAddr objects, the system resolver when nil



28
29
30
31
32
# File 'lib/recipe_scrapers/http/address_guard.rb', line 28

def initialize(app, allow_private: false, resolver: nil)
  super(app)
  @allow_private = allow_private
  @resolver = resolver || method(:resolve)
end

Instance Method Details

#on_request(env) ⇒ 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.

Parameters:

  • env (Faraday::Env)

Raises:



38
39
40
41
42
43
44
45
# File 'lib/recipe_scrapers/http/address_guard.rb', line 38

def on_request(env)
  host = env.url.host.to_s
  addresses = @resolver.call(host)
  raise BlockedAddress, "#{host} did not resolve to any address" if addresses.empty?

  addresses.each { |address| check(host, address) }
  pin(env, addresses)
end