open_graph_fetcher 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 46670fff3dd827c35482bd63b1c246aa876fd85f82b3fdff752144e4f07e537b
4
- data.tar.gz: a260be55faeb2038d4aeacfa9d419a1b7301ec023d327eb51fc2d5a1992ff260
3
+ metadata.gz: 0c8d1c67970ce91969c7caa437fba256fc1527f46006a10b8576bcd2f52fc774
4
+ data.tar.gz: 8e994a0fd3b384367c42ab93b73bd9185fa506e1f2af6a702a125bc26314b2a6
5
5
  SHA512:
6
- metadata.gz: f23ee76f381d04b9fcc1bb60eb2f1baf4a438647009987a072f7a23334008a18614f11bb9a9cf74065e5deb695f65a3d8bed786ea2e6f32137c61a4c14a4ae06
7
- data.tar.gz: 005b86f83da1f16ce55998bcefc1bceb93c0e0137bccab08e72ad1da2e749077fe2a0f5e85cd0bbf6abc005181cb16c2abab01adc1e2fa623344146743d198a7
6
+ metadata.gz: b6d51a0157d6b3088a8f6a8f4bb31243736300fc6bc891ecaafb6b4aa2907236b0b1e45f4e1a22c40c935a4287e3b9ada4509e40c37bbef466c1ce9ae5da2cbe
7
+ data.tar.gz: 678eab6e764a9ad9fc85c8e09a5b5918409f88a5fc293022c9fa847e3283bd0bc90a37700dd87c36d474566ce13047e7b57a1d8524e635b3ad54952d659ab7bb
data/README.md CHANGED
@@ -3,10 +3,11 @@
3
3
  Fetch Open Graph metadata in a safer way.
4
4
 
5
5
  - Includes some mitigations for SSRF attacks
6
- - Blocks private and local IP ranges
6
+ - Blocks the direct usage of IP addresses in URLs
7
+ - Blocks private and local IP ranges (after DNS resolution)
7
8
  - Avoids TOC/TOU when connecting to the IP
8
9
  - Supports only HTTPS on the standard port (443)
9
- - Includes request timeouts
10
+ - Includes request timeouts (for DNS and HTTP)
10
11
  - Avoids redirects
11
12
  - Allows only text/html responses
12
13
  - Returns only known OG properties and nothing else
data/examples/fetch.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'open_graph_fetcher'
2
+
3
+ url = "https://ogp.me"
4
+ fetcher = OpenGraphFetcher::Fetcher.new(url)
5
+ og_data = fetcher.fetch
6
+ puts og_data
@@ -3,6 +3,7 @@ module OpenGraphFetcher
3
3
 
4
4
  class InvalidSchemeError < Error; end
5
5
  class InvalidPortError < Error; end
6
+ class InvalidHostError < Error; end
6
7
  class IPResolutionError < Error; end
7
8
  class PrivateIPError < Error; end
8
9
  class FetchError < Error; end
@@ -7,6 +7,7 @@ module OpenGraphFetcher
7
7
  class Fetcher
8
8
  OG_PROPERTIES = %w[title type image url description].freeze
9
9
 
10
+ DNS_TIMEOUT = 3
10
11
  OPEN_TIMEOUT = 3
11
12
  READ_TIMEOUT = 3
12
13
 
@@ -22,6 +23,7 @@ module OpenGraphFetcher
22
23
  uri = URI.parse(@url)
23
24
  raise InvalidSchemeError, "Only HTTPS URLs are allowed" unless uri.scheme == "https"
24
25
  raise InvalidPortError, "Only the default HTTPS port (443) is allowed" if uri.port && uri.port != 443
26
+ raise InvalidHostError, "Using an IP as host is not allowed" if ip_address?(uri.hostname)
25
27
 
26
28
  ip_address = resolve_ip(uri)
27
29
  raise PrivateIPError, "Resolved IP address is in a private or reserved range" if private_ip?(ip_address)
@@ -36,10 +38,17 @@ module OpenGraphFetcher
36
38
  private
