From e67b316977c0e93e7feebd1193da3a13b1f2559f Mon Sep 17 00:00:00 2001 From: Ryan Lovelett Date: Sat, 19 Mar 2011 00:09:33 -0500 Subject: [PATCH 1/2] Prevents RFC 1918 IPv4 addresses from being input. Also, prevents 127.0.0.1 and 0.0.0.0 --- init.rb | 17 +++++++++++++++++ test/validates_url_format_of_test.rb | 13 +++++++++++++ 2 files changed, 30 insertions(+) diff --git a/init.rb b/init.rb index 49804da..986526c 100644 --- a/init.rb +++ b/init.rb @@ -2,6 +2,21 @@ module ValidatesUrlFormatOf IPv4_PART = /\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]/ # 0-255 + # http://en.wikipedia.org/wiki/IP_address + # http://en.wikipedia.org/wiki/Default_route + # http://en.wikipedia.org/wiki/Localhost + + # Blocks IPv4 10.0.0.0 - 10.255.255.255 + TWENTY_FOUR_BIT_BLOCK = /(?!10\.((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.?)){3})/ + # Blocks IPv4 172.16.0.0 - 172.31.255.255 + TWENTY_BIT_BLOCK = /(?!172\.(0?3[0-1]|0?2[0-9]|0?1[6-9])\.((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.?)){2})/ + # Blocks IPv4 192.168.0.0 - 192.168.255.255 + SIXTEEN_BIT_BLOCK = /(?!192\.168\.((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.?)){2})/ + # Blocks IPv4 127.0.0.1 (which is also localhost) + LOCALHOST_LOOPBACK = /(?!127\.0\.0\.[0-8])/ + ALL_ROUTES = /(?!0\.0\.0\.0)/ + RFC_1918_IPS = %r{#{TWENTY_FOUR_BIT_BLOCK}#{TWENTY_BIT_BLOCK}#{SIXTEEN_BIT_BLOCK}#{LOCALHOST_LOOPBACK}#{ALL_ROUTES}} + # First regexp doesn't work in Ruby 1.8 and second has a bug in 1.9.2: # https://github.com/henrik/validates_url_format_of/issues/issue/4/#comment_760674 ALNUM = "รค".match(/[[:alnum:]]/) ? /[[:alnum:]]/ : /[^\W_]/ @@ -9,6 +24,7 @@ module ValidatesUrlFormatOf REGEXP = %r{ \A https?:// # http:// or https:// + #{RFC_1918_IPS} # blocks the use of RFC 1918 private network IPv4 addresses, also blocks 127.0.0.0/8 and 0.0.0.0 ([^\s:@]+:[^\s:@]*@)? # optional username:pw@ ( ((#{ALNUM}+\.)*xn--)?#{ALNUM}+([-.]#{ALNUM}+)*\.[a-z]{2,6}\.? | # domain (including Punycode/IDN)... #{IPv4_PART}(\.#{IPv4_PART}){3} ) # or IPv4 @@ -20,6 +36,7 @@ module ValidatesUrlFormatOf DEFAULT_MESSAGE = 'does not appear to be a valid URL' DEFAULT_MESSAGE_URL = 'does not appear to be valid' + def validates_url_format_of(*attr_names) options = { :allow_nil => false, :allow_blank => false, diff --git a/test/validates_url_format_of_test.rb b/test/validates_url_format_of_test.rb index 8f3d723..7d2ea11 100644 --- a/test/validates_url_format_of_test.rb +++ b/test/validates_url_format_of_test.rb @@ -101,6 +101,19 @@ def test_should_reject_invalid_urls end end + def test_require_publicly_routeable_ip4_addresses + private_ips_10 = 100.times.map { "http://10.#{Random.new.rand(0..255)}.#{Random.new.rand(0..255)}.#{Random.new.rand(0..255)}" } + private_ips_172 = 100.times.map { "http://172.#{Random.new.rand(16..31)}.#{Random.new.rand(0..255)}.#{Random.new.rand(0..255)}" } + private_ips_192 = 100.times.map { "http://192.168.#{Random.new.rand(0..255)}.#{Random.new.rand(0..255)}" } + reserved_ips = (private_ips_10 << private_ips_172 << private_ips_192 << "http://0.0.0.0" << "http://127.0.0.1").flatten + reserved_ips.each do |url| + @model.homepage = url + @model.valid? + assert !@model.errors[:homepage].empty?, "#{url.inspect} should have been rejected" + end + + end + def test_different_defaults_based_on_attribute_name @model.homepage = 'x' @model.my_UrL_hooray = 'x' From b04a0221f799c0a7ace511c831ac5378c79b3574 Mon Sep 17 00:00:00 2001 From: Ryan Lovelett Date: Sat, 19 Mar 2011 00:25:04 -0500 Subject: [PATCH 2/2] Seperates the matchers for RFC 1918 and localhost --- init.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/init.rb b/init.rb index 986526c..fa3bf5f 100644 --- a/init.rb +++ b/init.rb @@ -15,7 +15,7 @@ module ValidatesUrlFormatOf # Blocks IPv4 127.0.0.1 (which is also localhost) LOCALHOST_LOOPBACK = /(?!127\.0\.0\.[0-8])/ ALL_ROUTES = /(?!0\.0\.0\.0)/ - RFC_1918_IPS = %r{#{TWENTY_FOUR_BIT_BLOCK}#{TWENTY_BIT_BLOCK}#{SIXTEEN_BIT_BLOCK}#{LOCALHOST_LOOPBACK}#{ALL_ROUTES}} + RFC_1918_IPS = %r{#{TWENTY_FOUR_BIT_BLOCK}#{TWENTY_BIT_BLOCK}#{SIXTEEN_BIT_BLOCK}} # First regexp doesn't work in Ruby 1.8 and second has a bug in 1.9.2: # https://github.com/henrik/validates_url_format_of/issues/issue/4/#comment_760674 @@ -24,7 +24,9 @@ module ValidatesUrlFormatOf REGEXP = %r{ \A https?:// # http:// or https:// - #{RFC_1918_IPS} # blocks the use of RFC 1918 private network IPv4 addresses, also blocks 127.0.0.0/8 and 0.0.0.0 + #{LOCALHOST_LOOPBACK} # blocks 127.0.0.0/8 + #{ALL_ROUTES} # blocks 0.0.0.0 + #{RFC_1918_IPS} # blocks the use of RFC 1918 private network IPv4 addresses ([^\s:@]+:[^\s:@]*@)? # optional username:pw@ ( ((#{ALNUM}+\.)*xn--)?#{ALNUM}+([-.]#{ALNUM}+)*\.[a-z]{2,6}\.? | # domain (including Punycode/IDN)... #{IPv4_PART}(\.#{IPv4_PART}){3} ) # or IPv4