private_address_check 0.7.0 → 0.8.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: 7b4f39e178d7ce144d60df00537f65b9a506037a6fb15aaae625ac156ec6a23b
4
- data.tar.gz: dc61b3d2e5a3cde94d4801f8ac746a9761a0501280e109ffbe535d4057db22a6
3
+ metadata.gz: ca4c176629d7fe2c0be2be0f113d51e0a03449cbf4c564387b7950f4500994a3
4
+ data.tar.gz: 1ca594143b83be4ebba2a0a5825b79bf81dfae0b015adbb5994d637a227d9c02
5
5
  SHA512:
6
- metadata.gz: 18cd0a4e01f064df93b47ff721e3deee8337c19ea829c4c8d38aea23a5e0e342be261e1728dca6bd01824e4b9073f59c2a175c7f4745635411f5c860b08e0d02
7
- data.tar.gz: 8e4b63a2986997385b4b4261d92d50da3044455648f7f06e1f8306b4a69b7d6628dde55c30b7923d53a14bc7b98eff243725bda571cb41c902cd72a87bf24f86
6
+ metadata.gz: 95e99d25ee1a57352a61be412cae4505f968e958515e9ffa1fb79688f30a2e6c966cc61971111af1636e4abd7055fc3b2168c48d2c55311e77c1eaa7e99cc3a3
7
+ data.tar.gz: ad87ec9e56d459434ad6b9602807d67414bfa79fe9f6cddbab73a6158f3f95b837e6e16cb100c09e4ad87afbfa7119c4e6afbf825910fed98bd274a1d8367d88
@@ -1,3 +1,3 @@
1
1
  module PrivateAddressCheck
2
- VERSION = "0.7.0".freeze
2
+ VERSION = "0.8.0".freeze
3
3
  end
@@ -7,10 +7,8 @@ module PrivateAddressCheck
7
7
  module_function
8
8
 
9
9
  # https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
