From 0b6a776f2718154a3cdaa2584a4b1b0057e9482b Mon Sep 17 00:00:00 2001 From: Jeremy Daer Date: Mon, 20 Jul 2026 02:18:38 -0700 Subject: [PATCH] Block NAT64 and 6to4 IPv6 encapsulation ranges in SSRF protection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DISALLOWED_IP_RANGES covered the NAT64 well-known prefix (RFC6052, 64:ff9b::/96) and 6to4 (RFC3056, 2002::/16) — both encapsulate IPv4 destinations and can be used to smuggle otherwise-blocked targets past SSRF filtering. Add both ranges and cover them with blocked_address? assertions plus a public control. Weekend run #3873122. --- app/models/ssrf_protection.rb | 4 +++- test/models/ssrf_protection_test.rb | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/app/models/ssrf_protection.rb b/app/models/ssrf_protection.rb index 40be7d1573..5d95be74b1 100644 --- a/app/models/ssrf_protection.rb +++ b/app/models/ssrf_protection.rb @@ -11,7 +11,9 @@ module SsrfProtection DISALLOWED_IP_RANGES = [ IPAddr.new("0.0.0.0/8"), # "This" network (RFC1700) IPAddr.new("100.64.0.0/10"), # Carrier-grade NAT (RFC6598) - IPAddr.new("198.18.0.0/15") # Benchmark testing (RFC2544) + IPAddr.new("198.18.0.0/15"), # Benchmark testing (RFC2544) + IPAddr.new("64:ff9b::/96"), # NAT64 well-known prefix (RFC6052) + IPAddr.new("2002::/16") # 6to4 (RFC3056) ].freeze def resolve_public_ip(hostname) diff --git a/test/models/ssrf_protection_test.rb b/test/models/ssrf_protection_test.rb index fc2828b60f..d4057a9156 100644 --- a/test/models/ssrf_protection_test.rb +++ b/test/models/ssrf_protection_test.rb @@ -82,4 +82,18 @@ class SsrfProtectionTest < ActiveSupport::TestCase stub_dns_resolution("::93.184.216.34") assert_nil SsrfProtection.resolve_public_ip("compat-public.example.com") end + + # IPv6 encapsulation ranges (SSRF bypass prevention) + + test "blocks NAT64 well-known prefix addresses" do + assert SsrfProtection.blocked_address?("64:ff9b::a00:1") + end + + test "blocks 6to4 addresses" do + assert SsrfProtection.blocked_address?("2002::1") + end + + test "allows public addresses through blocked_address?" do + assert_not SsrfProtection.blocked_address?("93.184.216.34") + end end