37
39
 
38
40
  def resolve_ip(uri)
39
- Resolv.getaddress(uri.host)
41
+ Resolv::DNS.open do |dns|
42
+ dns.timeouts = DNS_TIMEOUT
43
+ dns.getaddress(uri.hostname).to_s
44
+ end
40
45
  rescue Resolv::ResolvError => e
41
46
  raise IPResolutionError, "Could not resolve IP: #{e.message}"
42
47
  end
48
+
49
+ def ip_address?(host)
50
+ host =~ Resolv::IPv4::Regex || host =~ Resolv::IPv6::Regex
51
+ end
43
52
 
44
53
  def private_ip?(ip)
45
54
  ip_addr = IPAddr.new(ip)
@@ -1,3 +1,3 @@
1
1
  module OpenGraphFetcher
2
- VERSION = '0.1.0'.freeze
2
+ VERSION = '0.2.0'.freeze
3
3
  end
data/spec/fetcher_spec.rb CHANGED
@@ -4,7 +4,7 @@ require 'webmock/rspec'
4
4
  RSpec.describe OpenGraphFetcher::Fetcher do
5
5
 
6
6
  before do
7
- allow(Resolv).to receive(:getaddress).and_return("203.0.113.0")
7
+ allow(Resolv::DNS).to receive(:open).and_return("203.0.113.0")
8
8
  end
9
9
 
10
10
  describe ".fetch" do
@@ -51,20 +51,26 @@ RSpec.describe OpenGraphFetcher::Fetcher do
51
51
  expect { OpenGraphFetcher::Fetcher.fetch("https://example.com:8443") }.to raise_error(OpenGraphFetcher::InvalidPortError)
52
52
  end
53
53
  end
54
+
55
+ context "when given a URL with an IP address" do
56
+ it "raises an InvalidHostError" do
57
+ expect { OpenGraphFetcher::Fetcher.fetch("https://203.0.113.0/test") }.to raise_error(OpenGraphFetcher::InvalidHostError)
58
+ end
59
+ end
54
60
 
55
61
  context "when the IP address cannot be resolved" do
56
62
  it "raises an IPResolutionError with an appropriate error message" do
57
- allow(Resolv).to receive(:getaddress).and_raise(Resolv::ResolvError, "DNS resolution failed")
63
+ allow(Resolv::DNS).to receive(:open).and_raise(Resolv::ResolvError, "DNS resolution failed")
58
64
 
59
- expect { OpenGraphFetcher::Fetcher.fetch("https://nonexistent-domain.com") }.to raise_error(OpenGraphFetcher::IPResolutionError, /Could not resolve IP: DNS resolution failed/)
65
+ expect { OpenGraphFetcher::Fetcher.fetch("https://nonexistent.example.com") }.to raise_error(OpenGraphFetcher::IPResolutionError, /Could not resolve IP: DNS resolution failed/)
60
66
  end
61
67
  end
62
68
 
63
69
  context "when the resolved IP address is private" do
64
70
  it "raises a PrivateIPError" do
65
- allow(Resolv).to receive(:getaddress).with("10.0.0.1").and_return("10.0.0.1")
71
+ allow(Resolv::DNS).to receive(:open).and_return("10.0.0.1")
66
72
 
67
- expect { OpenGraphFetcher::Fetcher.fetch("https://10.0.0.1") }.to raise_error(OpenGraphFetcher::PrivateIPError)
73
+ expect { OpenGraphFetcher::Fetcher.fetch("https://ssrf.example.com") }.to raise_error(OpenGraphFetcher::PrivateIPError)
68
74
  end
69
75
  end
70
76
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: open_graph_fetcher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marco Colli
@@ -63,6 +63,7 @@ files:
63
63
  - Gemfile
64
64
  - LICENSE
65
65
  - README.md
66
+ - examples/fetch.rb
66
67
  - lib/open_graph_fetcher.rb
67
68
  - lib/open_graph_fetcher/errors.rb
68
69
  - lib/open_graph_fetcher/fetcher.rb