10
- # https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
11
- CIDR_LIST = [
10
+ IPV4_CIDRS = [
12
11
  IPAddr.new("127.0.0.0/8"), # Loopback
13
- IPAddr.new("::1/128"), # Loopback
14
12
  IPAddr.new("0.0.0.0/8"), # Current network (only valid as source address)
15
13
  IPAddr.new("169.254.0.0/16"), # Link-local
16
14
  IPAddr.new("10.0.0.0/8"), # Private network
@@ -18,26 +16,52 @@ module PrivateAddressCheck
18
16
  IPAddr.new("172.16.0.0/12"), # Private network
19
17
  IPAddr.new("192.0.0.0/24"), # IETF Protocol Assignments
20
18
  IPAddr.new("192.0.2.0/24"), # TEST-NET-1, documentation and examples
21
- IPAddr.new("192.88.99.0/24"), # IPv6 to IPv4 relay (includes 2002::/16)
19
+ IPAddr.new("192.88.99.0/24"), # IPv6 to IPv4 relay anycast (RFC 7526, deprecated)
22
20
  IPAddr.new("192.168.0.0/16"), # Private network
23
21
  IPAddr.new("198.18.0.0/15"), # Network benchmark tests
24
22
  IPAddr.new("198.51.100.0/24"), # TEST-NET-2, documentation and examples
25
23
  IPAddr.new("203.0.113.0/24"), # TEST-NET-3, documentation and examples
26
24
  IPAddr.new("224.0.0.0/4"), # IP multicast (former Class D network)
27
- IPAddr.new("240.0.0.0/4"), # Reserved (former Class E network)
28
- IPAddr.new("255.255.255.255"), # Broadcast
29
- IPAddr.new("64:ff9b::/96"), # IPv4/IPv6 translation (RFC 6052)
25
+ IPAddr.new("240.0.0.0/4") # Reserved (former Class E network, covers 255.255.255.255)
26
+ ].freeze
27
+
28
+ # https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
29
+ IPV6_CIDRS = [
30
+ IPAddr.new("::/128"), # Unspecified address (RFC 4291)
31
+ IPAddr.new("::1/128"), # Loopback
32
+ IPAddr.new("64:ff9b:1::/48"), # IPv4/IPv6 translation, local use (RFC 8215)
30
33
  IPAddr.new("100::/64"), # Discard prefix (RFC 6666)
34
+ IPAddr.new("100:0:0:1::/64"), # Dummy IPv6 Prefix (RFC 9780)
31
35
  IPAddr.new("2001::/32"), # Teredo tunneling
36
+ IPAddr.new("2001:2::/48"), # Benchmarking (RFC 5180)
32
37
  IPAddr.new("2001:10::/28"), # Deprecated (previously ORCHID)
33
38
  IPAddr.new("2001:20::/28"), # ORCHIDv2
34
39
  IPAddr.new("2001:db8::/32"), # Addresses used in documentation and example source code
35
- IPAddr.new("2002::/16"), # 6to4
40
+ IPAddr.new("3fff::/20"), # Documentation (RFC 9637)
41
+ IPAddr.new("5f00::/16"), # Segment Routing (SRv6) SIDs (RFC 9602)
36
42
  IPAddr.new("fc00::/7"), # Unique local address
37
43
  IPAddr.new("fe80::/10"), # Link-local address
38
44
  IPAddr.new("ff00::/8") # Multicast
39
45
  ].freeze
40
46
 
47
+ # Embedded IPv4 representations in IPv6, generated from IPV4_CIDRS so that
48
+ # addresses like ::ffff:10.0.0.1 cannot bypass the private-address check.
49
+ IPV4_MAPPED_CIDRS = IPV4_CIDRS.flat_map do |cidr|
50
+ prefix = cidr.prefix + 96
51
+ ip = cidr.to_s
52
+ octets = ip.split(".").map(&:to_i)
53
+ v4_hex = format("%<high>04x:%<low>04x", high: (octets[0] << 8) | octets[1], low: (octets[2] << 8) | octets[3])
54
+ [
55
+ IPAddr.new("::#{ip}/#{prefix}"), # IPv4-compatible (deprecated)
56
+ IPAddr.new("::ffff:#{ip}/#{prefix}"), # IPv4-mapped (RFC 4291)
57
+ IPAddr.new("::ffff:0:#{ip}/#{prefix}"), # IPv4-translated (RFC 2765)
58
+ IPAddr.new("64:ff9b::#{ip}/#{prefix}"), # NAT64 well-known prefix (RFC 6052)
59
+ IPAddr.new("2002:#{v4_hex}::/#{cidr.prefix + 16}") # 6to4 (RFC 3056)
60
+ ]
61
+ end.freeze
62
+
63
+ CIDR_LIST = (IPV4_CIDRS + IPV6_CIDRS + IPV4_MAPPED_CIDRS).freeze
64
+
41
65
  def private_address?(address)
42
66
  CIDR_LIST.any? do |cidr|
43
67
  cidr.include?(address)
@@ -27,6 +27,56 @@ class PrivateAddressCheckTest < Minitest::Test
27
27
  assert PrivateAddressCheck.private_address?("169.254.2.5")
28
28
  end
29
29
 
30
+ def test_private_address_for_unspecified_ipv6
31
+ assert PrivateAddressCheck.private_address?("::")
32
+ end
33
+
34
+ def test_private_address_for_additional_ipv6_special_ranges
35
+ assert PrivateAddressCheck.private_address?("64:ff9b:1::1")
36
+ assert PrivateAddressCheck.private_address?("2001:2::1")
37
+ assert PrivateAddressCheck.private_address?("3fff::1")
38
+ end
39
+
40
+ def test_private_address_for_dummy_ipv6_prefix
41
+ assert PrivateAddressCheck.private_address?("100:0:0:1::1")
42
+ end
43
+
44
+ def test_private_address_for_srv6_sid_range
45
+ assert PrivateAddressCheck.private_address?("5f00::1")
46
+ end
47
+
48
+ def test_private_address_for_ipv4_mapped_ipv6_addresses
49
+ assert PrivateAddressCheck.private_address?("::ffff:127.0.0.1")
50
+ assert PrivateAddressCheck.private_address?("::ffff:10.0.0.1")
51
+ assert PrivateAddressCheck.private_address?("::ffff:169.254.169.254")
52
+ end
53
+
54
+ def test_private_address_for_alternate_ipv4_embeddings
55
+ assert PrivateAddressCheck.private_address?("::127.0.0.1")
56
+ assert PrivateAddressCheck.private_address?("::ffff:0:127.0.0.1")
57
+ assert PrivateAddressCheck.private_address?("64:ff9b::127.0.0.1")
58
+ end
59
+
60
+ def test_public_ipv4_mapped_ipv6_addresses_are_not_private
61
+ refute PrivateAddressCheck.private_address?("::ffff:8.8.8.8")
62
+ refute PrivateAddressCheck.private_address?("::ffff:1.1.1.1")
63
+ end
64
+
65
+ def test_public_nat64_and_6to4_addresses_are_not_private
66
+ refute PrivateAddressCheck.private_address?("64:ff9b::8.8.8.8")
67
+ refute PrivateAddressCheck.private_address?("2002:808:808::1")
68
+ end
69
+
70
+ def test_private_nat64_addresses_are_still_private
71
+ assert PrivateAddressCheck.private_address?("64:ff9b::10.0.0.1")
72
+ end
73
+
74
+ def test_private_6to4_addresses_are_private
75
+ assert PrivateAddressCheck.private_address?("2002:0a00:0001::1")
76
+ assert PrivateAddressCheck.private_address?("2002:7f00:0001::1")
77
+ assert PrivateAddressCheck.private_address?("2002:a9fe:a9fe::1")
78
+ end
79
+
30
80
  def test_private_hostname_for_public_addresses
31
81
  refute PrivateAddressCheck.resolves_to_private_address?("github.com")
32
82
  refute PrivateAddressCheck.resolves_to_private_address?("example.com")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: private_address_check
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Downey
@@ -46,7 +46,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  requirements: []
49
- rubygems_version: 4.0.6
49
+ rubygems_version: 4.0.10
50
50
  specification_version: 4
51
51
  summary: Prevent Server Side Request Forgery attacks by checking the destination
52
52
  test_files: []