Merge pull request #122 from basecamp/unfurl-blind-ssrf

Security: disallow blind SSRF to link-local IPs via URL unfurling
This commit is contained in:
Stanko Krtalić
2025-12-03 08:12:24 +01:00
committed by GitHub
2 changed files with 23 additions and 1 deletions

View File

@@ -16,7 +16,7 @@ module RestrictedHTTP
def private_ip?(ip)
IPAddr.new(ip).then do |ipaddr|
ipaddr.private? || ipaddr.loopback? || LOCAL_IP.include?(ipaddr)
ipaddr.private? || ipaddr.loopback? || ipaddr.link_local? || ipaddr.ipv4_mapped? || LOCAL_IP.include?(ipaddr)
end
rescue IPAddr::InvalidAddressError
true

View File

@@ -21,6 +21,28 @@ class Opengraph::LocationTest < ActiveSupport::TestCase
assert_equal [ "is not public" ], location.errors[:url]
end
test "link-local addresses are blocked" do
Resolv.stubs(:getaddress).with("metadata.internal").returns("169.254.169.254")
location = Opengraph::Location.new("https://metadata.internal")
assert_not location.valid?
assert_equal [ "is not public" ], location.errors[:url]
end
test "IPv6 addresses mapped to IPv4 addresses are blocked" do
Resolv.stubs(:getaddress).with("metadata.internal").returns("::ffff:192.168.1.1")
location = Opengraph::Location.new("https://metadata.internal")
assert_not location.valid?
assert_equal [ "is not public" ], location.errors[:url]
Resolv.stubs(:getaddress).with("metadata.internal").returns("::ffff:c0a8:0101")
location = Opengraph::Location.new("https://metadata.internal")
assert_not location.valid?
assert_equal [ "is not public" ], location.errors[:url]
end
test "avoid reading file urls when expecting HTML" do
large_file = Opengraph::Location.new("https://www.example.com/100gb.zip")