require 'ipaddr'
require 'resolv'
uri = URI.parse(params[:url])
allowed_hosts = %w[images.example-cdn.com api.partner.com]
raise ActionController::BadRequest, 'invalid scheme' unless %w[https].include?(uri.scheme)
raise ActionController::BadRequest, 'host not allowed' unless allowed_hosts.include?(uri.host)
addresses = Resolv.getaddresses(uri.host).map { |address| IPAddr.new(address) }
forbidden_ranges = [
IPAddr.new('127.0.0.0/8'),
IPAddr.new('10.0.0.0/8'),
IPAddr.new('172.16.0.0/12'),
IPAddr.new('192.168.0.0/16'),
]
if addresses.any? { |address| forbidden_ranges.any? { |range| range.include?(address) } }
raise ActionController::BadRequest, 'resolved to forbidden network'
end
SSRF defense requires more than banning localhost. I parse URLs with a real library, enforce scheme and host allowlists, resolve and reject private IP ranges, and pair app-level checks with network egress rules. If an attacker can turn your server into a proxy, they will eventually find something sensitive behind it.